http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50814
--- Comment #1 from Kazumoto Kojima 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.h2011-04-23 09:43:19.0 +0900
+++ gcc/config/sh/sh.h2011-10-21 08:15:25.0 +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.c2011-07-29 09:31:42.0 +0900
+++ gcc/config/sh/sh.c2011-10-21 09:03:36.0 +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.md2011-08-02 09:47:17.0 +0900
+++ gcc/config/sh/sh.md2011-10-21 08:58:49.0 +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.