Skip to content

Commit b006ef1

Browse files
committed
[WIP][VectorCombine] Fold insert(binop(x,y),binop(a,b),idx) --> binop(insert(x,a,idx),insert(x,a,idx))
Add foldInsExtBinop fold to cleanup missed vectorization cases which can happen on targets with cheap insert/extract instructions which prevent foldExtractExtract (binop(extract(x),extract(y)) -> extract(binop(x,shuffle(y)))) from helping with the merge. WIP - still need to add VectorCombine specific tests
1 parent 88e0014 commit b006ef1

File tree

4 files changed

+169
-260
lines changed

4 files changed

+169
-260
lines changed

llvm/lib/Transforms/Vectorize/VectorCombine.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ class VectorCombine {
108108
Instruction &I);
109109
bool foldExtractExtract(Instruction &I);
110110
bool foldInsExtFNeg(Instruction &I);
111+
bool foldInsExtBinop(Instruction &I);
111112
bool foldInsExtVectorToShuffle(Instruction &I);
112113
bool foldBitcastShuffle(Instruction &I);
113114
bool scalarizeBinopOrCmp(Instruction &I);
@@ -738,6 +739,64 @@ bool VectorCombine::foldInsExtFNeg(Instruction &I) {
738739
return true;
739740
}
740741

742+
/// Try to fold insert(binop(x,y),binop(a,b),idx)
743+
/// --> binop(insert(x,a,idx),insert(x,a,idx))
744+
bool VectorCombine::foldInsExtBinop(Instruction &I) {
745+
BinaryOperator *VecBinOp, *SclBinOp;
746+
uint64_t Index;
747+
if (!match(&I,
748+
m_InsertElt(m_OneUse(m_BinOp(VecBinOp)),
749+
m_OneUse(m_BinOp(SclBinOp)), m_ConstantInt(Index))))
750+
return false;
751+
752+
// TODO: Add support for addlike etc.
753+
Instruction::BinaryOps BinOpcode = VecBinOp->getOpcode();
754+
if (BinOpcode != SclBinOp->getOpcode())
755+
return false;
756+
757+
auto *ResultTy = dyn_cast<FixedVectorType>(I.getType());
758+
if (!ResultTy)
759+
return false;
760+
761+
// TODO: Attempt to detect m_ExtractElt for scalar operands and convert to
762+
// shuffle?
763+
764+
InstructionCost OldCost = TTI.getInstructionCost(&I, CostKind) +
765+
TTI.getInstructionCost(VecBinOp, CostKind) +
766+
TTI.getInstructionCost(SclBinOp, CostKind);
767+
InstructionCost NewCost =
768+
TTI.getArithmeticInstrCost(BinOpcode, ResultTy, CostKind) +
769+
TTI.getVectorInstrCost(Instruction::InsertElement, ResultTy, CostKind,
770+
Index, VecBinOp->getOperand(0),
771+
SclBinOp->getOperand(0)) +
772+
TTI.getVectorInstrCost(Instruction::InsertElement, ResultTy, CostKind,
773+
Index, VecBinOp->getOperand(1),
774+
SclBinOp->getOperand(1));
775+
776+
LLVM_DEBUG(dbgs() << "Found an insertion of two binops: " << I
777+
<< "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
778+
<< "\n");
779+
if (NewCost > OldCost)
780+
return false;
781+
782+
Value *NewIns0 = Builder.CreateInsertElement(VecBinOp->getOperand(0),
783+
SclBinOp->getOperand(0), Index);
784+
Value *NewIns1 = Builder.CreateInsertElement(VecBinOp->getOperand(1),
785+
SclBinOp->getOperand(1), Index);
786+
Value *NewBO = Builder.CreateBinOp(BinOpcode, NewIns0, NewIns1);
787+
788+
// Intersect flags from the old binops.
789+
if (auto *NewInst = dyn_cast<Instruction>(NewBO)) {
790+
NewInst->copyIRFlags(VecBinOp);
791+
NewInst->andIRFlags(SclBinOp);
792+
}
793+
794+
Worklist.pushValue(NewIns0);
795+
Worklist.pushValue(NewIns1);
796+
replaceValue(I, *NewBO);
797+
return true;
798+
}
799+
741800
/// If this is a bitcast of a shuffle, try to bitcast the source vector to the
742801
/// destination type followed by shuffle. This can enable further transforms by
743802
/// moving bitcasts or shuffles together.
@@ -3206,6 +3265,7 @@ bool VectorCombine::run() {
32063265
switch (Opcode) {
32073266
case Instruction::InsertElement:
32083267
MadeChange |= foldInsExtFNeg(I);
3268+
MadeChange |= foldInsExtBinop(I);
32093269
MadeChange |= foldInsExtVectorToShuffle(I);
32103270
break;
32113271
case Instruction::ShuffleVector:

0 commit comments

Comments
 (0)