[Bug target/50814] SH Target: SHAD / SHLD instructions not used on SH2A

kkojima at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Oct 21 00:25:00 GMT 2011


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.



More information about the Gcc-bugs mailing list