@@ -943,56 +943,98 @@ static void recursivelyDeleteDeadRecipes(VPValue *V) {
943943 }
944944}
945945
946+ // / Get any instruction opcode or intrinsic ID data embedded in recipe \p R.
947+ // / Returns an optional pair, where the first element indicates whether it is
948+ // / an intrinsic ID.
949+ static std::optional<std::pair<bool , unsigned >>
950+ getOpcodeOrIntrinsicID (const VPSingleDefRecipe *R) {
951+ return TypeSwitch<const VPSingleDefRecipe *,
952+ std::optional<std::pair<bool , unsigned >>>(R)
953+ .Case <VPInstruction, VPWidenRecipe, VPWidenCastRecipe,
954+ VPWidenSelectRecipe, VPWidenGEPRecipe, VPReplicateRecipe>(
955+ [](auto *I) { return std::make_pair (false , I->getOpcode ()); })
956+ .Case <VPWidenIntrinsicRecipe>([](auto *I) {
957+ return std::make_pair (true , I->getVectorIntrinsicID ());
958+ })
959+ .Case <VPVectorPointerRecipe, VPPredInstPHIRecipe>([](auto *I) {
960+ // For recipes that do not directly map to LLVM IR instructions,
961+ // assign opcodes after the last VPInstruction opcode (which is also
962+ // after the last IR Instruction opcode), based on the VPDefID.
963+ return std::make_pair (false ,
964+ VPInstruction::OpsEnd + 1 + I->getVPDefID ());
965+ })
966+ .Default ([](auto *) { return std::nullopt ; });
967+ }
968+
946969// / Try to fold \p R using InstSimplifyFolder. Will succeed and return a
947- // / non-nullptr Value for a handled \p Opcode if corresponding \p Operands are
948- // / foldable live-ins.
949- static Value *tryToFoldLiveIns (const VPRecipeBase &R, unsigned Opcode,
950- ArrayRef<VPValue *> Operands,
951- const DataLayout &DL, VPTypeAnalysis &TypeInfo) {
970+ // / non-nullptr VPValue for a handled opcode or intrinsic ID if corresponding \p
971+ // / Operands are foldable live-ins.
972+ static VPValue *tryToFoldLiveIns (VPSingleDefRecipe &R,
973+ ArrayRef<VPValue *> Operands,
974+ const DataLayout &DL,
975+ VPTypeAnalysis &TypeInfo) {
976+ auto OpcodeOrIID = getOpcodeOrIntrinsicID (&R);
977+ if (!OpcodeOrIID)
978+ return nullptr ;
979+
952980 SmallVector<Value *, 4 > Ops;
953981 for (VPValue *Op : Operands) {
954982 if (!Op->isLiveIn () || !Op->getLiveInIRValue ())
955983 return nullptr ;
956984 Ops.push_back (Op->getLiveInIRValue ());
957985 }
958986
959- InstSimplifyFolder Folder (DL);
960- if (Instruction::isBinaryOp (Opcode))
961- return Folder.FoldBinOp (static_cast <Instruction::BinaryOps>(Opcode), Ops[0 ],
987+ auto FoldToIRValue = [&]() -> Value * {
988+ InstSimplifyFolder Folder (DL);
989+ if (OpcodeOrIID->first ) {
990+ if (R.getNumOperands () != 2 )
991+ return nullptr ;
992+ unsigned ID = OpcodeOrIID->second ;
993+ return Folder.FoldBinaryIntrinsic (ID, Ops[0 ], Ops[1 ],
994+ TypeInfo.inferScalarType (&R));
995+ }
996+ unsigned Opcode = OpcodeOrIID->second ;
997+ if (Instruction::isBinaryOp (Opcode))
998+ return Folder.FoldBinOp (static_cast <Instruction::BinaryOps>(Opcode),
999+ Ops[0 ], Ops[1 ]);
1000+ if (Instruction::isCast (Opcode))
1001+ return Folder.FoldCast (static_cast <Instruction::CastOps>(Opcode), Ops[0 ],
1002+ TypeInfo.inferScalarType (R.getVPSingleValue ()));
1003+ switch (Opcode) {
1004+ case VPInstruction::LogicalAnd:
1005+ return Folder.FoldSelect (Ops[0 ], Ops[1 ],
1006+ ConstantInt::getNullValue (Ops[1 ]->getType ()));
1007+ case VPInstruction::Not:
1008+ return Folder.FoldBinOp (Instruction::BinaryOps::Xor, Ops[0 ],
1009+ Constant::getAllOnesValue (Ops[0 ]->getType ()));
1010+ case Instruction::Select:
1011+ return Folder.FoldSelect (Ops[0 ], Ops[1 ], Ops[2 ]);
1012+ case Instruction::ICmp:
1013+ case Instruction::FCmp:
1014+ return Folder.FoldCmp (cast<VPRecipeWithIRFlags>(R).getPredicate (), Ops[0 ],
9621015 Ops[1 ]);
963- if (Instruction::isCast (Opcode))
964- return Folder.FoldCast (static_cast <Instruction::CastOps>(Opcode), Ops[0 ],
965- TypeInfo.inferScalarType (R.getVPSingleValue ()));
966- switch (Opcode) {
967- case VPInstruction::LogicalAnd:
968- return Folder.FoldSelect (Ops[0 ], Ops[1 ],
969- ConstantInt::getNullValue (Ops[1 ]->getType ()));
970- case VPInstruction::Not:
971- return Folder.FoldBinOp (Instruction::BinaryOps::Xor, Ops[0 ],
972- Constant::getAllOnesValue (Ops[0 ]->getType ()));
973- case Instruction::Select:
974- return Folder.FoldSelect (Ops[0 ], Ops[1 ], Ops[2 ]);
975- case Instruction::ICmp:
976- case Instruction::FCmp:
977- return Folder.FoldCmp (cast<VPRecipeWithIRFlags>(R).getPredicate (), Ops[0 ],
978- Ops[1 ]);
979- case Instruction::GetElementPtr: {
980- auto &RFlags = cast<VPRecipeWithIRFlags>(R);
981- auto *GEP = cast<GetElementPtrInst>(RFlags.getUnderlyingInstr ());
982- return Folder.FoldGEP (GEP->getSourceElementType (), Ops[0 ], drop_begin (Ops),
983- RFlags.getGEPNoWrapFlags ());
984- }
985- case VPInstruction::PtrAdd:
986- case VPInstruction::WidePtrAdd:
987- return Folder.FoldGEP (IntegerType::getInt8Ty (TypeInfo.getContext ()), Ops[0 ],
988- Ops[1 ],
989- cast<VPRecipeWithIRFlags>(R).getGEPNoWrapFlags ());
990- // An extract of a live-in is an extract of a broadcast, so return the
991- // broadcasted element.
992- case Instruction::ExtractElement:
993- assert (!Ops[0 ]->getType ()->isVectorTy () && " Live-ins should be scalar" );
994- return Ops[0 ];
995- }
1016+ case Instruction::GetElementPtr: {
1017+ auto &RFlags = cast<VPRecipeWithIRFlags>(R);
1018+ auto *GEP = cast<GetElementPtrInst>(RFlags.getUnderlyingInstr ());
1019+ return Folder.FoldGEP (GEP->getSourceElementType (), Ops[0 ],
1020+ drop_begin (Ops), RFlags.getGEPNoWrapFlags ());
1021+ }
1022+ case VPInstruction::PtrAdd:
1023+ case VPInstruction::WidePtrAdd:
1024+ return Folder.FoldGEP (IntegerType::getInt8Ty (TypeInfo.getContext ()),
1025+ Ops[0 ], Ops[1 ],
1026+ cast<VPRecipeWithIRFlags>(R).getGEPNoWrapFlags ());
1027+ // An extract of a live-in is an extract of a broadcast, so return the
1028+ // broadcasted element.
1029+ case Instruction::ExtractElement:
1030+ assert (!Ops[0 ]->getType ()->isVectorTy () && " Live-ins should be scalar" );
1031+ return Ops[0 ];
1032+ }
1033+ return nullptr ;
1034+ };
1035+
1036+ if (Value *V = FoldToIRValue ())
1037+ return R.getParent ()->getPlan ()->getOrAddLiveIn (V);
9961038 return nullptr ;
9971039}
9981040
@@ -1006,19 +1048,10 @@ static void simplifyRecipe(VPRecipeBase &R, VPTypeAnalysis &TypeInfo) {
10061048
10071049 // Simplification of live-in IR values for SingleDef recipes using
10081050 // InstSimplifyFolder.
1009- if (TypeSwitch<VPRecipeBase *, bool >(&R)
1010- .Case <VPInstruction, VPWidenRecipe, VPWidenCastRecipe,
1011- VPReplicateRecipe, VPWidenSelectRecipe>([&](auto *I) {
1012- const DataLayout &DL =
1013- Plan->getScalarHeader ()->getIRBasicBlock ()->getDataLayout ();
1014- Value *V = tryToFoldLiveIns (*I, I->getOpcode (), I->operands (), DL,
1015- TypeInfo);
1016- if (V)
1017- I->replaceAllUsesWith (Plan->getOrAddLiveIn (V));
1018- return V;
1019- })
1020- .Default ([](auto *) { return false ; }))
1021- return ;
1051+ const DataLayout &DL =
1052+ Plan->getScalarHeader ()->getIRBasicBlock ()->getDataLayout ();
1053+ if (VPValue *V = tryToFoldLiveIns (*Def, Def->operands (), DL, TypeInfo))
1054+ return Def->replaceAllUsesWith (V);
10221055
10231056 // Fold PredPHI LiveIn -> LiveIn.
10241057 if (auto *PredPHI = dyn_cast<VPPredInstPHIRecipe>(&R)) {
@@ -1996,29 +2029,6 @@ struct VPCSEDenseMapInfo : public DenseMapInfo<VPSingleDefRecipe *> {
19962029 return Def == getEmptyKey () || Def == getTombstoneKey ();
19972030 }
19982031
1999- // / Get any instruction opcode or intrinsic ID data embedded in recipe \p R.
2000- // / Returns an optional pair, where the first element indicates whether it is
2001- // / an intrinsic ID.
2002- static std::optional<std::pair<bool , unsigned >>
2003- getOpcodeOrIntrinsicID (const VPSingleDefRecipe *R) {
2004- return TypeSwitch<const VPSingleDefRecipe *,
2005- std::optional<std::pair<bool , unsigned >>>(R)
2006- .Case <VPInstruction, VPWidenRecipe, VPWidenCastRecipe,
2007- VPWidenSelectRecipe, VPWidenGEPRecipe, VPReplicateRecipe>(
2008- [](auto *I) { return std::make_pair (false , I->getOpcode ()); })
2009- .Case <VPWidenIntrinsicRecipe>([](auto *I) {
2010- return std::make_pair (true , I->getVectorIntrinsicID ());
2011- })
2012- .Case <VPVectorPointerRecipe, VPPredInstPHIRecipe>([](auto *I) {
2013- // For recipes that do not directly map to LLVM IR instructions,
2014- // assign opcodes after the last VPInstruction opcode (which is also
2015- // after the last IR Instruction opcode), based on the VPDefID.
2016- return std::make_pair (false ,
2017- VPInstruction::OpsEnd + 1 + I->getVPDefID ());
2018- })
2019- .Default ([](auto *) { return std::nullopt ; });
2020- }
2021-
20222032 // / If recipe \p R will lower to a GEP with a non-i8 source element type,
20232033 // / return that source element type.
20242034 static Type *getGEPSourceElementType (const VPSingleDefRecipe *R) {
0 commit comments