simplify-rtx.c (simplify_binary_operation_1): Add LSHIFTRT case.
authorTamar Christina <tamar.christina@arm.com>
Tue, 2 May 2017 15:19:07 +0000 (15:19 +0000)
committerTamar Christina <tnfchris@gcc.gnu.org>
Tue, 2 May 2017 15:19:07 +0000 (15:19 +0000)
gcc/
2017-04-27  Tamar Christina  <tamar.christina@arm.com>

* simplify-rtx.c (simplify_binary_operation_1): Add LSHIFTRT case.

gcc/testsuite/
2017-04-27  Tamar Christina  <tamar.christina@arm.com>

* gcc.dg/lsr-div1.c: New testcase.

From-SVN: r247504

gcc/ChangeLog
gcc/simplify-rtx.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/lsr-div1.c [new file with mode: 0644]

index a3cb157..00f21e7 100644 (file)
@@ -1,3 +1,7 @@
+2017-04-27  Tamar Christina  <tamar.christina@arm.com>
+
+       * simplify-rtx.c (simplify_binary_operation_1): Add LSHIFTRT case.
+
 2017-05-02  Martin Liska  <mliska@suse.cz>
 
        PR lto/77954.
index b453419..ac85a56 100644 (file)
@@ -3345,19 +3345,21 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
          && UINTVAL (trueop0) == GET_MODE_MASK (mode)
          && ! side_effects_p (op1))
        return op0;
+
+    canonicalize_shift:
       /* Given:
         scalar modes M1, M2
         scalar constants c1, c2
         size (M2) > size (M1)
         c1 == size (M2) - size (M1)
         optimize:
-        (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>))
+        ([a|l]shiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>))
                                 <low_part>)
                      (const_int <c2>))
         to:
-        (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int <c1 + c2>))
+        (subreg:M1 ([a|l]shiftrt:M2 (reg:M2) (const_int <c1 + c2>))
                    <low_part>).  */
-      if (code == ASHIFTRT
+      if ((code == ASHIFTRT || code == LSHIFTRT)
          && !VECTOR_MODE_P (mode)
          && SUBREG_P (op0)
          && CONST_INT_P (op1)
@@ -3374,13 +3376,13 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
          rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1))
                             + INTVAL (op1));
          machine_mode inner_mode = GET_MODE (SUBREG_REG (op0));
-         tmp = simplify_gen_binary (ASHIFTRT,
+         tmp = simplify_gen_binary (code,
                                     GET_MODE (SUBREG_REG (op0)),
                                     XEXP (SUBREG_REG (op0), 0),
                                     tmp);
          return lowpart_subreg (mode, tmp, inner_mode);
        }
-    canonicalize_shift:
+
       if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1))
        {
          val = INTVAL (op1) & (GET_MODE_PRECISION (mode) - 1);
index d47aa91..759a603 100644 (file)
@@ -1,3 +1,7 @@
+2017-04-27  Tamar Christina  <tamar.christina@arm.com>
+
+       * gcc.dg/lsr-div1.c: New testcase.
+
 2017-05-02  Sebastian Peryt  <sebastian.peryt@intel.com>
 
        * gcc.target/i386/avx512f-vaddsd-1.c (_mm_mask_add_sd)
diff --git a/gcc/testsuite/gcc.dg/lsr-div1.c b/gcc/testsuite/gcc.dg/lsr-div1.c
new file mode 100644 (file)
index 0000000..962054d
--- /dev/null
@@ -0,0 +1,57 @@
+/* Test division by const int generates only one shift.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-rtl-combine-all" } */
+/* { dg-options "-O2 -fdump-rtl-combine-all -mtune=cortex-a53" { target aarch64*-*-* } } */
+/* { dg-require-effective-target int32plus } */
+
+extern void abort (void);
+
+#define NOINLINE __attribute__((noinline))
+
+static NOINLINE int
+f1 (unsigned int n)
+{
+  return n % 0x33;
+}
+
+static NOINLINE int
+f2 (unsigned int n)
+{
+  return n % 0x12;
+}
+
+int
+main ()
+{
+  int a = 0xaaaaaaaa;
+  int b = 0x55555555;
+  int c;
+  c = f1 (a);
+  if (c != 0x11)
+    abort ();
+  c = f1 (b);
+  if (c != 0x22)
+    abort ();
+  c = f2 (a);
+  if (c != 0xE)
+    abort ();
+  c = f2 (b);
+  if (c != 0x7)
+    abort ();
+  return 0;
+}
+
+/* Following replacement pattern of intger division by constant, GCC is expected
+   to generate UMULL and (x)SHIFTRT.  This test checks that considering division
+   by const 0x33, gcc generates a single LSHIFTRT by 37, instead of
+   two - LSHIFTRT by 32 and LSHIFTRT by 5.  */
+
+/* { dg-final { scan-rtl-dump "\\(set \\(subreg:DI \\(reg:SI" "combine" { target aarch64*-*-* } } } */
+/* { dg-final { scan-rtl-dump "\\(lshiftrt:DI \\(reg:DI" "combine" { target aarch64*-*-* } } } */
+/* { dg-final { scan-rtl-dump "\\(const_int 37 " "combine" { target aarch64*-*-* } } } */
+
+/* Similarly, considering division by const 0x12, gcc generates a
+   single LSHIFTRT by 34, instead of two - LSHIFTRT by 32 and LSHIFTRT by 2.  */
+
+/* { dg-final { scan-rtl-dump "\\(const_int 34 " "combine" { target aarch64*-*-* } } } */
+