@@ -108,6 +108,7 @@ class VectorCombine {
108
108
Instruction &I);
109
109
bool foldExtractExtract (Instruction &I);
110
110
bool foldInsExtFNeg (Instruction &I);
111
+ bool foldInsExtBinop (Instruction &I);
111
112
bool foldInsExtVectorToShuffle (Instruction &I);
112
113
bool foldBitcastShuffle (Instruction &I);
113
114
bool scalarizeBinopOrCmp (Instruction &I);
@@ -738,6 +739,64 @@ bool VectorCombine::foldInsExtFNeg(Instruction &I) {
738
739
return true ;
739
740
}
740
741
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
+
741
800
// / If this is a bitcast of a shuffle, try to bitcast the source vector to the
742
801
// / destination type followed by shuffle. This can enable further transforms by
743
802
// / moving bitcasts or shuffles together.
@@ -3206,6 +3265,7 @@ bool VectorCombine::run() {
3206
3265
switch (Opcode) {
3207
3266
case Instruction::InsertElement:
3208
3267
MadeChange |= foldInsExtFNeg (I);
3268
+ MadeChange |= foldInsExtBinop (I);
3209
3269
MadeChange |= foldInsExtVectorToShuffle (I);
3210
3270
break ;
3211
3271
case Instruction::ShuffleVector:
0 commit comments