gcc/
authorolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Feb 2016 13:33:31 +0000 (13:33 +0000)
committerolegendo <olegendo@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 22 Feb 2016 13:33:31 +0000 (13:33 +0000)
PR target/69806
PR target/54089
* config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p):
Handle negative shift counts.
* config/sh/sh.md (ashlsi3, lshrsi3_n, lshrsi3_n_clobbers_t): Don't use
force_reg on the shift constant.
(lshrsi3): Likewise.  Expand into lshrsi3_n* instead of lshrsi3_d.
(lshrsi3_d): Handle negative shift counts.

gcc/testsuite/
PR target/69806
PR target/54089
* gcc.target/sh/pr54089-10.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@233601 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sh/sh.c
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr54089-10.c [new file with mode: 0644]

index 3e4273b..14e3adb 100644 (file)
@@ -1,3 +1,14 @@
+2016-02-22  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/69806
+       PR target/54089
+       * config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p, sh_dynamicalize_shift_p):
+       Handle negative shift counts.
+       * config/sh/sh.md (ashlsi3, lshrsi3_n, lshrsi3_n_clobbers_t): Don't use
+       force_reg on the shift constant.
+       (lshrsi3): Likewise.  Expand into lshrsi3_n* instead of lshrsi3_d.
+       (lshrsi3_d): Handle negative shift counts.
+
 2016-02-22  Richard Biener  <rguenther@suse.de>
            Tom de Vries  <tom@codesourcery.com>
 
index 0b18ce5..8c8fe3c 100644 (file)
@@ -3259,7 +3259,8 @@ sh_lshrsi_clobbers_t_reg_p (rtx shift_amount)
 {
   gcc_assert (CONST_INT_P (shift_amount));
 
-  const int shift_amount_i = INTVAL (shift_amount) & 31;
+  /* For right shifts the constant might be negative.  */
+  const int shift_amount_i = std::abs (INTVAL (shift_amount)) & 31;
  
   /* Special case for shift count of 31: use shll-movt sequence.  */
   if (shift_amount_i == 31)
@@ -3278,7 +3279,8 @@ sh_dynamicalize_shift_p (rtx count)
 {
   gcc_assert (CONST_INT_P (count));
 
-  const int shift_amount_i = INTVAL (count) & 31;
+  /* For right shifts the constant might be negative.  */
+  const int shift_amount_i = std::abs (INTVAL (count)) & 31;
   int insn_count;
 
   /* For left and right shifts, there are shorter 2 insn sequences for
index 9fa835b..c0a9249 100644 (file)
@@ -5011,7 +5011,10 @@ label:
     }
   if (TARGET_DYNSHIFT
       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
-      operands[2] = force_reg (SImode, operands[2]);
+    {
+      /* Don't force the constant into a reg yet.  Some other optimizations
+        might not see through the reg that holds the shift count.  */
+    }
 
   /*  If the ashlsi3_* insn is going to clobber the T_REG it must be
       expanded here.  */
@@ -5567,9 +5570,12 @@ label:
   if (TARGET_DYNSHIFT
       && CONST_INT_P (operands[2]) && sh_dynamicalize_shift_p (operands[2]))
     {
-      rtx neg_count = force_reg (SImode,
-                                gen_int_mode (- INTVAL (operands[2]), SImode));
-      emit_insn (gen_lshrsi3_d (operands[0], operands[1], neg_count));
+      /* Don't force the constant into a reg yet.  Some other optimizations
+        might not see through the reg that holds the shift count.  */
+      if (sh_lshrsi_clobbers_t_reg_p (operands[2]))
+        emit_insn (gen_lshrsi3_n_clobbers_t (operands[0], operands[1], operands[2]));
+      else
+        emit_insn (gen_lshrsi3_n (operands[0], operands[1], operands[2]));
       DONE;
     }
 
@@ -5621,6 +5627,10 @@ label:
    && ! sh_lshrsi_clobbers_t_reg_p (operands[2])"
   [(const_int 0)]
 {
+  /* The shift count const_int is a negative value for all dynamic
+     right shift insns.  */
+  operands[2] = GEN_INT (- INTVAL (operands[2]));
+
   if (satisfies_constraint_P27 (operands[2]))
     {
       /* This will not be done for a shift amount of 1, because it would
@@ -5679,8 +5689,7 @@ label:
     {
       /* If this pattern was picked and dynamic shifts are supported, switch
         to dynamic shift pattern before reload.  */
-      operands[2] = force_reg (SImode,
-                              gen_int_mode (- INTVAL (operands[2]), SImode));
+      operands[2] = GEN_INT (- INTVAL (operands[2]));
       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
     }
   else
@@ -5711,8 +5720,7 @@ label:
     {
       /* If this pattern was picked and dynamic shifts are supported, switch
         to dynamic shift pattern before reload.  */
-      operands[2] = force_reg (SImode,
-                              gen_int_mode (- INTVAL (operands[2]), SImode));
+      operands[2] = GEN_INT (- INTVAL (operands[2]));
       emit_insn (gen_lshrsi3_d (operands[0], operands[1], operands[2]));
     }
   else
index 6c73051..927af63 100644 (file)
@@ -1,3 +1,9 @@
+2016-02-22  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/69806
+       PR target/54089
+       * gcc.target/sh/pr54089-10.c: New.
+
 2016-02-20  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/69423
diff --git a/gcc/testsuite/gcc.target/sh/pr54089-10.c b/gcc/testsuite/gcc.target/sh/pr54089-10.c
new file mode 100644 (file)
index 0000000..85aeabd
--- /dev/null
@@ -0,0 +1,153 @@
+/* Check that there are no redundant zero extensions around logical right
+   shifts.  */
+/* { dg-do compile }  */
+/* { dg-options "-O1" }  */
+/* { dg-final { scan-assembler-times "extu" 20 } }  */
+
+/* { dg-final { scan-assembler-times "shll" 2 { target { "! sh2a" && has_dyn_shift } } } }  */
+/* { dg-final { scan-assembler-times "shll" 3 { target { "! sh2a" && "! has_dyn_shift" } } } }  */
+/* { dg-final { scan-assembler-times "movt" 2 { target { ! sh2a } } } }  */
+
+/* { dg-final { scan-assembler-times "bld" 1 { target { sh2a } } } }  */
+/* { dg-final { scan-assembler-times "movt" 1 { target { sh2a } } } }  */
+/* { dg-final { scan-assembler-times "movrt" 1 { target { sh2a } } } }  */
+/* { dg-final { scan-assembler-times "cmp/pz" 1 { target { sh2a } } } }  */
+
+/* { dg-final { scan-assembler-times "shld" 9 { target { has_dyn_shift } } } }  */
+
+void
+test_0 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 1;
+}
+
+void
+test_1 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 2;
+}
+
+void
+test_2 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 3;
+}
+
+void
+test_3 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 4;
+}
+
+void
+test_4 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 5;
+}
+
+void
+test_5 (unsigned char* x, unsigned int* y)
+{
+  y[0] = x[1] >> 6;
+}
+
+void
+test_6 (unsigned char* x, unsigned int* y)
+{
+  /* non-SH2A: shll, movt
+     SH2A: bld, movt */
+  y[0] = x[1] >> 7;
+}
+
+
+void
+test_100 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 1;
+}
+
+void
+test_101 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 2;
+}
+
+void
+test_102 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 3;
+}
+
+void
+test_103 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 4;
+}
+
+void
+test_104 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 5;
+}
+
+void
+test_105 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 6;
+}
+
+void
+test_106 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 7;
+}
+
+void
+test_107 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 8;
+}
+
+void
+test_108 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 9;
+}
+
+void
+test_109 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 10;
+}
+
+void
+test_110 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 11;
+}
+
+void
+test_111 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 12;
+}
+
+void
+test_112 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 13;
+}
+
+void
+test_113 (unsigned short* x, unsigned int* y)
+{
+  y[0] = x[1] >> 14;
+}
+
+void
+test_114 (unsigned short* x, unsigned int* y)
+{
+  /* non-SH2A: shll, movt
+     SH2A: cmp/pz, movrt */
+  y[0] = x[1] >> 15;
+}