http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50814
--- Comment #1 from Kazumoto Kojima <kkojima at gcc dot gnu.org> 2011-10-21 00:24:36 UTC --- (In reply to comment #0) > It is also not clear to me why SH2A seems to require different handling for > dynamic shifts than SH3 or SH4... Will be slightly different because sh2a's shad&shld are 4-byte insns. Perhaps something like below will work, though I don't test it at all. diff -up ORIG/gcc/config/sh/sh.h gcc/config/sh/sh.h --- ORIG/gcc/config/sh/sh.h 2011-04-23 09:43:19.000000000 +0900 +++ gcc/config/sh/sh.h 2011-10-21 08:15:25.000000000 +0900 @@ -2371,7 +2371,8 @@ extern int current_function_interrupt; #define ACCUMULATE_OUTGOING_ARGS TARGET_ACCUMULATE_OUTGOING_ARGS #define SH_DYNAMIC_SHIFT_COST \ - (TARGET_HARD_SH4 ? 1 : TARGET_SH3 ? (optimize_size ? 1 : 2) : 20) + (TARGET_HARD_SH4 ? 1 : TARGET_SH3 ? (optimize_size ? 1 : 2) \ + : TARGET_SH2A ? 2 : 20) #define NUM_MODES_FOR_MODE_SWITCHING { FP_MODE_NONE } diff -up ORIG/gcc/config/sh/sh.c gcc/config/sh/sh.c --- ORIG/gcc/config/sh/sh.c 2011-07-29 09:31:42.000000000 +0900 +++ gcc/config/sh/sh.c 2011-10-21 09:03:36.000000000 +0900 @@ -3246,7 +3246,7 @@ expand_ashiftrt (rtx *operands) char func[18]; int value; - if (TARGET_SH3) + if (TARGET_SH3 || TARGET_SH2A) { if (!CONST_INT_P (operands[2])) { diff -up ORIG/gcc/config/sh/sh.md gcc/config/sh/sh.md --- ORIG/gcc/config/sh/sh.md 2011-08-02 09:47:17.000000000 +0900 +++ gcc/config/sh/sh.md 2011-10-21 08:58:49.000000000 +0900 @@ -3424,15 +3424,6 @@ label: ;; ;; shift left -(define_insn "ashlsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0") - (match_operand:SI 2 "arith_reg_operand" "r")))] - "TARGET_SH2A" - "shad %2,%0" - [(set_attr "type" "arith") - (set_attr "length" "4")]) - ;; This pattern is used by init_expmed for computing the costs of shift ;; insns. @@ -3441,14 +3432,14 @@ label: (ashift:SI (match_operand:SI 1 "arith_reg_operand" "0,0,0,0") (match_operand:SI 2 "nonmemory_operand" "r,M,P27,?ri"))) (clobber (match_scratch:SI 3 "=X,X,X,&r"))] - "TARGET_SH3 + "(TARGET_SH3 || TARGET_SH2A) || (TARGET_SH1 && satisfies_constraint_P27 (operands[2]))" "@ shld %2,%0 add %0,%0 shll%O2 %0 #" - "TARGET_SH3 + "(TARGET_SH3 || TARGET_SH2A) && reload_completed && CONST_INT_P (operands[2]) && ! satisfies_constraint_P27 (operands[2])" @@ -3457,7 +3448,11 @@ label: [(set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 3))) (clobber (match_dup 4))])] "operands[4] = gen_rtx_SCRATCH (SImode);" - [(set_attr "length" "*,*,*,4") + [(set_attr_alternative "length" + [(if_then_else + (ne (symbol_ref "TARGET_SH2A") (const_int 0)) + (const_int 4) (const_int 2)) + (const_int 2) (const_int 2) (const_int 4)]) (set_attr "type" "dyn_shift,arith,arith,arith")]) (define_insn "ashlhi3_k" @@ -3584,15 +3579,6 @@ label: ; arithmetic shift right ; -(define_insn "ashrsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") - (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] - "TARGET_SH2A" - "shad %2,%0" - [(set_attr "type" "dyn_shift") - (set_attr "length" "4")]) - (define_insn "ashrsi3_k" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") @@ -3687,9 +3673,13 @@ label: [(set (match_operand:SI 0 "arith_reg_dest" "=r") (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] - "TARGET_SH3" + "TARGET_SH3 || TARGET_SH2A" "shad %2,%0" - [(set_attr "type" "dyn_shift")]) + [(set_attr_alternative "length" + [(if_then_else + (ne (symbol_ref "TARGET_SH2A") (const_int 0)) + (const_int 4) (const_int 2))]) + (set_attr "type" "dyn_shift")]) (define_insn "ashrsi3_n" [(set (reg:SI R4_REG) @@ -3735,22 +3725,17 @@ label: ;; logical shift right -(define_insn "lshrsi3_sh2a" - [(set (match_operand:SI 0 "arith_reg_dest" "=r") - (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") - (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] - "TARGET_SH2A" - "shld %2,%0" - [(set_attr "type" "dyn_shift") - (set_attr "length" "4")]) - (define_insn "lshrsi3_d" [(set (match_operand:SI 0 "arith_reg_dest" "=r") (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0") (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))] - "TARGET_SH3" + "TARGET_SH3 || TARGET_SH2A" "shld %2,%0" - [(set_attr "type" "dyn_shift")]) + [(set_attr "type" "dyn_shift") + (set_attr_alternative "length" + [(if_then_else + (ne (symbol_ref "TARGET_SH2A") (const_int 0)) + (const_int 4) (const_int 2))])]) ;; Only the single bit shift clobbers the T bit.