Hi,

As subject, for the testcase in the patch:

  unsigned long
  f2 (unsigned long a, int b)
  {
    unsigned long x = 1UL << b;
    return a / x;
  }

We currently generate:

  f2:
        mov     x2, 1
        lsl     x1, x2, x1
        udiv    x0, x0, x1
        ret

Which could instead be transformed to:

  f2:
        lsr     x0, x0, x1
        ret

OK?

Thanks,
James

---
gcc/

2017-06-12  James Greenhalgh  <james.greenha...@arm.com>

        * match.pd (A / (1 << B) -> A >> B): New.

gcc/testsuite/

2017-06-12  James Greenhalgh  <james.greenha...@arm.com>

        * gcc.dg/tree-ssa/forwprop-37.c: New.

diff --git a/gcc/match.pd b/gcc/match.pd
index 54a8e04..656ede2 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -147,6 +147,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (op @0 integer_onep)
     (non_lvalue @0)))
 
+/* For unsigned A: (A / (1 << B)), (A >> B).
+   We can't do the same for signed A, as it might be negative, which would
+   introduce undefined behaviour.  */
+(simplify
+ (trunc_div @0 (lshift integer_onep@1 @2))
+ (if (TYPE_UNSIGNED (type))
+  (rshift @0 @2)))
+
 /* Preserve explicit divisions by 0: the C++ front-end wants to detect
    undefined behavior in constexpr evaluation, and assuming that the division
    traps enables better optimizations than these anyway.  */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c
new file mode 100644
index 0000000..dec826c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-37.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-forwprop1-raw" } */
+
+unsigned int
+f1 (unsigned int a, unsigned int b)
+{
+  unsigned int x = 1U << b;
+  return a / x;
+}
+
+unsigned long
+f2 (unsigned long a, int b)
+{
+  unsigned long x = 1UL << b;
+  return a / x;
+}
+
+unsigned long long
+f3 (unsigned long long a, int b)
+{
+  unsigned long long x = 1ULL << b;
+  return a / x;
+}
+
+/* { dg-final { scan-tree-dump-not "trunc_div_expr" "forwprop1" } } */

Reply via email to