Skip to content

Commit 0f78da8

Browse files
committed
[LVI] Thread binop over select with constant arms
1 parent 07a545f commit 0f78da8

File tree

2 files changed

+59
-4
lines changed

2 files changed

+59
-4
lines changed

llvm/lib/Analysis/LazyValueInfo.cpp

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -924,18 +924,74 @@ LazyValueInfoImpl::solveBlockValueBinaryOpImpl(
924924
Instruction *I, BasicBlock *BB,
925925
std::function<ConstantRange(const ConstantRange &, const ConstantRange &)>
926926
OpFn) {
927+
Value *LHS = I->getOperand(0);
928+
Value *RHS = I->getOperand(1);
929+
930+
auto GetValueFromCondition =
931+
[&](Value *V, Value *Cond,
932+
bool CondIsTrue) -> std::optional<ConstantRange> {
933+
std::optional<ValueLatticeElement> OptVal = getBlockValue(V, BB, I);
934+
if (!OptVal)
935+
return std::nullopt;
936+
return OptVal->asConstantRange(V->getType());
937+
};
938+
939+
auto ThreadBinOpOverSelect =
940+
[&](Value *X, const ConstantRange &CRX, SelectInst *Y,
941+
bool XIsLHS) -> std::optional<ValueLatticeElement> {
942+
Value *Cond = Y->getCondition();
943+
// Only handle selects with constant values.
944+
Constant *TrueC = dyn_cast<Constant>(Y->getTrueValue());
945+
if (!TrueC)
946+
return std::nullopt;
947+
Constant *FalseC = dyn_cast<Constant>(Y->getFalseValue());
948+
if (!FalseC)
949+
return std::nullopt;
950+
if (!isGuaranteedNotToBeUndef(Cond, AC))
951+
return std::nullopt;
952+
953+
ConstantRange TrueX =
954+
CRX.intersectWith(getValueFromCondition(X, Cond, /*CondIsTrue=*/true,
955+
/*UseBlockValue=*/false)
956+
->asConstantRange(X->getType()));
957+
ConstantRange FalseX =
958+
CRX.intersectWith(getValueFromCondition(X, Cond, /*CondIsTrue=*/false,
959+
/*UseBlockValue=*/false)
960+
->asConstantRange(X->getType()));
961+
ConstantRange TrueY = TrueC->toConstantRange();
962+
ConstantRange FalseY = FalseC->toConstantRange();
963+
964+
if (XIsLHS)
965+
return ValueLatticeElement::getRange(
966+
OpFn(TrueX, TrueY).unionWith(OpFn(FalseX, FalseY)));
967+
return ValueLatticeElement::getRange(
968+
OpFn(TrueY, TrueX).unionWith(OpFn(FalseY, FalseX)));
969+
};
970+
927971
// Figure out the ranges of the operands. If that fails, use a
928972
// conservative range, but apply the transfer rule anyways. This
929973
// lets us pick up facts from expressions like "and i32 (call i32
930974
// @foo()), 32"
931-
std::optional<ConstantRange> LHSRes = getRangeFor(I->getOperand(0), I, BB);
975+
std::optional<ConstantRange> LHSRes = getRangeFor(LHS, I, BB);
932976
if (!LHSRes)
933977
return std::nullopt;
934978

935-
std::optional<ConstantRange> RHSRes = getRangeFor(I->getOperand(1), I, BB);
979+
// Try to thread binop over rhs select
980+
if (auto *SI = dyn_cast<SelectInst>(RHS)) {
981+
if (auto Res = ThreadBinOpOverSelect(LHS, *LHSRes, SI, /*XIsLHS=*/true))
982+
return *Res;
983+
}
984+
985+
std::optional<ConstantRange> RHSRes = getRangeFor(RHS, I, BB);
936986
if (!RHSRes)
937987
return std::nullopt;
938988

989+
// Try to thread binop over lhs select
990+
if (auto *SI = dyn_cast<SelectInst>(LHS)) {
991+
if (auto Res = ThreadBinOpOverSelect(RHS, *RHSRes, SI, /*XIsLHS=*/false))
992+
return *Res;
993+
}
994+
939995
const ConstantRange &LHSRange = *LHSRes;
940996
const ConstantRange &RHSRange = *RHSRes;
941997
return ValueLatticeElement::getRange(OpFn(LHSRange, RHSRange));

llvm/test/Transforms/CorrelatedValuePropagation/cond-at-use.ll

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -638,8 +638,7 @@ define i1 @test_icmp_mod(i64 noundef %x) {
638638
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[REM]], 0
639639
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i64 86400, i64 0
640640
; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[COND]], [[REM]]
641-
; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i64 [[ADD]], 86399
642-
; CHECK-NEXT: ret i1 [[CMP1]]
641+
; CHECK-NEXT: ret i1 false
643642
;
644643
entry:
645644
%rem = srem i64 %x, 86400

0 commit comments

Comments
 (0)