-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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
[CVP] Propagate constant range on icmp at use level #73767
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-analysis @llvm/pr-subscribers-llvm-transforms Author: XChy (XChy) ChangesSolve a shallow version of #71383. However, this patch cannot solve #71383 now, for InstCombine canonicalizes Full diff: https://github.com/llvm/llvm-project/pull/73767.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index 1bdc441d18ea65e..9e947a7e6d39c83 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -275,11 +275,26 @@ static bool processICmp(ICmpInst *Cmp, LazyValueInfo *LVI) {
if (!Cmp->isSigned())
return false;
+ auto LHSRange = LVI->getConstantRangeAtUse(Cmp->getOperandUse(0));
+ auto RHSRange = LVI->getConstantRangeAtUse(Cmp->getOperandUse(1));
+
+ // NOTE: It's not the original purpose.
+ // Do simple constant propagation at use level,
+ if (Cmp->hasOneUse()) {
+ if (LHSRange.icmp(Cmp->getPredicate(), RHSRange)) {
+ Cmp->replaceAllUsesWith(Constant::getAllOnesValue(Cmp->getType()));
+ return true;
+ }
+
+ if (LHSRange.icmp(Cmp->getInversePredicate(), RHSRange)) {
+ Cmp->replaceAllUsesWith(Constant::getNullValue(Cmp->getType()));
+ return true;
+ }
+ }
+
ICmpInst::Predicate UnsignedPred =
- ConstantRange::getEquivalentPredWithFlippedSignedness(
- Cmp->getPredicate(),
- LVI->getConstantRangeAtUse(Cmp->getOperandUse(0)),
- LVI->getConstantRangeAtUse(Cmp->getOperandUse(1)));
+ ConstantRange::getEquivalentPredWithFlippedSignedness(Cmp->getPredicate(),
+ LHSRange, RHSRange);
if (UnsignedPred == ICmpInst::Predicate::BAD_ICMP_PREDICATE)
return false;
diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
index 101820a4c65f23b..ff9b5df666860c4 100644
--- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
+++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll
@@ -1455,3 +1455,105 @@ entry:
%select = select i1 %cmp1, i1 %cmp2, i1 false
ret i1 %select
}
+
+define i1 @select_ternary_icmp1(i32 noundef %a) {
+; CHECK-LABEL: @select_ternary_icmp1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 3
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 5
+; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i32 [[A]], 7
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 true, i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 3
+ %cmp1 = icmp slt i32 %a, 5
+ %cmp2 = icmp slt i32 %a, 7
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
+
+define i1 @select_ternary_icmp2(i32 noundef %a) {
+; CHECK-LABEL: @select_ternary_icmp2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 5
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 7
+; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 3
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 true, i1 false
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 5
+ %cmp1 = icmp slt i32 %a, 7
+ %cmp2 = icmp slt i32 %a, 3
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
+
+define i1 @select_ternary_icmp3(i32 noundef %a) {
+; CHECK-LABEL: @select_ternary_icmp3(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 7
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[A]], 3
+; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[A]], 5
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 false
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 7
+ %cmp1 = icmp slt i32 %a, 3
+ %cmp2 = icmp slt i32 %a, 5
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
+
+define i1 @select_ternary_icmp3_reverse(i32 noundef %a) {
+; CHECK-LABEL: @select_ternary_icmp3_reverse(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 3
+; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i32 [[A]], 5
+; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i32 [[A]], 7
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 false, i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 3
+ %cmp1 = icmp sge i32 %a, 5
+ %cmp2 = icmp sge i32 %a, 7
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
+
+define i1 @select_ternary_icmp_fail1(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: @select_ternary_icmp_fail1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 3
+; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[B:%.*]], 5
+; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[B]], 7
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 3
+ %cmp1 = icmp slt i32 %b, 5
+ %cmp2 = icmp slt i32 %b, 7
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
+
+define i1 @select_ternary_icmp_fail2(i32 noundef %a, i32 noundef %b) {
+; CHECK-LABEL: @select_ternary_icmp_fail2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A:%.*]], 3
+; CHECK-NEXT: [[CMP1:%.*]] = icmp sge i32 5, [[B:%.*]]
+; CHECK-NEXT: [[CMP2:%.*]] = icmp sge i32 7, [[B]]
+; CHECK-NEXT: [[COND_V:%.*]] = select i1 [[CMP]], i1 [[CMP1]], i1 [[CMP2]]
+; CHECK-NEXT: ret i1 [[COND_V]]
+;
+entry:
+ %cmp = icmp slt i32 %a, 3
+ %cmp1 = icmp sge i32 5, %b
+ %cmp2 = icmp sge i32 7, %b
+ %cond.v = select i1 %cmp, i1 %cmp1, i1 %cmp2
+ ret i1 %cond.v
+}
|
This is duplicating the functionality of getPredicateAt() -- would it be better to introduce getPredicateAtUse()? |
I think so. I would introduce it in LazyValueInfo later. |
ping. |
1 similar comment
ping. |
In 7de592b I have refactored the getConstantRangeAtUse() implementation to be based on an internal getValueAtUse() method that works on ValueLatticeElement. I think with that, it should be possible to integrate the implementations. |
OK, I will rebase on it and integrate them. |
232525c
to
8a1fc0d
Compare
The implementations are integrated. Now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Please wait for additional approval from other reviewers.
Rebase this PR on latest main to avoid test failure in CI. |
@nikic , what's your opinion on this patch? |
Could you please have a look at dtcxzyw/llvm-opt-benchmark@a71358f? Our CI detected a regression in
|
@dtcxzyw , there is the example for your report: https://alive2.llvm.org/ce/z/aausVv. And pipeline: https://godbolt.org/z/YETvK3Yhj. |
Ping? |
#73767 (comment) has been resolved now for the improvement in InstCombine. Any other review opinions? |
Ping. |
1 similar comment
Ping. |
Solve a shallow version of #71383.
ProcessICmp
in CVP is used to flip the signedness oficmp
predicate. This patch reuses the constant range to directly foldicmp
at use level.However, this patch cannot solve #71383 now, for InstCombine canonicalizes
select cond, binop(a, C1), op(a, C2)
tobinop(a, select cond, C1, C2)
.