-
Notifications
You must be signed in to change notification settings - Fork 12.1k
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 NonEqual from dominating conditions/assumptions #117442
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Yingwei Zheng (dtcxzyw) ChangesThis patch adds context-sensitive analysis support for Full diff: https://github.com/llvm/llvm-project/pull/117442.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c48068afc04816..b45bfa2fd3d964 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3748,6 +3748,50 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
+ if (!Q.CxtI)
+ return false;
+
+ // Try to infer NonEqual based on information from dominating conditions.
+ if (Q.DC && Q.DT) {
+ for (BranchInst *BI : Q.DC->conditionsFor(V1)) {
+ Value *Cond = BI->getCondition();
+ BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
+ if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
+ isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/true, Depth)
+ .value_or(false))
+ return true;
+
+ BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
+ if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
+ isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/false, Depth)
+ .value_or(false))
+ return true;
+ }
+ }
+
+ if (!Q.AC)
+ return false;
+
+ // Try to infer NonEqual based on information from assumptions.
+ for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
+ if (!AssumeVH)
+ continue;
+ CallInst *I = cast<CallInst>(AssumeVH);
+
+ assert(I->getFunction() == Q.CxtI->getFunction() &&
+ "Got assumption for the wrong function!");
+ assert(I->getIntrinsicID() == Intrinsic::assume &&
+ "must be an assume intrinsic");
+
+ if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/true, Depth)
+ .value_or(false) &&
+ isValidAssumeForContext(I, Q.CxtI, Q.DT))
+ return true;
+ }
+
return false;
}
@@ -10037,10 +10081,10 @@ void llvm::findValuesAffectedByCondition(
Worklist.push_back(B);
}
} else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
- AddCmpOperands(A, B);
-
bool HasRHSC = match(B, m_ConstantInt());
if (ICmpInst::isEquality(Pred)) {
+ AddAffected(A);
+ AddAffected(B);
if (HasRHSC) {
Value *Y;
// (X & C) or (X | C) or (X ^ C).
@@ -10055,6 +10099,7 @@ void llvm::findValuesAffectedByCondition(
}
}
} else {
+ AddCmpOperands(A, B);
if (HasRHSC) {
// Handle (A + C1) u< C2, which is the canonical form of
// A > C3 && A < C4.
diff --git a/llvm/test/Transforms/InstCombine/icmp-dom.ll b/llvm/test/Transforms/InstCombine/icmp-dom.ll
index 3cf3a7af77041c..07793e8951de59 100644
--- a/llvm/test/Transforms/InstCombine/icmp-dom.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-dom.ll
@@ -534,3 +534,203 @@ else:
%cmp1 = icmp eq i32 %and1, 0
ret i1 %cmp1
}
+
+; TODO: X != Y implies X | Y != 0
+define i1 @or_nonzero_from_nonequal(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_nonzero_from_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[X]], [[Y]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond = icmp eq i8 %x, %y
+ br i1 %cond, label %if.else, label %if.then
+
+if.then:
+ %or = or i8 %x, %y
+ %cmp = icmp eq i8 %or, 0
+ ret i1 %cmp
+
+if.else:
+ ret i1 false
+}
+
+define i1 @test_nonequal_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_domcond1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 false
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp eq i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.end, label %if.then
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_domcond2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 [[COND2]], i1 false
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 false
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ %cond2 = icmp ne i64 %w, %z
+ %or.cond = select i1 %cond1, i1 %cond2, i1 false
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_assume(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ne i64 %w, %z
+ call void @llvm.assume(i1 %cond2)
+
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+}
+
+; Negative tests
+
+define i1 @test_nonequal_invalid_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_domcond1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 true
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.end, label %if.then
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_invalid_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_domcond2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br label [[IF_END]]
+; CHECK: if.end:
+; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W]], [[Z]]
+; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y]], [[X]]
+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %cond1 = icmp eq i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then:
+ br label %if.end
+
+if.end:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+}
+
+define i1 @test_nonequal_invalid_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_assume(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
+; CHECK-NEXT: call void @side_effect()
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y]], [[X]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W]], [[Z]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+
+ call void @side_effect()
+ %cond1 = icmp ne i64 %y, %x
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ne i64 %w, %z
+ call void @llvm.assume(i1 %cond2)
+ ret i1 %cmp
+}
+
+declare void @side_effect()
|
@llvm/pr-subscribers-llvm-transforms Author: Yingwei Zheng (dtcxzyw) ChangesThis patch adds context-sensitive analysis support for Full diff: https://github.com/llvm/llvm-project/pull/117442.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c48068afc04816..b45bfa2fd3d964 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3748,6 +3748,50 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2,
match(V2, m_PtrToIntSameSize(Q.DL, m_Value(B))))
return isKnownNonEqual(A, B, DemandedElts, Depth + 1, Q);
+ if (!Q.CxtI)
+ return false;
+
+ // Try to infer NonEqual based on information from dominating conditions.
+ if (Q.DC && Q.DT) {
+ for (BranchInst *BI : Q.DC->conditionsFor(V1)) {
+ Value *Cond = BI->getCondition();
+ BasicBlockEdge Edge0(BI->getParent(), BI->getSuccessor(0));
+ if (Q.DT->dominates(Edge0, Q.CxtI->getParent()) &&
+ isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/true, Depth)
+ .value_or(false))
+ return true;
+
+ BasicBlockEdge Edge1(BI->getParent(), BI->getSuccessor(1));
+ if (Q.DT->dominates(Edge1, Q.CxtI->getParent()) &&
+ isImpliedCondition(Cond, ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/false, Depth)
+ .value_or(false))
+ return true;
+ }
+ }
+
+ if (!Q.AC)
+ return false;
+
+ // Try to infer NonEqual based on information from assumptions.
+ for (auto &AssumeVH : Q.AC->assumptionsFor(V1)) {
+ if (!AssumeVH)
+ continue;
+ CallInst *I = cast<CallInst>(AssumeVH);
+
+ assert(I->getFunction() == Q.CxtI->getFunction() &&
+ "Got assumption for the wrong function!");
+ assert(I->getIntrinsicID() == Intrinsic::assume &&
+ "must be an assume intrinsic");
+
+ if (isImpliedCondition(I->getArgOperand(0), ICmpInst::ICMP_NE, V1, V2, Q.DL,
+ /*LHSIsTrue=*/true, Depth)
+ .value_or(false) &&
+ isValidAssumeForContext(I, Q.CxtI, Q.DT))
+ return true;
+ }
+
return false;
}
@@ -10037,10 +10081,10 @@ void llvm::findValuesAffectedByCondition(
Worklist.push_back(B);
}
} else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
- AddCmpOperands(A, B);
-
bool HasRHSC = match(B, m_ConstantInt());
if (ICmpInst::isEquality(Pred)) {
+ AddAffected(A);
+ AddAffected(B);
if (HasRHSC) {
Value *Y;
// (X & C) or (X | C) or (X ^ C).
@@ -10055,6 +10099,7 @@ void llvm::findValuesAffectedByCondition(
}
}
} else {
+ AddCmpOperands(A, B);
if (HasRHSC) {
// Handle (A + C1) u< C2, which is the canonical form of
// A > C3 && A < C4.
diff --git a/llvm/test/Transforms/InstCombine/icmp-dom.ll b/llvm/test/Transforms/InstCombine/icmp-dom.ll
index 3cf3a7af77041c..07793e8951de59 100644
--- a/llvm/test/Transforms/InstCombine/icmp-dom.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-dom.ll
@@ -534,3 +534,203 @@ else:
%cmp1 = icmp eq i32 %and1, 0
ret i1 %cmp1
}
+
+; TODO: X != Y implies X | Y != 0
+define i1 @or_nonzero_from_nonequal(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_nonzero_from_nonequal(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: [[OR:%.*]] = or i8 [[X]], [[Y]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+; CHECK: if.else:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond = icmp eq i8 %x, %y
+ br i1 %cond, label %if.else, label %if.then
+
+if.then:
+ %or = or i8 %x, %y
+ %cmp = icmp eq i8 %or, 0
+ ret i1 %cmp
+
+if.else:
+ ret i1 false
+}
+
+define i1 @test_nonequal_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_domcond1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 false
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp eq i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.end, label %if.then
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_domcond2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 [[COND2]], i1 false
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 false
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ %cond2 = icmp ne i64 %w, %z
+ %or.cond = select i1 %cond1, i1 %cond2, i1 false
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_assume(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ne i64 %w, %z
+ call void @llvm.assume(i1 %cond2)
+
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+}
+
+; Negative tests
+
+define i1 @test_nonequal_invalid_domcond1(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_domcond1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_END:%.*]], label [[IF_THEN:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: ret i1 true
+; CHECK: if.end:
+; CHECK-NEXT: ret i1 false
+;
+entry:
+ %cond1 = icmp ne i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.end, label %if.then
+
+if.then:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+
+if.end:
+ ret i1 false
+}
+
+define i1 @test_nonequal_invalid_domcond2(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_domcond2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[COND1]], i1 true, i1 [[COND2]]
+; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br label [[IF_END]]
+; CHECK: if.end:
+; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W]], [[Z]]
+; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y]], [[X]]
+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %cond1 = icmp eq i64 %y, %x
+ %cond2 = icmp eq i64 %w, %z
+ %or.cond = select i1 %cond1, i1 true, i1 %cond2
+ br i1 %or.cond, label %if.then, label %if.end
+
+if.then:
+ br label %if.end
+
+if.end:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+ ret i1 %cmp
+}
+
+define i1 @test_nonequal_invalid_assume(i64 %x, i64 %y, i64 %z, i64 %w) {
+; CHECK-LABEL: @test_nonequal_invalid_assume(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[SUB1:%.*]] = sub i64 [[W:%.*]], [[Z:%.*]]
+; CHECK-NEXT: [[SUB2:%.*]] = sub i64 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[SUB1]], i64 [[SUB2]])
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[UMIN]], 0
+; CHECK-NEXT: call void @side_effect()
+; CHECK-NEXT: [[COND1:%.*]] = icmp ne i64 [[Y]], [[X]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])
+; CHECK-NEXT: [[COND2:%.*]] = icmp ne i64 [[W]], [[Z]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[COND2]])
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+entry:
+ %sub1 = sub i64 %w, %z
+ %sub2 = sub i64 %y, %x
+ %umin = call i64 @llvm.umin.i64(i64 %sub1, i64 %sub2)
+ %cmp = icmp eq i64 %umin, 0
+
+ call void @side_effect()
+ %cond1 = icmp ne i64 %y, %x
+ call void @llvm.assume(i1 %cond1)
+ %cond2 = icmp ne i64 %w, %z
+ call void @llvm.assume(i1 %cond2)
+ ret i1 %cmp
+}
+
+declare void @side_effect()
|
This patch adds context-sensitive analysis support for
isKnownNonEqual
. It is required for #117436.