-
Notifications
You must be signed in to change notification settings - Fork 12.3k
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
[ValueTracking] Infer relationship for the select with ICmp #66668
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Changesx-y+1 is positive when x > y, so abs (x-y+1) --> x-y+1 Fixes #54735 Full diff: https://github.com/llvm/llvm-project/pull/66668.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 5fe0d53c313d40e..ecb261716cb71fb 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4547,6 +4547,20 @@ static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
return nullptr;
}
+/// Return nullptr if the comparison relationship of X and Y can't be inferred.
+static Value *simplifySelectWithICmpKnownRelation(ICmpInst::Predicate Pred,
+ Value *CmpLHS, Value *CmpRHS,
+ Value *TrueVal,
+ Value *FalseVal,
+ const SimplifyQuery &Q) {
+ if (std::optional<bool> Flag =
+ isImpliedByDomCondition(Pred, CmpLHS, CmpRHS, Q.CxtI, Q.DL)) {
+ if (Flag)
+ return *Flag ? TrueVal : FalseVal;
+ }
+ return nullptr;
+}
+
/// Try to simplify a select instruction when its condition operand is an
/// integer comparison.
static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
@@ -4669,6 +4683,17 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
}
}
+ if (Pred == ICmpInst::ICMP_SLT) {
+ Value *X;
+ Value *Y;
+ const APInt *C;
+ // x-y+1 is positive when x >= y or non-positive when x < y
+ if (match(CmpLHS, m_NSWSub(m_Value(X), m_Value(Y))) &&
+ match(CmpRHS, m_AllOnes()))
+ return simplifySelectWithICmpKnownRelation(ICmpInst::ICMP_SLT, X, Y,
+ TrueVal, FalseVal, Q);
+ }
+
return nullptr;
}
diff --git a/llvm/test/Transforms/InstSimplify/select-icmp.ll b/llvm/test/Transforms/InstSimplify/select-icmp.ll
new file mode 100755
index 000000000000000..1271941565d9dc3
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/select-icmp.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+; https://alive2.llvm.org/ce/z/zKX64J
+define i32 @pr54735(i32 noundef %x, i32 noundef %y) {
+; CHECK-LABEL: @pr54735(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
+; CHECK: cond.true:
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[SUB]], 1
+; CHECK-NEXT: br label [[COND_END]]
+; CHECK: cond.end:
+; CHECK-NEXT: [[COND:%.*]] = phi i32 [ [[ADD]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+entry:
+ %cmp = icmp sgt i32 %x, %y
+ br i1 %cmp, label %cond.true, label %cond.end
+
+cond.true: ; preds = %entry
+ %sub = sub nsw i32 %x, %y
+ %add = add nsw i32 %sub, 1
+ %neg = xor i32 %sub, -1 ; sub nsw i32 0, %add
+ %abscond = icmp slt i32 %sub, -1
+ %abs = select i1 %abscond, i32 %neg, i32 %add
+ br label %cond.end
+
+cond.end: ; preds = %entry, %cond.true
+ %cond = phi i32 [ %abs, %cond.true ], [ 0, %entry ]
+ ret i32 %cond
+}
|
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.
I believe this needs to be handled in isImpliedCondition. There is already existing code that will simplify implications from dominating conditions.
Though really, this seems like something that ConstraintElimination should handle, not InstSimplify.
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.
Please add an alive2 proof to the patch description. This should also needs additional tests (preferably more minimal than the example you added), e.g. that this does not fold without nsw, wrong constant, etc.
Thanks, Added alive2 proof link and 2 extra negative test cases. |
ping ? |
✅ With the latest revision this PR passed the C/C++ code formatter. |
revert the change for |
ping ? |
llvm/lib/Analysis/ValueTracking.cpp
Outdated
@@ -8294,6 +8294,17 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS, | |||
if (areMatchingOperands(L0, L1, R0, R1, AreSwappedOps)) | |||
return isImpliedCondMatchingOperands(LPred, RPred, AreSwappedOps); | |||
|
|||
if (LPred == ICmpInst::ICMP_SGT) { |
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.
Should also handle the less-than variant no?
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.
hi @goldsteinn
I reverted the change for less-than because the commit #66668 (review), so I think it may be addressed with some other method.
If you don't object, I think it is fine to keep this PR to fix the issue in the comment link.
If there's no objection, I'll take a try for this commit in the next week? |
Ping @nikic @goldsteinn |
5aa207b
to
8a732dc
Compare
LGTM. Please wait for an additional approval |
|
hi @nikic , would you give me some advice? thanks |
This PR has no update for a long time, so try rebasing to top upstream to see if there's any conflict. |
ping |
LGTM, should be fine to push. |
Thanks very much |
x-y+1 is positive when x > y, so abs (x-y+1) --> x-y+1 Fixes llvm#54735
x -nsw y < -C is false when x > y and C >= 0 Alive2 proof for sgt, sge : https://alive2.llvm.org/ce/z/tupvfi Note: It only really makes sense in the context of signed comparison for "X - Y must be positive if X >= Y and no overflow". Fixes llvm#54735
x -nsw y < C is false when x > y and C <= 0
Alive2 proof for sgt, sge, ugt, uge : https://alive2.llvm.org/ce/z/tupvfi
Fixes #54735