-
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
ConstraintElim: teach fact-transfer about samesign #115893
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Ramkumar Ramachandra (artagnon) ChangesWhen the samesign flag is present on an icmp, we can transfer all the facts on the unsigned system to the signed system, and vice-versa: we do this by specializing transferToOtherSystem when samesign is present. Supporting samesign in ConstraintElimination has necessitated adding extra information to ConditionFacts, as the information would otherwise be lost. Full diff: https://github.com/llvm/llvm-project/pull/115893.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 7c06e0c757e1cc..3a040ff3f60c0a 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -88,14 +88,15 @@ static Instruction *getContextInstForUse(Use &U) {
namespace {
/// Struct to express a condition of the form %Op0 Pred %Op1.
struct ConditionTy {
- CmpInst::Predicate Pred;
- Value *Op0;
- Value *Op1;
-
- ConditionTy()
- : Pred(CmpInst::BAD_ICMP_PREDICATE), Op0(nullptr), Op1(nullptr) {}
- ConditionTy(CmpInst::Predicate Pred, Value *Op0, Value *Op1)
- : Pred(Pred), Op0(Op0), Op1(Op1) {}
+ CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
+ bool HasSameSign = false;
+ Value *Op0 = nullptr;
+ Value *Op1 = nullptr;
+
+ ConditionTy() = default;
+ ConditionTy(CmpInst::Predicate Pred, Value *Op0, Value *Op1,
+ bool HasSameSign = false)
+ : Pred(Pred), HasSameSign(HasSameSign), Op0(Op0), Op1(Op1) {}
};
/// Represents either
@@ -132,19 +133,25 @@ struct FactOrCheck {
Ty(Ty) {}
FactOrCheck(DomTreeNode *DTN, Use *U)
- : U(U), DoesHold(CmpInst::BAD_ICMP_PREDICATE, nullptr, nullptr),
- NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
+ : U(U), NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
Ty(EntryTy::UseCheck) {}
FactOrCheck(DomTreeNode *DTN, CmpInst::Predicate Pred, Value *Op0, Value *Op1,
- ConditionTy Precond = ConditionTy())
- : Cond(Pred, Op0, Op1), DoesHold(Precond), NumIn(DTN->getDFSNumIn()),
- NumOut(DTN->getDFSNumOut()), Ty(EntryTy::ConditionFact) {}
+ ConditionTy Precond = {}, bool HasSameSign = false)
+ : Cond(Pred, Op0, Op1, HasSameSign), DoesHold(Precond),
+ NumIn(DTN->getDFSNumIn()), NumOut(DTN->getDFSNumOut()),
+ Ty(EntryTy::ConditionFact) {}
static FactOrCheck getConditionFact(DomTreeNode *DTN, CmpInst::Predicate Pred,
Value *Op0, Value *Op1,
- ConditionTy Precond = ConditionTy()) {
- return FactOrCheck(DTN, Pred, Op0, Op1, Precond);
+ ConditionTy Precond = {}) {
+ return FactOrCheck(DTN, Pred, Op0, Op1, Precond, false);
+ }
+
+ static FactOrCheck getConditionFact(DomTreeNode *DTN, CmpInst::Predicate Pred,
+ Value *Op0, Value *Op1,
+ bool HasSameSign) {
+ return FactOrCheck(DTN, Pred, Op0, Op1, {}, HasSameSign);
}
static FactOrCheck getInstFact(DomTreeNode *DTN, Instruction *Inst) {
@@ -1077,8 +1084,9 @@ void State::addInfoFor(BasicBlock &BB) {
if (GuaranteedToExecute) {
// The assume is guaranteed to execute when BB is entered, hence Cond
// holds on entry to BB.
+ bool HasSameSign = cast<ICmpInst>(I.getOperand(0))->hasSameSign();
WorkList.emplace_back(FactOrCheck::getConditionFact(
- DT.getNode(I.getParent()), Pred, A, B));
+ DT.getNode(I.getParent()), Pred, A, B, HasSameSign));
} else {
WorkList.emplace_back(
FactOrCheck::getInstFact(DT.getNode(I.getParent()), &I));
@@ -1160,7 +1168,7 @@ void State::addInfoFor(BasicBlock &BB) {
DT.getNode(Successor),
IsOr ? CmpInst::getInversePredicate(Cmp->getPredicate())
: Cmp->getPredicate(),
- Cmp->getOperand(0), Cmp->getOperand(1)));
+ Cmp->getOperand(0), Cmp->getOperand(1), Cmp->hasSameSign()));
continue;
}
if (IsOr && match(Cur, m_LogicalOr(m_Value(Op0), m_Value(Op1)))) {
@@ -1184,12 +1192,12 @@ void State::addInfoFor(BasicBlock &BB) {
if (canAddSuccessor(BB, Br->getSuccessor(0)))
WorkList.emplace_back(FactOrCheck::getConditionFact(
DT.getNode(Br->getSuccessor(0)), CmpI->getPredicate(),
- CmpI->getOperand(0), CmpI->getOperand(1)));
+ CmpI->getOperand(0), CmpI->getOperand(1), CmpI->hasSameSign()));
if (canAddSuccessor(BB, Br->getSuccessor(1)))
WorkList.emplace_back(FactOrCheck::getConditionFact(
DT.getNode(Br->getSuccessor(1)),
CmpInst::getInversePredicate(CmpI->getPredicate()), CmpI->getOperand(0),
- CmpI->getOperand(1)));
+ CmpI->getOperand(1), CmpI->hasSameSign()));
}
#ifndef NDEBUG
@@ -1780,7 +1788,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
continue;
}
- auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) {
+ auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B,
+ bool HasSameSign = false) {
LLVM_DEBUG(dbgs() << "Processing fact to add to the system: ";
dumpUnpackedICmp(dbgs(), Pred, A, B); dbgs() << "\n");
if (Info.getCS(CmpInst::isSigned(Pred)).size() > MaxRows) {
@@ -1794,7 +1803,14 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
if (ReproducerModule && DFSInStack.size() > ReproducerCondStack.size())
ReproducerCondStack.emplace_back(Pred, A, B);
- Info.transferToOtherSystem(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
+ // If samesign is present on the ICmp, simply transfer the signed system
+ // to the unsigned system, and viceversa.
+ if (HasSameSign)
+ Info.addFact(CmpInst::getFlippedSignednessPredicate(Pred), A, B,
+ CB.NumIn, CB.NumOut, DFSInStack);
+ else
+ Info.transferToOtherSystem(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
+
if (ReproducerModule && DFSInStack.size() > ReproducerCondStack.size()) {
// Add dummy entries to ReproducerCondStack to keep it in sync with
// DFSInStack.
@@ -1828,7 +1844,9 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
}
Value *A = nullptr, *B = nullptr;
+ bool HasSameSign = false;
if (CB.isConditionFact()) {
+ HasSameSign = CB.Cond.HasSameSign;
Pred = CB.Cond.Pred;
A = CB.Cond.Op0;
B = CB.Cond.Op1;
@@ -1847,10 +1865,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
} else {
bool Matched = match(CB.Inst, m_Intrinsic<Intrinsic::assume>(
m_ICmp(Pred, m_Value(A), m_Value(B))));
+ HasSameSign = cast<ICmpInst>(CB.Inst->getOperand(0))->hasSameSign();
(void)Matched;
assert(Matched && "Must have an assume intrinsic with a icmp operand");
}
- AddFact(Pred, A, B);
+ AddFact(Pred, A, B, HasSameSign);
}
if (ReproducerModule && !ReproducerModule->functions().empty()) {
diff --git a/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll b/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll
new file mode 100644
index 00000000000000..1b155e050de29e
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll
@@ -0,0 +1,305 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+define i1 @idx_known_positive_via_len_1(i8 %len, i8 %idx) {
+; CHECK-LABEL: @idx_known_positive_via_len_1(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp samesign ult i8 [[IDX:%.*]], [[LEN:%.*]]
+; CHECK-NEXT: [[AND_1:%.*]] = and i1 true, [[IDX_ULT_LEN]]
+; CHECK-NEXT: br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
+; CHECK: then.1:
+; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true
+; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[IDX]], 1
+; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_1]]
+; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[LEN]], 1
+; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_2]]
+; CHECK-NEXT: ret i1 [[R_3]]
+; CHECK: else:
+; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: ret i1 [[C_3]]
+;
+entry:
+ %len.pos = icmp samesign uge i8 %len, 0
+ %idx.ult.len = icmp samesign ult i8 %idx, %len
+ %and.1 = and i1 %len.pos, %idx.ult.len
+ br i1 %and.1, label %then.1, label %else
+
+then.1:
+ %t.1 = icmp slt i8 %idx, %len
+ %t.2 = icmp samesign uge i8 %idx, 0
+ %r.1 = xor i1 %t.1, %t.2
+
+ %c.1 = icmp sge i8 %idx, 1
+ %r.2 = xor i1 %r.1, %c.1
+
+ %c.2 = icmp sge i8 %len, 1
+ %r.3 = xor i1 %r.2, %c.2
+ ret i1 %r.3
+
+else:
+ %c.3 = icmp sge i8 %idx, 0
+ ret i1 %c.3
+}
+
+; Like @idx_known_positive_via_len_1, but with a different order of known facts.
+define i1 @idx_known_positive_via_len_2(i8 %len, i8 %idx) {
+; CHECK-LABEL: @idx_known_positive_via_len_2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp samesign ult i8 [[IDX:%.*]], [[LEN:%.*]]
+; CHECK-NEXT: [[AND_1:%.*]] = and i1 true, [[IDX_ULT_LEN]]
+; CHECK-NEXT: br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
+; CHECK: then.1:
+; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true
+; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[IDX]], 1
+; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_1]]
+; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[LEN]], 1
+; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_2]]
+; CHECK-NEXT: ret i1 [[R_3]]
+; CHECK: else:
+; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: ret i1 [[C_3]]
+;
+entry:
+ %idx.ult.len = icmp samesign ult i8 %idx, %len
+ %len.pos = icmp samesign uge i8 %len, 0
+ %and.1 = and i1 %len.pos, %idx.ult.len
+ br i1 %and.1, label %then.1, label %else
+
+then.1:
+ %t.1 = icmp slt i8 %idx, %len
+ %t.2 = icmp samesign uge i8 %idx, 0
+ %r.1 = xor i1 %t.1, %t.2
+
+ %c.1 = icmp sge i8 %idx, 1
+ %r.2 = xor i1 %r.1, %c.1
+
+ %c.2 = icmp sge i8 %len, 1
+ %r.3 = xor i1 %r.2, %c.2
+ ret i1 %r.3
+
+else:
+ %c.3 = icmp sge i8 %idx, 0
+ ret i1 %c.3
+}
+
+
+define i1 @idx_not_known_positive_via_len_uge(i8 %len, i8 %idx) {
+; CHECK-LABEL: @idx_not_known_positive_via_len_uge(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp samesign ult i8 [[IDX:%.*]], [[LEN:%.*]]
+; CHECK-NEXT: br i1 [[IDX_ULT_LEN]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
+; CHECK: then.1:
+; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, [[C_2]]
+; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 1
+; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_3]]
+; CHECK-NEXT: [[C_4:%.*]] = icmp sge i8 [[LEN]], 1
+; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_4]]
+; CHECK-NEXT: ret i1 [[R_3]]
+; CHECK: else:
+; CHECK-NEXT: [[C_5:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: ret i1 [[C_5]]
+;
+entry:
+ %idx.ult.len = icmp samesign ult i8 %idx, %len
+ br i1 %idx.ult.len, label %then.1, label %else
+
+then.1:
+ %c.1 = icmp slt i8 %idx, %len
+ %c.2 = icmp sge i8 %idx, 0
+ %r.1 = xor i1 %c.1, %c.2
+
+ %c.3 = icmp sge i8 %idx, 1
+ %r.2 = xor i1 %r.1, %c.3
+
+ %c.4 = icmp sge i8 %len, 1
+ %r.3 = xor i1 %r.2, %c.4
+ ret i1 %r.3
+
+else:
+ %c.5 = icmp sge i8 %idx, 0
+ ret i1 %c.5
+}
+
+define i1 @idx_not_known_positive_via_len(i8 %len, i8 %idx) {
+; CHECK-LABEL: @idx_not_known_positive_via_len(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp samesign ult i8 [[IDX:%.*]], [[LEN:%.*]]
+; CHECK-NEXT: br i1 [[IDX_ULT_LEN]], label [[THEN_1:%.*]], label [[ELSE:%.*]]
+; CHECK: then.1:
+; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, [[C_2]]
+; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 1
+; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_3]]
+; CHECK-NEXT: [[C_4:%.*]] = icmp sge i8 [[LEN]], 1
+; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_4]]
+; CHECK-NEXT: ret i1 [[R_3]]
+; CHECK: else:
+; CHECK-NEXT: [[C_5:%.*]] = icmp sge i8 [[IDX]], 0
+; CHECK-NEXT: ret i1 [[C_5]]
+;
+entry:
+ %idx.ult.len = icmp samesign ult i8 %idx, %len
+ br i1 %idx.ult.len, label %then.1, label %else
+
+then.1:
+ %c.1 = icmp slt i8 %idx, %len
+ %c.2 = icmp sge i8 %idx, 0
+ %r.1 = xor i1 %c.1, %c.2
+
+ %c.3 = icmp sge i8 %idx, 1
+ %r.2 = xor i1 %r.1, %c.3
+
+ %c.4 = icmp sge i8 %len, 1
+ %r.3 = xor i1 %r.2, %c.4
+ ret i1 %r.3
+
+else:
+ %c.5 = icmp sge i8 %idx, 0
+ ret i1 %c.5
+}
+
+define i1 @ult_signed_pos_constant(i8 %a) {
+; CHECK-LABEL: @ult_signed_pos_constant(
+; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp samesign ult i8 [[A:%.*]], 4
+; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[RES_1:%.*]] = icmp sge i8 [[A]], 0
+; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true
+; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_2]], true
+; CHECK-NEXT: ret i1 [[RES_5]]
+; CHECK: else:
+; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, false
+; CHECK-NEXT: [[C_4:%.*]] = icmp slt i8 [[A]], 5
+; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_4]]
+; CHECK-NEXT: ret i1 [[RES_4]]
+;
+ %a.ult.4 = icmp samesign ult i8 %a, 4
+ br i1 %a.ult.4, label %then, label %else
+
+then:
+ %t.0 = icmp sge i8 %a, 0
+ %t.1 = icmp slt i8 %a, 4
+ %res.1 = xor i1 %t.0, %t.1
+
+ %c.0 = icmp slt i8 %a, 5
+ %res.2 = xor i1 %res.1, %c.0
+ ret i1 %res.2
+
+else:
+ %c.2 = icmp sge i8 %a, 0
+ %c.3 = icmp slt i8 %a, 4
+ %res.3 = xor i1 %c.2, %c.3
+
+ %c.4 = icmp slt i8 %a, 5
+ %res.4 = xor i1 %res.3, %c.4
+
+ ret i1 %res.4
+}
+
+define i1 @ult_signed_neg_constant(i8 %a) {
+; CHECK-LABEL: @ult_signed_neg_constant(
+; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp samesign ult i8 [[A:%.*]], -2
+; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[RES_1:%.*]] = xor i1 false, true
+; CHECK-NEXT: ret i1 [[RES_1]]
+; CHECK: else:
+; CHECK-NEXT: ret i1 false
+;
+ %a.ult.4 = icmp samesign ult i8 %a, -2
+ br i1 %a.ult.4, label %then, label %else
+
+then:
+ %c.0 = icmp sge i8 %a, 0
+ %c.1 = icmp slt i8 %a, -2
+ %res.1 = xor i1 %c.0, %c.1
+ ret i1 %res.1
+
+else:
+ ret i1 0
+}
+
+define i1 @ule_signed_pos_constant_1(i8 %a, i8 %b) {
+; CHECK-LABEL: @ule_signed_pos_constant_1(
+; CHECK-NEXT: [[A_ULE_B:%.*]] = icmp samesign ule i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[A_ULE_B]])
+; CHECK-NEXT: [[SLT_TEST:%.*]] = icmp slt i8 [[A]], [[B]]
+; CHECK-NEXT: [[RESULT_XOR:%.*]] = xor i1 true, [[SLT_TEST]]
+; CHECK-NEXT: ret i1 [[RESULT_XOR]]
+;
+ %a_ule_b = icmp samesign ule i8 %a, %b
+ call void @llvm.assume(i1 %a_ule_b)
+
+ %sle_test = icmp sle i8 %a, %b
+ %slt_test = icmp slt i8 %a, %b
+ %result_xor = xor i1 %sle_test, %slt_test
+
+ ret i1 %result_xor
+}
+
+define i1 @ule_signed_pos_constant_2(i8 %a) {
+; CHECK-LABEL: @ule_signed_pos_constant_2(
+; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp samesign ule i8 [[A:%.*]], 4
+; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]]
+; CHECK: then:
+; CHECK-NEXT: [[RES_1:%.*]] = icmp sge i8 [[A]], 0
+; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true
+; CHECK-NEXT: [[RES_5:%.*]] = xor i1 [[RES_2]], true
+; CHECK-NEXT: ret i1 [[RES_5]]
+; CHECK: else:
+; CHECK-NEXT: [[RES_3:%.*]] = xor i1 true, false
+; CHECK-NEXT: [[C_4:%.*]] = icmp sle i8 [[A]], 5
+; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_4]]
+; CHECK-NEXT: ret i1 [[RES_4]]
+;
+ %a.ult.4 = icmp samesign ule i8 %a, 4
+ br i1 %a.ult.4, label %then, label %else
+
+then:
+ %t.0 = icmp sge i8 %a, 0
+ %t.1 = icmp sle i8 %a, 4
+ %res.1 = xor i1 %t.0, %t.1
+
+ %c.0 = icmp sle i8 %a, 5
+ %res.2 = xor i1 %res.1, %c.0
+ ret i1 %res.2
+
+else:
+ %c.2 = icmp sge i8 %a, 0
+ %c.3 = icmp sle i8 %a, 4
+ %res.3 = xor i1 %c.2, %c.3
+
+ %c.4 = icmp sle i8 %a, 5
+ %res.4 = xor i1 %res.3, %c.4
+
+ ret i1 %res.4
+}
+
+define i1 @uge_assumed_positive_values(i8 %a, i8 %b) {
+; CHECK-LABEL: @uge_assumed_positive_values(
+; CHECK-NEXT: [[A_UGT_B:%.*]] = icmp samesign uge i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[A_UGT_B]])
+; CHECK-NEXT: ret i1 true
+;
+ %a_ugt_b = icmp samesign uge i8 %a, %b
+ call void @llvm.assume(i1 %a_ugt_b)
+
+ %result = icmp sge i8 %a, %b
+
+ ret i1 %result
+}
+
+define i1 @ugt_assumed_positive_values(i8 %a, i8 %b) {
+; CHECK-LABEL: @ugt_assumed_positive_values(
+; CHECK-NEXT: [[A_UGT_B:%.*]] = icmp samesign ugt i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT: call void @llvm.assume(i1 [[A_UGT_B]])
+; CHECK-NEXT: ret i1 true
+;
+ %a_ugt_b = icmp samesign ugt i8 %a, %b
+ call void @llvm.assume(i1 %a_ugt_b)
+
+ %result = icmp sgt i8 %a, %b
+
+ ret i1 %result
+}
|
9e9920d
to
eb4542b
Compare
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.
LG. Please wait for additional approval from other reviewers.
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.
Probably makes sense to land #116867 first and then use it here...
When the samesign flag is present on an icmp, we can transfer all the facts on the unsigned system to the signed system, and vice-versa: we do this by specializing transferToOtherSystem when samesign is present. Supporting samesign in ConstraintElimination has necessitated adding extra information to ConditionFacts, as the information would otherwise be lost.
e546b23
to
2a1dde8
Compare
Rebased for a clean implementation. |
Ping. Is it ready to land? |
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
revert: stacked on SPIRV patches a22578d ConstraintElim: teach fact-transfer about samesign (llvm#115893) Change-Id: If585e91c8cf2ac18d204be5564131956b18f14e8
When the samesign flag is present on an icmp, we can transfer all the facts on the unsigned system to the signed system, and vice-versa: we do this by specializing transferToOtherSystem when samesign is present. Change-Id: I13b0133a5756aa6cf279db0e16c45c498b981428
When the samesign flag is present on an icmp, we can transfer all the facts on the unsigned system to the signed system, and vice-versa: we do this by specializing transferToOtherSystem when samesign is present.