From f70bb3d2c33f105543df4b4db1070fd665fd513e Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Mon, 16 Jun 2025 16:32:37 +0100 Subject: [PATCH 1/2] [SCEV] Better preserve wrapping info in SimplifyICmpOperands for UGE. Update SimplifyICmpOperands to only try subtracting 1 from RHS first, if RHS is an op we can fold the subtract directly into. Otherwise try adding to LHS first, as we can preserve NUW flags. This improves results in a few cases, including the modified test case from berkeley-abc and new code to be added in https://github.com/llvm/llvm-project/pull/128061. Note that there are more cases where the results can be improved by better ordering here which I'll try to investigate as follow-up. --- llvm/lib/Analysis/ScalarEvolution.cpp | 10 +++++++++- .../IndVarSimplify/simplify-icmp-operands-order.ll | 9 +++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 2dfe625eb0dcc..ea7c7ece5632f 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -10892,7 +10892,11 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS, } break; case ICmpInst::ICMP_UGE: - if (!getUnsignedRangeMin(RHS).isMinValue()) { + // If RHS is an op we can fold the -1, try that first. + if ((isa(RHS) || + match(RHS, + m_scev_AffineAddRec(m_SCEVConstant(), m_SCEV(), m_Loop()))) && + !getUnsignedRangeMin(RHS).isMinValue()) { RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS); Pred = ICmpInst::ICMP_UGT; Changed = true; @@ -10901,6 +10905,10 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS, SCEV::FlagNUW); Pred = ICmpInst::ICMP_UGT; Changed = true; + } else if (!getUnsignedRangeMin(RHS).isMinValue()) { + RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS); + Pred = ICmpInst::ICMP_UGT; + Changed = true; } break; default: diff --git a/llvm/test/Transforms/IndVarSimplify/simplify-icmp-operands-order.ll b/llvm/test/Transforms/IndVarSimplify/simplify-icmp-operands-order.ll index b0dbbd5eaedf4..fb2fdb116f904 100644 --- a/llvm/test/Transforms/IndVarSimplify/simplify-icmp-operands-order.ll +++ b/llvm/test/Transforms/IndVarSimplify/simplify-icmp-operands-order.ll @@ -53,15 +53,12 @@ loop.latch: define void @test_simplifycompare_rhs_not_constant1() { ; CHECK-LABEL: define void @test_simplifycompare_rhs_not_constant1() { -; CHECK-NEXT: [[ENTRY:.*]]: +; CHECK-NEXT: [[ENTRY:.*:]] ; CHECK-NEXT: [[P:%.*]] = alloca i64, align 8 ; CHECK-NEXT: br label %[[LOOP:.*]] ; CHECK: [[LOOP]]: -; CHECK-NEXT: [[PTR_IV:%.*]] = phi ptr [ [[P]], %[[ENTRY]] ], [ [[PTR_IV_NEXT:%.*]], %[[LOOP]] ] -; CHECK-NEXT: [[PTR_IV_NEXT]] = getelementptr i8, ptr [[PTR_IV]], i64 -8 -; CHECK-NEXT: call void @use(ptr [[PTR_IV]]) -; CHECK-NEXT: [[EC:%.*]] = icmp ult ptr [[PTR_IV_NEXT]], [[P]] -; CHECK-NEXT: br i1 [[EC]], label %[[EXIT:.*]], label %[[LOOP]] +; CHECK-NEXT: call void @use(ptr [[P]]) +; CHECK-NEXT: br i1 true, label %[[EXIT:.*]], label %[[LOOP]] ; CHECK: [[EXIT]]: ; CHECK-NEXT: ret void ; From 3baa3103298713f293c2a9bd584e854848185b77 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 17 Jun 2025 14:17:15 +0100 Subject: [PATCH 2/2] !fixup address comments, thanks --- llvm/lib/Analysis/ScalarEvolution.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index ea7c7ece5632f..dd309bc2c54a8 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -10893,9 +10893,10 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS, break; case ICmpInst::ICMP_UGE: // If RHS is an op we can fold the -1, try that first. + // Otherwise prefer LHS to preserve the nuw flag. if ((isa(RHS) || - match(RHS, - m_scev_AffineAddRec(m_SCEVConstant(), m_SCEV(), m_Loop()))) && + (isa(RHS) && + isa(cast(RHS)->getOperand(0)))) && !getUnsignedRangeMin(RHS).isMinValue()) { RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS); Pred = ICmpInst::ICMP_UGT;