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