https://gcc.gnu.org/g:7306944cffc49249c4947e6f9b13130986f24f5a
commit r17-2516-g7306944cffc49249c4947e6f9b13130986f24f5a Author: Andrew MacLeod <[email protected]> Date: Thu Jul 16 16:43:40 2026 -0400 Enhance logical AND and OR op1_range. The rangeops should recognize that [0, 0] = op1 & TRUE --> op1 must be [0, 0] [1, 1] = op1 | FALSE --> op1 must be [1, 1] op2_range simple transposes the operands, so this covers both cases. PR tree-optimization/126212 * range-op.cc (operator_logical_and::op1_range): Add case for [0, 0] = op1 & [1, 1] (operator_logical_or::op1_range): Add case for [1, 1] = op1 | [0, 0] Diff: --- gcc/range-op.cc | 72 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/gcc/range-op.cc b/gcc/range-op.cc index 94edfdc98708..a1a479a8319a 100644 --- a/gcc/range-op.cc +++ b/gcc/range-op.cc @@ -3420,22 +3420,31 @@ operator_logical_and::fold_range (irange &r, tree type, bool operator_logical_and::op1_range (irange &r, tree type, const irange &lhs, - const irange &op2 ATTRIBUTE_UNUSED, + const irange &op2, relation_trio) const { - switch (get_bool_state (r, lhs, type)) - { - case BRS_TRUE: - // A true result means both sides of the AND must be true. - r = range_true (type); - break; - default: - // Any other result means only one side has to be false, the - // other side can be anything. So we cannot be sure of any - // result here. - r = range_true_and_false (type); - break; - } + switch (get_bool_state (r, lhs, type)) + { + case BRS_TRUE: + // A TRUE result means both sides of the AND must be true. + r = range_true (type); + return true; + + case BRS_FALSE: + // A FALSE result when op2 is TRUE, must have op1 FALSE. + if (!op2.contains_p (wi::zero (TYPE_PRECISION (op2.type ())))) + { + r = range_false (type); + return true; + } + break; + + default: + break; + } + + // Any other result means we cannot be sure of any result. + r = range_true_and_false (type); return true; } @@ -3950,22 +3959,31 @@ operator_logical_or::fold_range (irange &r, tree type ATTRIBUTE_UNUSED, bool operator_logical_or::op1_range (irange &r, tree type, const irange &lhs, - const irange &op2 ATTRIBUTE_UNUSED, + const irange &op2, relation_trio) const { - switch (get_bool_state (r, lhs, type)) - { - case BRS_FALSE: - // A false result means both sides of the OR must be false. - r = range_false (type); - break; - default: - // Any other result means only one side has to be true, the - // other side can be anything. so we can't be sure of any result - // here. - r = range_true_and_false (type); - break; + switch (get_bool_state (r, lhs, type)) + { + case BRS_FALSE: + // A false result means both sides of the OR must be false. + r = range_false (type); + return true; + + case BRS_TRUE: + // A TRUE result when op2 is FALSE must have op1 TRUE. + if (op2.zero_p ()) + { + r = range_true (type); + return true; + } + break; + + default: + break; } + + // Any other result means we cannot be sure of any result. + r = range_true_and_false (type); return true; }
