diff --git a/gcc/match.pd b/gcc/match.pd index 7b96800..be20fb7 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -508,6 +508,19 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) && tree_nop_conversion_p (type, TREE_TYPE (@1))) (lshift @0 @2))) +/* Fold (1 << (C - x)) where C = precision(type) - 1 + into ((1 << C) >> x). */ +(simplify + (lshift integer_onep@0 (minus INTEGER_CST@1 @2)) + (if (INTEGRAL_TYPE_P (type) + && TYPE_PRECISION (type) <= HOST_BITS_PER_WIDE_INT + && tree_to_uhwi (@1) == (unsigned)(TYPE_PRECISION (type) - 1)) + (if (TYPE_UNSIGNED(type)) + (rshift (lshift @0 @1) @2) + (with + { tree utype = unsigned_type_for (type); } + (convert:type (rshift (lshift (convert:utype @0) @1) @2)))))) + /* Fold (C1/X)*C2 into (C1*C2)/X. */ (simplify (mult (rdiv@3 REAL_CST@0 @1) REAL_CST@2) diff --git a/gcc/testsuite/gcc.dg/pr80131-1.c b/gcc/testsuite/gcc.dg/pr80131-1.c new file mode 100644 index 0000000..2bb6ff3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr80131-1.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +/* Checks the simplification of: + 1 << (C - x) to (1 << C) >> x, where C = precision (type) - 1 + f1 is not simplified but f2, f3 and f4 are. */ + +__INT64_TYPE__ f1 (__INT64_TYPE__ i) +{ + return (__INT64_TYPE__)1 << (31 - i); +} + +__INT64_TYPE__ f2 (__INT64_TYPE__ i) +{ + return (__INT64_TYPE__)1 << (63 - i); +} + +__UINT64_TYPE__ f3 (__INT64_TYPE__ i) +{ + return (__UINT64_TYPE__)1 << (63 - i); +} + +__INT32_TYPE__ f4 (__INT32_TYPE__ i) +{ + return (__INT32_TYPE__)1 << (31 - i); +} + +/* { dg-final { scan-tree-dump-times "= 31 -" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "9223372036854775808 >>" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump "2147483648 >>" "gimple" } } */