Skip to content

Commit e5471c3

Browse files
committed
Handle select
1 parent 4d93396 commit e5471c3

File tree

1 file changed

+75
-9
lines changed

1 file changed

+75
-9
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

+75-9
Original file line numberDiff line numberDiff line change
@@ -5810,7 +5810,8 @@ static Instruction *foldICmpPow2Test(ICmpInst &I,
58105810

58115811
/// Find all possible pairs (BinOp, RHS) that BinOp V, RHS can be simplified.
58125812
using OffsetOp = std::pair<Instruction::BinaryOps, Value *>;
5813-
static void collectOffsetOp(Value *V, SmallVectorImpl<OffsetOp> &Offsets) {
5813+
static void collectOffsetOp(Value *V, SmallVectorImpl<OffsetOp> &Offsets,
5814+
bool AllowRecursion) {
58145815
Instruction *Inst = dyn_cast<Instruction>(V);
58155816
if (!Inst)
58165817
return;
@@ -5826,11 +5827,51 @@ static void collectOffsetOp(Value *V, SmallVectorImpl<OffsetOp> &Offsets) {
58265827
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(1));
58275828
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(0));
58285829
break;
5830+
case Instruction::Select:
5831+
if (AllowRecursion) {
5832+
Value *TrueV = Inst->getOperand(1);
5833+
if (TrueV->hasOneUse())
5834+
collectOffsetOp(TrueV, Offsets, /*AllowRecursion=*/false);
5835+
Value *FalseV = Inst->getOperand(2);
5836+
if (FalseV->hasOneUse())
5837+
collectOffsetOp(FalseV, Offsets, /*AllowRecursion=*/false);
5838+
}
5839+
break;
58295840
default:
58305841
break;
58315842
}
58325843
}
58335844

5845+
enum class OffsetKind { Invalid, Value, Select };
5846+
5847+
struct OffsetResult {
5848+
OffsetKind Kind;
5849+
Value *V0, *V1, *V2;
5850+
5851+
static OffsetResult invalid() {
5852+
return {OffsetKind::Invalid, nullptr, nullptr, nullptr};
5853+
}
5854+
static OffsetResult value(Value *V) {
5855+
return {OffsetKind::Value, V, nullptr, nullptr};
5856+
}
5857+
static OffsetResult select(Value *Cond, Value *TrueV, Value *FalseV) {
5858+
return {OffsetKind::Select, Cond, TrueV, FalseV};
5859+
}
5860+
bool isValid() const { return Kind != OffsetKind::Invalid; }
5861+
Value *materialize(InstCombiner::BuilderTy &Builder) const {
5862+
switch (Kind) {
5863+
case OffsetKind::Invalid:
5864+
llvm_unreachable("Invalid offset result");
5865+
case OffsetKind::Value:
5866+
return V0;
5867+
case OffsetKind::Select:
5868+
return Builder.CreateSelect(V0, V1, V2);
5869+
default:
5870+
llvm_unreachable("Unknown offset result kind");
5871+
}
5872+
}
5873+
};
5874+
58345875
/// Offset both sides of an equality icmp to see if we can save some
58355876
/// instructions. icmp eq/ne X, Y -> icmp eq/ne X op C, Y op C Note: This
58365877
/// operation should not introduce poison.
@@ -5844,22 +5885,47 @@ static Instruction *foldICmpEqualityWithOffset(ICmpInst &I,
58445885

58455886
SmallVector<OffsetOp, 4> OffsetOps;
58465887
if (Op0->hasOneUse())
5847-
collectOffsetOp(Op0, OffsetOps);
5888+
collectOffsetOp(Op0, OffsetOps, /*AllowRecursion=*/true);
58485889
if (Op1->hasOneUse())
5849-
collectOffsetOp(Op1, OffsetOps);
5890+
collectOffsetOp(Op1, OffsetOps, /*AllowRecursion=*/true);
5891+
5892+
auto ApplyOffsetImpl = [&](Value *V, unsigned BinOpc, Value *RHS) -> Value * {
5893+
Value *Simplified = simplifyBinOp(BinOpc, V, RHS, SQ);
5894+
// Avoid infinite loops by checking if RHS is an identity for the BinOp.
5895+
if (!Simplified || Simplified == V)
5896+
return nullptr;
5897+
return Simplified;
5898+
};
5899+
5900+
auto ApplyOffset = [&](Value *V, unsigned BinOpc,
5901+
Value *RHS) -> OffsetResult {
5902+
if (auto *Sel = dyn_cast<SelectInst>(V)) {
5903+
Value *TrueVal = ApplyOffsetImpl(Sel->getTrueValue(), BinOpc, RHS);
5904+
if (!TrueVal)
5905+
return OffsetResult::invalid();
5906+
Value *FalseVal = ApplyOffsetImpl(Sel->getFalseValue(), BinOpc, RHS);
5907+
if (!FalseVal)
5908+
return OffsetResult::invalid();
5909+
return OffsetResult::select(Sel->getCondition(), TrueVal, FalseVal);
5910+
} else if (Value *Simplified = ApplyOffsetImpl(V, BinOpc, RHS)) {
5911+
return OffsetResult::value(Simplified);
5912+
}
5913+
return OffsetResult::invalid();
5914+
};
5915+
58505916
for (auto [BinOp, RHS] : OffsetOps) {
58515917
auto BinOpc = static_cast<unsigned>(BinOp);
58525918

5853-
Value *Simplified0 = simplifyBinOp(BinOpc, Op0, RHS, SQ);
5854-
if (!Simplified0 || Simplified0 == Op0)
5919+
auto Op0Result = ApplyOffset(Op0, BinOpc, RHS);
5920+
if (!Op0Result.isValid())
58555921
continue;
5856-
5857-
Value *Simplified1 = simplifyBinOp(BinOpc, Op1, RHS, SQ);
5858-
if (!Simplified1 || Simplified1 == Op1)
5922+
auto Op1Result = ApplyOffset(Op1, BinOpc, RHS);
5923+
if (!Op1Result.isValid())
58595924
continue;
58605925

58615926
return new ICmpInst(static_cast<ICmpInst::Predicate>(I.getPredicate()),
5862-
Simplified0, Simplified1);
5927+
Op0Result.materialize(Builder),
5928+
Op1Result.materialize(Builder));
58635929
}
58645930

58655931
return nullptr;

0 commit comments

Comments
 (0)