From: Andrew MacLeod Date: Thu, 14 Oct 2021 14:43:58 +0000 (-0400) Subject: Simplification for right shift. X-Git-Tag: basepoints/gcc-13~3900 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0b7d4cc49ddb1c2c7474cc3f61e260aa93a96c0;p=thirdparty%2Fgcc.git Simplification for right shift. When the first operand of a signed right shift is zero or negative one, the RHS doesn't matter and the shift can be converted to a copy. PR tree-optimization/102738 gcc/ * vr-values.c (simplify_using_ranges::simplify): Handle RSHIFT_EXPR. gcc/testsuite * gcc.dg/pr102738.c: New. --- diff --git a/gcc/testsuite/gcc.dg/pr102738.c b/gcc/testsuite/gcc.dg/pr102738.c new file mode 100644 index 000000000000..776fcecb27a8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102738.c @@ -0,0 +1,48 @@ +/* PR tree-optimization/102738 */ +/* { dg-options "-O2 -fdump-tree-evrp" } */ + +/* Remove arithmetic shift right when the LHS is known to be 0 or -1. */ + +int a1(__int128 f, int g) +{ + /* Leaves f >> 127. */ + return (f >> 127) >> g; +} + +int a2(int f, int g) +{ + /* Leaves f >> 31. */ + return (f >> 31) >> g; +} + +int a3(int f, int g) +{ + if (f == 0 || f == -1) + return f >> g; + __builtin_unreachable(); +} + +int a4(int f, int g) +{ + if (f == 0 || f == 1) + return (-f) >> g; + __builtin_unreachable(); +} + +int a5(int f, int g) +{ + if (f == 0 || f == 1) + return (f-1) >> g; + return 0; +} + +int a6(int f, int g) +{ + if (f == 6 || f == 7) + return (f-7) >> g; + __builtin_unreachable(); +} + +/* { dg-final { scan-tree-dump-times " >> 127" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-times " >> 31" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-times " >> " 2 "evrp" } } */ diff --git a/gcc/vr-values.c b/gcc/vr-values.c index 9bf58f416f2d..d0f7cb41bc85 100644 --- a/gcc/vr-values.c +++ b/gcc/vr-values.c @@ -4281,6 +4281,28 @@ simplify_using_ranges::simplify (gimple_stmt_iterator *gsi) case MAX_EXPR: return simplify_min_or_max_using_ranges (gsi, stmt); + case RSHIFT_EXPR: + { + tree op0 = gimple_assign_rhs1 (stmt); + tree type = TREE_TYPE (op0); + int_range_max range; + if (TYPE_SIGN (type) == SIGNED + && query->range_of_expr (range, op0, stmt)) + { + unsigned prec = TYPE_PRECISION (TREE_TYPE (op0)); + int_range<2> nzm1 (type, wi::minus_one (prec), wi::zero (prec), + VR_ANTI_RANGE); + range.intersect (nzm1); + // If there are no ranges other than [-1, 0] remove the shift. + if (range.undefined_p ()) + { + gimple_assign_set_rhs_from_tree (gsi, op0); + return true; + } + return false; + } + break; + } default: break; }