https://gcc.gnu.org/g:8b9cd6490ce507a8e3612044137bd2024e8658c4
commit r16-4604-g8b9cd6490ce507a8e3612044137bd2024e8658c4 Author: Andrew MacLeod <[email protected]> Date: Thu Oct 23 17:19:02 2025 -0400 Split signed bitwise AND operations. The algorithm for bitwise AND struggles with complex signed operations which cross the signed/unsigned barrier. When this happens, process it as 2 seperate ranges [LB, -1] and [0, UB], and combine the results. PR tree-optimization/114725.c gcc/ * range-op.cc (operator_bitwise_and::wi_fold): Split signed operations crossing zero into 2 operations. gcc/testsuite/ * gcc.dg/pr114725.c: New. Diff: --- gcc/range-op.cc | 16 ++++++++++++++++ gcc/testsuite/gcc.dg/pr114725.c | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 762fd349e5f7..6b6bf78cb2f1 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3522,6 +3522,22 @@ operator_bitwise_and::wi_fold (irange &r, tree type, const wide_int &rh_lb, const wide_int &rh_ub) const { + // The AND algorithm does not handle complex signed operations well. + // If a signed range crosses the boundry between signed and unsigned + // proces sit as 2 ranges and union the results. + if (TYPE_SIGN (type) == SIGNED + && wi::neg_p (lh_lb, SIGNED) != wi::neg_p (lh_ub, SIGNED)) + { + int prec = TYPE_PRECISION (type); + int_range_max tmp; + // Process [lh_lb, -1] + wi_fold (tmp, type, lh_lb, wi::minus_one (prec), rh_lb, rh_ub); + // Now Process [0, rh_ub] + wi_fold (r, type, wi::zero (prec), lh_ub, rh_lb, rh_ub); + r.union_ (tmp); + return; + } + if (wi_optimize_and_or (r, BIT_AND_EXPR, type, lh_lb, lh_ub, rh_lb, rh_ub)) return; diff --git a/gcc/testsuite/gcc.dg/pr114725.c b/gcc/testsuite/gcc.dg/pr114725.c new file mode 100644 index 000000000000..01c31399ba86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr114725.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +//* This should fold to return 0 +bool +src(int offset) +{ + if (offset > 128) + return 0; + else + return (offset & -9) == 258; +} + +/* { dg-final { scan-tree-dump "return 0" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "PHI" "optimized" } } */
