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" } } */