Commit 3f2dc806 by Andrew Stubbs Committed by Ulrich Weigand

arm.c (arm_emit_coreregs_64bit_shift): Fix comment.

2012-11-13  Andrew Stubbs  <ams@codesourcery.com>
            Ulrich Weigand  <ulrich.weigand@linaro.org>

	* config/arm/arm.c (arm_emit_coreregs_64bit_shift): Fix comment.
	* config/arm/arm.md (opt, opt_enabled): New attributes.
	(enabled): Use opt_enabled.
	(ashldi3, ashrdi3, lshrdi3): Add TARGET_NEON case.
	(ashldi3): Allow general operands for TARGET_NEON case.
	* config/arm/iterators.md (rshifts): New code iterator.
	(shift, shifttype): New code attributes.
	* config/arm/neon.md (UNSPEC_LOAD_COUNT): New unspec type.
	(neon_load_count, ashldi3_neon_noclobber, ashldi3_neon,
	signed_shift_di3_neon, unsigned_shift_di3_neon,
	ashrdi3_neon_imm_noclobber, lshrdi3_neon_imm_noclobber,
	<shift>di3_neon): New patterns.

Co-Authored-By: Ulrich Weigand <ulrich.weigand@linaro.org>

From-SVN: r193476
parent 2b12109c
2012-11-13 Andrew Stubbs <ams@codesourcery.com>
Ulrich Weigand <ulrich.weigand@linaro.org>
* config/arm/arm.c (arm_emit_coreregs_64bit_shift): Fix comment.
* config/arm/arm.md (opt, opt_enabled): New attributes.
(enabled): Use opt_enabled.
(ashldi3, ashrdi3, lshrdi3): Add TARGET_NEON case.
(ashldi3): Allow general operands for TARGET_NEON case.
* config/arm/iterators.md (rshifts): New code iterator.
(shift, shifttype): New code attributes.
* config/arm/neon.md (UNSPEC_LOAD_COUNT): New unspec type.
(neon_load_count, ashldi3_neon_noclobber, ashldi3_neon,
signed_shift_di3_neon, unsigned_shift_di3_neon,
ashrdi3_neon_imm_noclobber, lshrdi3_neon_imm_noclobber,
<shift>di3_neon): New patterns.
2012-11-13 Jakub Jelinek <jakub@redhat.com> 2012-11-13 Jakub Jelinek <jakub@redhat.com>
* Makefile.in (asan.o): Depend on $(TM_P_H). * Makefile.in (asan.o): Depend on $(TM_P_H).
...@@ -26635,8 +26635,7 @@ arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code) ...@@ -26635,8 +26635,7 @@ arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code)
Input requirements: Input requirements:
- It is safe for the input and output to be the same register, but - It is safe for the input and output to be the same register, but
early-clobber rules apply for the shift amount and scratch registers. early-clobber rules apply for the shift amount and scratch registers.
- Shift by register requires both scratch registers. Shift by a constant - Shift by register requires both scratch registers. In all other cases
less than 32 in Thumb2 mode requires SCRATCH1 only. In all other cases
the scratch registers may be NULL. the scratch registers may be NULL.
- Ashiftrt by a register also clobbers the CC register. */ - Ashiftrt by a register also clobbers the CC register. */
void void
......
...@@ -249,6 +249,22 @@ ...@@ -249,6 +249,22 @@
(const_string "no"))) (const_string "no")))
(define_attr "opt" "any,speed,size"
(const_string "any"))
(define_attr "opt_enabled" "no,yes"
(cond [(eq_attr "opt" "any")
(const_string "yes")
(and (eq_attr "opt" "speed")
(match_test "optimize_function_for_speed_p (cfun)"))
(const_string "yes")
(and (eq_attr "opt" "size")
(match_test "optimize_function_for_size_p (cfun)"))
(const_string "yes")]
(const_string "no")))
; Allows an insn to disable certain alternatives for reasons other than ; Allows an insn to disable certain alternatives for reasons other than
; arch support. ; arch support.
(define_attr "insn_enabled" "no,yes" (define_attr "insn_enabled" "no,yes"
...@@ -256,11 +272,15 @@ ...@@ -256,11 +272,15 @@
; Enable all alternatives that are both arch_enabled and insn_enabled. ; Enable all alternatives that are both arch_enabled and insn_enabled.
(define_attr "enabled" "no,yes" (define_attr "enabled" "no,yes"
(if_then_else (eq_attr "insn_enabled" "yes") (cond [(eq_attr "insn_enabled" "no")
(if_then_else (eq_attr "arch_enabled" "yes") (const_string "no")
(const_string "yes")
(const_string "no")) (eq_attr "arch_enabled" "no")
(const_string "no"))) (const_string "no")
(eq_attr "opt_enabled" "no")
(const_string "no")]
(const_string "yes")))
; POOL_RANGE is how far away from a constant pool entry that this insn ; POOL_RANGE is how far away from a constant pool entry that this insn
; can be placed. If the distance is zero, then this insn will never ; can be placed. If the distance is zero, then this insn will never
...@@ -3489,9 +3509,23 @@ ...@@ -3489,9 +3509,23 @@
(define_expand "ashldi3" (define_expand "ashldi3"
[(set (match_operand:DI 0 "s_register_operand" "") [(set (match_operand:DI 0 "s_register_operand" "")
(ashift:DI (match_operand:DI 1 "s_register_operand" "") (ashift:DI (match_operand:DI 1 "s_register_operand" "")
(match_operand:SI 2 "reg_or_int_operand" "")))] (match_operand:SI 2 "general_operand" "")))]
"TARGET_32BIT" "TARGET_32BIT"
" "
if (TARGET_NEON)
{
/* Delay the decision whether to use NEON or core-regs until
register allocation. */
emit_insn (gen_ashldi3_neon (operands[0], operands[1], operands[2]));
DONE;
}
else
{
/* Only the NEON case can handle in-memory shift counts. */
if (!reg_or_int_operand (operands[2], SImode))
operands[2] = force_reg (SImode, operands[2]);
}
if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT) if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
; /* No special preparation statements; expand pattern as above. */ ; /* No special preparation statements; expand pattern as above. */
else else
...@@ -3566,6 +3600,14 @@ ...@@ -3566,6 +3600,14 @@
(match_operand:SI 2 "reg_or_int_operand" "")))] (match_operand:SI 2 "reg_or_int_operand" "")))]
"TARGET_32BIT" "TARGET_32BIT"
" "
if (TARGET_NEON)
{
/* Delay the decision whether to use NEON or core-regs until
register allocation. */
emit_insn (gen_ashrdi3_neon (operands[0], operands[1], operands[2]));
DONE;
}
if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT) if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
; /* No special preparation statements; expand pattern as above. */ ; /* No special preparation statements; expand pattern as above. */
else else
...@@ -3638,6 +3680,14 @@ ...@@ -3638,6 +3680,14 @@
(match_operand:SI 2 "reg_or_int_operand" "")))] (match_operand:SI 2 "reg_or_int_operand" "")))]
"TARGET_32BIT" "TARGET_32BIT"
" "
if (TARGET_NEON)
{
/* Delay the decision whether to use NEON or core-regs until
register allocation. */
emit_insn (gen_lshrdi3_neon (operands[0], operands[1], operands[2]));
DONE;
}
if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT) if (!CONST_INT_P (operands[2]) && TARGET_REALLY_IWMMXT)
; /* No special preparation statements; expand pattern as above. */ ; /* No special preparation statements; expand pattern as above. */
else else
......
...@@ -188,6 +188,9 @@ ...@@ -188,6 +188,9 @@
;; A list of widening operators ;; A list of widening operators
(define_code_iterator SE [sign_extend zero_extend]) (define_code_iterator SE [sign_extend zero_extend])
;; Right shifts
(define_code_iterator rshifts [ashiftrt lshiftrt])
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
;; Mode attributes ;; Mode attributes
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
...@@ -449,3 +452,8 @@ ...@@ -449,3 +452,8 @@
;; Assembler mnemonics for signedness of widening operations. ;; Assembler mnemonics for signedness of widening operations.
(define_code_attr US [(sign_extend "s") (zero_extend "u")]) (define_code_attr US [(sign_extend "s") (zero_extend "u")])
;; Right shifts
(define_code_attr shift [(ashiftrt "ashr") (lshiftrt "lshr")])
(define_code_attr shifttype [(ashiftrt "signed") (lshiftrt "unsigned")])
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
(define_c_enum "unspec" [ (define_c_enum "unspec" [
UNSPEC_ASHIFT_SIGNED UNSPEC_ASHIFT_SIGNED
UNSPEC_ASHIFT_UNSIGNED UNSPEC_ASHIFT_UNSIGNED
UNSPEC_LOAD_COUNT
UNSPEC_VABD UNSPEC_VABD
UNSPEC_VABDL UNSPEC_VABDL
UNSPEC_VADD UNSPEC_VADD
...@@ -1200,6 +1201,189 @@ ...@@ -1200,6 +1201,189 @@
DONE; DONE;
}) })
;; 64-bit shifts
;; This pattern loads a 32-bit shift count into a 64-bit NEON register,
;; leaving the upper half uninitalized. This is OK since the shift
;; instruction only looks at the low 8 bits anyway. To avoid confusing
;; data flow analysis however, we pretend the full register is set
;; using an unspec.
(define_insn "neon_load_count"
[(set (match_operand:DI 0 "s_register_operand" "=w,w")
(unspec:DI [(match_operand:SI 1 "nonimmediate_operand" "Um,r")]
UNSPEC_LOAD_COUNT))]
"TARGET_NEON"
"@
vld1.32\t{%P0[0]}, %A1
vmov.32\t%P0[0], %1"
[(set_attr "neon_type" "neon_vld1_vld2_lane,neon_mcr")]
)
(define_insn "ashldi3_neon_noclobber"
[(set (match_operand:DI 0 "s_register_operand" "=w,w")
(ashift:DI (match_operand:DI 1 "s_register_operand" " w,w")
(match_operand:DI 2 "reg_or_int_operand" " i,w")))]
"TARGET_NEON && reload_completed
&& (!CONST_INT_P (operands[2])
|| (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 64))"
"@
vshl.u64\t%P0, %P1, %2
vshl.u64\t%P0, %P1, %P2"
[(set_attr "neon_type" "neon_vshl_ddd,neon_vshl_ddd")]
)
(define_insn_and_split "ashldi3_neon"
[(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r, ?w,w")
(ashift:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r, 0w,w")
(match_operand:SI 2 "general_operand" "rUm, i, r, i,rUm,i")))
(clobber (match_scratch:SI 3 "= X, X,?&r, X, X,X"))
(clobber (match_scratch:SI 4 "= X, X,?&r, X, X,X"))
(clobber (match_scratch:DI 5 "=&w, X, X, X, &w,X"))
(clobber (reg:CC_C CC_REGNUM))]
"TARGET_NEON"
"#"
"TARGET_NEON && reload_completed"
[(const_int 0)]
"
{
if (IS_VFP_REGNUM (REGNO (operands[0])))
{
if (CONST_INT_P (operands[2]))
{
if (INTVAL (operands[2]) < 1)
{
emit_insn (gen_movdi (operands[0], operands[1]));
DONE;
}
else if (INTVAL (operands[2]) > 63)
operands[2] = gen_rtx_CONST_INT (VOIDmode, 63);
}
else
{
emit_insn (gen_neon_load_count (operands[5], operands[2]));
operands[2] = operands[5];
}
/* Ditch the unnecessary clobbers. */
emit_insn (gen_ashldi3_neon_noclobber (operands[0], operands[1],
operands[2]));
}
else
{
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
/* This clobbers CC. */
emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
else
arm_emit_coreregs_64bit_shift (ASHIFT, operands[0], operands[1],
operands[2], operands[3], operands[4]);
}
DONE;
}"
[(set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")
(set_attr "opt" "*,*,speed,speed,*,*")]
)
; The shift amount needs to be negated for right-shifts
(define_insn "signed_shift_di3_neon"
[(set (match_operand:DI 0 "s_register_operand" "=w")
(unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
(match_operand:DI 2 "s_register_operand" " w")]
UNSPEC_ASHIFT_SIGNED))]
"TARGET_NEON && reload_completed"
"vshl.s64\t%P0, %P1, %P2"
[(set_attr "neon_type" "neon_vshl_ddd")]
)
; The shift amount needs to be negated for right-shifts
(define_insn "unsigned_shift_di3_neon"
[(set (match_operand:DI 0 "s_register_operand" "=w")
(unspec:DI [(match_operand:DI 1 "s_register_operand" " w")
(match_operand:DI 2 "s_register_operand" " w")]
UNSPEC_ASHIFT_UNSIGNED))]
"TARGET_NEON && reload_completed"
"vshl.u64\t%P0, %P1, %P2"
[(set_attr "neon_type" "neon_vshl_ddd")]
)
(define_insn "ashrdi3_neon_imm_noclobber"
[(set (match_operand:DI 0 "s_register_operand" "=w")
(ashiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
(match_operand:DI 2 "const_int_operand" " i")))]
"TARGET_NEON && reload_completed
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
"vshr.s64\t%P0, %P1, %2"
[(set_attr "neon_type" "neon_vshl_ddd")]
)
(define_insn "lshrdi3_neon_imm_noclobber"
[(set (match_operand:DI 0 "s_register_operand" "=w")
(lshiftrt:DI (match_operand:DI 1 "s_register_operand" " w")
(match_operand:DI 2 "const_int_operand" " i")))]
"TARGET_NEON && reload_completed
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 64"
"vshr.u64\t%P0, %P1, %2"
[(set_attr "neon_type" "neon_vshl_ddd")]
)
;; ashrdi3_neon
;; lshrdi3_neon
(define_insn_and_split "<shift>di3_neon"
[(set (match_operand:DI 0 "s_register_operand" "= w, w,?&r,?r,?w,?w")
(rshifts:DI (match_operand:DI 1 "s_register_operand" " 0w, w, 0r, r,0w, w")
(match_operand:SI 2 "reg_or_int_operand" " r, i, r, i, r, i")))
(clobber (match_scratch:SI 3 "=2r, X, &r, X,2r, X"))
(clobber (match_scratch:SI 4 "= X, X, &r, X, X, X"))
(clobber (match_scratch:DI 5 "=&w, X, X, X,&w, X"))
(clobber (reg:CC CC_REGNUM))]
"TARGET_NEON"
"#"
"TARGET_NEON && reload_completed"
[(const_int 0)]
"
{
if (IS_VFP_REGNUM (REGNO (operands[0])))
{
if (CONST_INT_P (operands[2]))
{
if (INTVAL (operands[2]) < 1)
{
emit_insn (gen_movdi (operands[0], operands[1]));
DONE;
}
else if (INTVAL (operands[2]) > 64)
operands[2] = gen_rtx_CONST_INT (VOIDmode, 64);
/* Ditch the unnecessary clobbers. */
emit_insn (gen_<shift>di3_neon_imm_noclobber (operands[0],
operands[1],
operands[2]));
}
else
{
/* We must use a negative left-shift. */
emit_insn (gen_negsi2 (operands[3], operands[2]));
emit_insn (gen_neon_load_count (operands[5], operands[3]));
emit_insn (gen_<shifttype>_shift_di3_neon (operands[0], operands[1],
operands[5]));
}
}
else
{
if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) == 1)
/* This clobbers CC. */
emit_insn (gen_arm_<shift>di3_1bit (operands[0], operands[1]));
else
/* This clobbers CC (ASHIFTRT by register only). */
arm_emit_coreregs_64bit_shift (<CODE>, operands[0], operands[1],
operands[2], operands[3], operands[4]);
}
DONE;
}"
[(set_attr "arch" "nota8,nota8,*,*,onlya8,onlya8")
(set_attr "opt" "*,*,speed,speed,*,*")]
)
;; Widening operations ;; Widening operations
(define_insn "widen_ssum<mode>3" (define_insn "widen_ssum<mode>3"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment