Skip to content

[SCEV] Better preserve wrapping info in SimplifyICmpOperands for UGE. #144404

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion llvm/lib/Analysis/ScalarEvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10892,7 +10892,12 @@ 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// If RHS is an op we can fold the -1, try that first.
// If RHS is an op we can fold the -1, try that first.
// Otherwise prefer LHS to preserve the nuw flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added thanks

// Otherwise prefer LHS to preserve the nuw flag.
if ((isa<SCEVConstant>(RHS) ||
(isa<SCEVAddExpr, SCEVAddRecExpr>(RHS) &&
isa<SCEVConstant>(cast<SCEVNAryExpr>(RHS)->getOperand(0)))) &&
!getUnsignedRangeMin(RHS).isMinValue()) {
RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS);
Pred = ICmpInst::ICMP_UGT;
Changed = true;
Expand All @@ -10901,6 +10906,10 @@ bool ScalarEvolution::SimplifyICmpOperands(CmpPredicate &Pred, const SCEV *&LHS,
SCEV::FlagNUW);
Pred = ICmpInst::ICMP_UGT;
Changed = true;
} else if (!getUnsignedRangeMin(RHS).isMinValue()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really don't like the code structure here, but I don't have a good suggestion on improving it either...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, but I also didn't find anything better :(

Copy link
Contributor

@antoniofrighetto antoniofrighetto Jun 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nikic Not sure if this could be an acceptable alternative: https://gist.github.com/antoniofrighetto/83c188d5ad0a4988eec8d4c30684dafe. It started relatively well, it didn't really end up as good as originally envisioned (NFCI, as RHS is checked first for UGE, might not want this as we probably should preserve the flag).

RHS = getAddExpr(getConstant(RHS->getType(), (uint64_t)-1, true), RHS);
Pred = ICmpInst::ICMP_UGT;
Changed = true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does unconditionally swapping the cases cause regressions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, we would loose flags in test_simplifycompare_rhs_constant and test_simplifycompare_rhs_addrec, but gain some in test_simplifycompare_rhs_not_constant2

The current version doesn't have any regression on a large test-set of C/C++ workloads.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

llvm-opt-benchmark results are available here: https://github.com/dtcxzyw/llvm-opt-benchmark/pull/2452/files

}
break;
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
;
Expand Down
Loading