Skip to content

Commit 351961c

Browse files
committed
use foldICmpEqualityWithOffset
1 parent 528aa2b commit 351961c

File tree

5 files changed

+104
-436
lines changed

5 files changed

+104
-436
lines changed

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2557,6 +2557,14 @@ static Value *simplifyXorInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
25572557
return X;
25582558
}
25592559

2560+
// (xor (or disjoint X, Y), Y) -> X
2561+
{
2562+
Value *X;
2563+
if (match(Op0, m_c_DisjointOr(m_Value(X), m_Specific(Op1))) ||
2564+
match(Op1, m_c_DisjointOr(m_Value(X), m_Specific(Op0))))
2565+
return X;
2566+
}
2567+
25602568
return nullptr;
25612569
}
25622570

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 18 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -4332,98 +4332,6 @@ Instruction *InstCombinerImpl::foldICmpInstWithConstantNotInt(ICmpInst &I) {
43324332
return nullptr;
43334333
}
43344334

4335-
/// If the APInt C has the same invertible function with Operator RefOp in Pred,
4336-
/// return the operands of the function corresponding to each input. Otherwise,
4337-
/// return std::nullopt. This is equivalent to saying that Op1 pred Op2 is true
4338-
/// exactly when the specified pair of RefOp pred C is true.
4339-
/// alive2: https://alive2.llvm.org/ce/z/4jniEb
4340-
static std::optional<std::pair<Value *, Value *>>
4341-
getInvertibleOperandsWithPredicte(const Operator *RefOp, const APInt C,
4342-
CmpInst::Predicate Pred) {
4343-
APInt Op1C;
4344-
// for BinaryOperator just handle RefOp with constant Operand(1)
4345-
if (isa<BinaryOperator>(RefOp)) {
4346-
if (isa<ConstantInt>(RefOp->getOperand(1)))
4347-
Op1C = cast<ConstantInt>(RefOp->getOperand(1))->getValue();
4348-
else
4349-
return std::nullopt;
4350-
}
4351-
4352-
auto getOperands = [&](APInt A) -> auto {
4353-
return std::make_pair(RefOp->getOperand(0),
4354-
ConstantInt::get(RefOp->getOperand(0)->getType(), A));
4355-
};
4356-
switch (RefOp->getOpcode()) {
4357-
default:
4358-
break;
4359-
case Instruction::Or:
4360-
if (cast<PossiblyDisjointInst>(RefOp)->isDisjoint() && ((C & Op1C) == Op1C))
4361-
return getOperands(C ^ Op1C);
4362-
break;
4363-
case Instruction::Add: {
4364-
// TODO: add/sub could support nsw/nuw for scmp/ucmp
4365-
if (CmpInst::isEquality(Pred))
4366-
return getOperands(C - Op1C);
4367-
break;
4368-
}
4369-
case Instruction::Xor: {
4370-
if (CmpInst::isEquality(Pred))
4371-
return getOperands(C ^ Op1C);
4372-
break;
4373-
}
4374-
case Instruction::Sub: {
4375-
if (CmpInst::isEquality(Pred))
4376-
return getOperands(C + Op1C);
4377-
break;
4378-
}
4379-
// alive2: https://alive2.llvm.org/ce/z/WPQznV
4380-
case Instruction::Shl: {
4381-
// Z = shl nsw X, Y <=> X = ashr exact Z, Y
4382-
// Z = shl nuw X, Y <=> X = lshr exact Z, Y
4383-
if (C.ashr(Op1C).shl(Op1C) == C) {
4384-
auto *OBO1 = cast<OverflowingBinaryOperator>(RefOp);
4385-
if (OBO1->hasNoSignedWrap())
4386-
return getOperands(C.ashr(Op1C));
4387-
else if (OBO1->hasNoUnsignedWrap() && !ICmpInst::isSigned(Pred))
4388-
return getOperands(C.lshr(Op1C));
4389-
}
4390-
break;
4391-
}
4392-
case Instruction::AShr: {
4393-
// Z = ashr exact X, Y <=> X = shl nsw Z, Y
4394-
auto *PEO1 = cast<PossiblyExactOperator>(RefOp);
4395-
if (PEO1->isExact() && C.shl(Op1C).ashr(Op1C) == C)
4396-
return getOperands(C.shl(Op1C));
4397-
break;
4398-
}
4399-
case Instruction::LShr: {
4400-
// Z = lshr exact X, Y <=> X = shl nuw Z, Y
4401-
auto *PEO1 = cast<PossiblyExactOperator>(RefOp);
4402-
if (PEO1->isExact() && C.shl(Op1C).lshr(Op1C) == C &&
4403-
!ICmpInst::isSigned(Pred))
4404-
return getOperands(C.shl(Op1C));
4405-
break;
4406-
}
4407-
case Instruction::SExt: {
4408-
unsigned NumBits = RefOp->getType()->getScalarSizeInBits();
4409-
unsigned NumBitsOp0 =
4410-
RefOp->getOperand(0)->getType()->getScalarSizeInBits();
4411-
if (C.trunc(NumBitsOp0).sext(NumBits) == C)
4412-
return getOperands(C.trunc(NumBitsOp0));
4413-
break;
4414-
}
4415-
case Instruction::ZExt: {
4416-
unsigned NumBits = RefOp->getType()->getScalarSizeInBits();
4417-
unsigned NumBitsOp0 =
4418-
RefOp->getOperand(0)->getType()->getScalarSizeInBits();
4419-
if (C.trunc(NumBitsOp0).zext(NumBits) == C && !ICmpInst::isSigned(Pred))
4420-
return getOperands(C.trunc(NumBitsOp0));
4421-
break;
4422-
}
4423-
}
4424-
return std::nullopt;
4425-
}
4426-
44274335
Instruction *InstCombinerImpl::foldSelectICmp(CmpPredicate Pred, SelectInst *SI,
44284336
Value *RHS, const ICmpInst &I) {
44294337
// Try to fold the comparison into the select arms, which will cause the
@@ -4483,24 +4391,6 @@ Instruction *InstCombinerImpl::foldSelectICmp(CmpPredicate Pred, SelectInst *SI,
44834391
return SelectInst::Create(SI->getOperand(0), Op1, Op2);
44844392
}
44854393

4486-
// fold select with constants and invertible op
4487-
Value *Cond;
4488-
const APInt *C1, *C2;
4489-
auto *RHSOp = dyn_cast<Operator>(RHS);
4490-
if (RHSOp &&
4491-
match(SI, m_OneUse(m_Select(m_Value(Cond), m_APInt(C1), m_APInt(C2))))) {
4492-
if (auto Values0 = getInvertibleOperandsWithPredicte(RHSOp, *C1, Pred)) {
4493-
if (auto Values1 = getInvertibleOperandsWithPredicte(RHSOp, *C2, Pred)) {
4494-
assert(Values0->first == Values1->first &&
4495-
"Invertible Operand0 mismatch");
4496-
auto *NewSI = Builder.CreateSelect(Cond, Values0->second,
4497-
Values1->second, SI->getName());
4498-
return ICmpInst::Create(Instruction::ICmp, Pred, NewSI, Values0->first,
4499-
I.getName());
4500-
}
4501-
}
4502-
}
4503-
45044394
return nullptr;
45054395
}
45064396

@@ -5976,6 +5866,24 @@ static void collectOffsetOp(Value *V, SmallVectorImpl<OffsetOp> &Offsets,
59765866
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(1));
59775867
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(0));
59785868
break;
5869+
case Instruction::Or:
5870+
if (cast<PossiblyDisjointInst>(Inst)->isDisjoint())
5871+
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(1));
5872+
Offsets.emplace_back(Instruction::Xor, Inst->getOperand(0));
5873+
break;
5874+
case Instruction::Shl:
5875+
if (auto *OBO = cast<OverflowingBinaryOperator>(Inst)) {
5876+
if (OBO->hasNoSignedWrap())
5877+
Offsets.emplace_back(Instruction::AShr, Inst->getOperand(1));
5878+
else if (OBO->hasNoUnsignedWrap())
5879+
Offsets.emplace_back(Instruction::LShr, Inst->getOperand(1));
5880+
}
5881+
break;
5882+
case Instruction::AShr:
5883+
case Instruction::LShr:
5884+
if (auto *PEO = cast<PossiblyExactOperator>(Inst); PEO && PEO->isExact())
5885+
Offsets.emplace_back(Instruction::Shl, Inst->getOperand(1));
5886+
break;
59795887
case Instruction::Select:
59805888
if (AllowRecursion) {
59815889
collectOffsetOp(Inst->getOperand(1), Offsets, /*AllowRecursion=*/false);

0 commit comments

Comments
 (0)