aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp106
1 files changed, 80 insertions, 26 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index a7ddadc25de4..7f5a7b666903 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -173,14 +173,14 @@ std::optional<Value *> InstCombiner::targetSimplifyDemandedUseBitsIntrinsic(
}
std::optional<Value *> InstCombiner::targetSimplifyDemandedVectorEltsIntrinsic(
- IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2,
- APInt &UndefElts3,
+ IntrinsicInst &II, APInt DemandedElts, APInt &PoisonElts,
+ APInt &PoisonElts2, APInt &PoisonElts3,
std::function<void(Instruction *, unsigned, APInt, APInt &)>
SimplifyAndSetOp) {
// Handle target specific intrinsics
if (II.getCalledFunction()->isTargetIntrinsic()) {
return TTI.simplifyDemandedVectorEltsIntrinsic(
- *this, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
+ *this, II, DemandedElts, PoisonElts, PoisonElts2, PoisonElts3,
SimplifyAndSetOp);
}
return std::nullopt;
@@ -1096,6 +1096,54 @@ Value *InstCombinerImpl::foldUsingDistributiveLaws(BinaryOperator &I) {
return SimplifySelectsFeedingBinaryOp(I, LHS, RHS);
}
+std::optional<std::pair<Value *, Value *>>
+InstCombinerImpl::matchSymmetricPhiNodesPair(PHINode *LHS, PHINode *RHS) {
+ if (LHS->getParent() != RHS->getParent())
+ return std::nullopt;
+
+ if (LHS->getNumIncomingValues() < 2)
+ return std::nullopt;
+
+ if (!equal(LHS->blocks(), RHS->blocks()))
+ return std::nullopt;
+
+ Value *L0 = LHS->getIncomingValue(0);
+ Value *R0 = RHS->getIncomingValue(0);
+
+ for (unsigned I = 1, E = LHS->getNumIncomingValues(); I != E; ++I) {
+ Value *L1 = LHS->getIncomingValue(I);
+ Value *R1 = RHS->getIncomingValue(I);
+
+ if ((L0 == L1 && R0 == R1) || (L0 == R1 && R0 == L1))
+ continue;
+
+ return std::nullopt;
+ }
+
+ return std::optional(std::pair(L0, R0));
+}
+
+Value *InstCombinerImpl::SimplifyPhiCommutativeBinaryOp(BinaryOperator &I,
+ Value *Op0,
+ Value *Op1) {
+ assert(I.isCommutative() && "Instruction should be commutative");
+
+ PHINode *LHS = dyn_cast<PHINode>(Op0);
+ PHINode *RHS = dyn_cast<PHINode>(Op1);
+
+ if (!LHS || !RHS)
+ return nullptr;
+
+ if (auto P = matchSymmetricPhiNodesPair(LHS, RHS)) {
+ Value *BI = Builder.CreateBinOp(I.getOpcode(), P->first, P->second);
+ if (auto *BO = dyn_cast<BinaryOperator>(BI))
+ BO->copyIRFlags(&I);
+ return BI;
+ }
+
+ return nullptr;
+}
+
Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
Value *LHS,
Value *RHS) {
@@ -1529,6 +1577,11 @@ Instruction *InstCombinerImpl::foldBinopWithPhiOperands(BinaryOperator &BO) {
BO.getParent() != Phi1->getParent())
return nullptr;
+ if (BO.isCommutative()) {
+ if (Value *V = SimplifyPhiCommutativeBinaryOp(BO, Phi0, Phi1))
+ return replaceInstUsesWith(BO, V);
+ }
+
// Fold if there is at least one specific constant value in phi0 or phi1's
// incoming values that comes from the same block and this specific constant
// value can be used to do optimization for specific binary operator.
@@ -1728,8 +1781,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
// If both arguments of the binary operation are shuffles that use the same
// mask and shuffle within a single vector, move the shuffle after the binop.
- if (match(LHS, m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))) &&
- match(RHS, m_Shuffle(m_Value(V2), m_Undef(), m_SpecificMask(Mask))) &&
+ if (match(LHS, m_Shuffle(m_Value(V1), m_Poison(), m_Mask(Mask))) &&
+ match(RHS, m_Shuffle(m_Value(V2), m_Poison(), m_SpecificMask(Mask))) &&
V1->getType() == V2->getType() &&
(LHS->hasOneUse() || RHS->hasOneUse() || LHS == RHS)) {
// Op(shuffle(V1, Mask), shuffle(V2, Mask)) -> shuffle(Op(V1, V2), Mask)
@@ -1770,9 +1823,9 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
Constant *C;
auto *InstVTy = dyn_cast<FixedVectorType>(Inst.getType());
if (InstVTy &&
- match(&Inst,
- m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))),
- m_ImmConstant(C))) &&
+ match(&Inst, m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Poison(),
+ m_Mask(Mask))),
+ m_ImmConstant(C))) &&
cast<FixedVectorType>(V1->getType())->getNumElements() <=
InstVTy->getNumElements()) {
assert(InstVTy->getScalarType() == V1->getType()->getScalarType() &&
@@ -1787,8 +1840,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
ArrayRef<int> ShMask = Mask;
unsigned SrcVecNumElts =
cast<FixedVectorType>(V1->getType())->getNumElements();
- UndefValue *UndefScalar = UndefValue::get(C->getType()->getScalarType());
- SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, UndefScalar);
+ PoisonValue *PoisonScalar = PoisonValue::get(C->getType()->getScalarType());
+ SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, PoisonScalar);
bool MayChange = true;
unsigned NumElts = InstVTy->getNumElements();
for (unsigned I = 0; I < NumElts; ++I) {
@@ -1801,29 +1854,29 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
// 2. The shuffle needs an element of the constant vector that can't
// be mapped to a new constant vector.
// 3. This is a widening shuffle that copies elements of V1 into the
- // extended elements (extending with undef is allowed).
- if (!CElt || (!isa<UndefValue>(NewCElt) && NewCElt != CElt) ||
+ // extended elements (extending with poison is allowed).
+ if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
I >= SrcVecNumElts) {
MayChange = false;
break;
}
NewVecC[ShMask[I]] = CElt;
}
- // If this is a widening shuffle, we must be able to extend with undef
- // elements. If the original binop does not produce an undef in the high
+ // If this is a widening shuffle, we must be able to extend with poison
+ // elements. If the original binop does not produce a poison in the high
// lanes, then this transform is not safe.
- // Similarly for undef lanes due to the shuffle mask, we can only
- // transform binops that preserve undef.
- // TODO: We could shuffle those non-undef constant values into the
- // result by using a constant vector (rather than an undef vector)
+ // Similarly for poison lanes due to the shuffle mask, we can only
+ // transform binops that preserve poison.
+ // TODO: We could shuffle those non-poison constant values into the
+ // result by using a constant vector (rather than an poison vector)
// as operand 1 of the new binop, but that might be too aggressive
// for target-independent shuffle creation.
if (I >= SrcVecNumElts || ShMask[I] < 0) {
- Constant *MaybeUndef =
+ Constant *MaybePoison =
ConstOp1
- ? ConstantFoldBinaryOpOperands(Opcode, UndefScalar, CElt, DL)
- : ConstantFoldBinaryOpOperands(Opcode, CElt, UndefScalar, DL);
- if (!MaybeUndef || !match(MaybeUndef, m_Undef())) {
+ ? ConstantFoldBinaryOpOperands(Opcode, PoisonScalar, CElt, DL)
+ : ConstantFoldBinaryOpOperands(Opcode, CElt, PoisonScalar, DL);
+ if (!MaybePoison || !isa<PoisonValue>(MaybePoison)) {
MayChange = false;
break;
}
@@ -1831,9 +1884,10 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
}
if (MayChange) {
Constant *NewC = ConstantVector::get(NewVecC);
- // It may not be safe to execute a binop on a vector with undef elements
+ // It may not be safe to execute a binop on a vector with poison elements
// because the entire instruction can be folded to undef or create poison
// that did not exist in the original code.
+ // TODO: The shift case should not be necessary.
if (Inst.isIntDivRem() || (Inst.isShift() && ConstOp1))
NewC = getSafeVectorConstantForBinop(Opcode, NewC, ConstOp1);
@@ -2241,10 +2295,10 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// compile-time.
if (auto *GEPFVTy = dyn_cast<FixedVectorType>(GEPType)) {
auto VWidth = GEPFVTy->getNumElements();
- APInt UndefElts(VWidth, 0);
+ APInt PoisonElts(VWidth, 0);
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
if (Value *V = SimplifyDemandedVectorElts(&GEP, AllOnesEltMask,
- UndefElts)) {
+ PoisonElts)) {
if (V != &GEP)
return replaceInstUsesWith(GEP, V);
return &GEP;
@@ -2462,7 +2516,7 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Idx2);
}
ConstantInt *C;
- if (match(GEP.getOperand(1), m_OneUse(m_SExt(m_OneUse(m_NSWAdd(
+ if (match(GEP.getOperand(1), m_OneUse(m_SExtLike(m_OneUse(m_NSWAdd(
m_Value(Idx1), m_ConstantInt(C))))))) {
// %add = add nsw i32 %idx1, idx2
// %sidx = sext i32 %add to i64