Skip to content

Commit debca7e

Browse files
committed
[VPlan] Move dropping of poison flags to VPlanTransforms. (NFC)
Move collectPoisonGeneratingFlags from InnerLoopVectorizer to VPlanTransforms and also update its name. collectPoisonGeneratingFlags already directly drops poison-generating flags, not only collecting it. This means it is more appropriate to integerate it directly into the VPlan transform pipeline. The current implementation still calls back to legal to check if a block needs predication, which should be improved in the future.
1 parent 6cab375 commit debca7e

File tree

3 files changed

+102
-98
lines changed

3 files changed

+102
-98
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 4 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -670,17 +670,6 @@ class InnerLoopVectorizer {
670670
/// running the verifier. Return the preheader of the completed vector loop.
671671
BasicBlock *completeLoopSkeleton();
672672

673-
/// Collect poison-generating recipes that may generate a poison value that is
674-
/// used after vectorization, even when their operands are not poison. Those
675-
/// recipes meet the following conditions:
676-
/// * Contribute to the address computation of a recipe generating a widen
677-
/// memory load/store (VPWidenMemoryInstructionRecipe or
678-
/// VPInterleaveRecipe).
679-
/// * Such a widen memory load/store has at least one underlying Instruction
680-
/// that is in a basic block that needs predication and after vectorization
681-
/// the generated instruction won't be predicated.
682-
void collectPoisonGeneratingRecipes(VPTransformState &State);
683-
684673
/// Allow subclasses to override and print debug traces before/after vplan
685674
/// execution, when trace information is requested.
686675
virtual void printDebugTracesAtStart(){};
@@ -1069,91 +1058,6 @@ static std::string getDebugLocString(const Loop *L) {
10691058
}
10701059
#endif
10711060

1072-
void InnerLoopVectorizer::collectPoisonGeneratingRecipes(
1073-
VPTransformState &State) {
1074-
1075-
// Collect recipes in the backward slice of `Root` that may generate a poison
1076-
// value that is used after vectorization.
1077-
SmallPtrSet<VPRecipeBase *, 16> Visited;
1078-
auto collectPoisonGeneratingInstrsInBackwardSlice([&](VPRecipeBase *Root) {
1079-
SmallVector<VPRecipeBase *, 16> Worklist;
1080-
Worklist.push_back(Root);
1081-
1082-
// Traverse the backward slice of Root through its use-def chain.
1083-
while (!Worklist.empty()) {
1084-
VPRecipeBase *CurRec = Worklist.back();
1085-
Worklist.pop_back();
1086-
1087-
if (!Visited.insert(CurRec).second)
1088-
continue;
1089-
1090-
// Prune search if we find another recipe generating a widen memory
1091-
// instruction. Widen memory instructions involved in address computation
1092-
// will lead to gather/scatter instructions, which don't need to be
1093-
// handled.
1094-
if (isa<VPWidenMemoryInstructionRecipe>(CurRec) ||
1095-
isa<VPInterleaveRecipe>(CurRec) ||
1096-
isa<VPScalarIVStepsRecipe>(CurRec) ||
1097-
isa<VPCanonicalIVPHIRecipe>(CurRec) ||
1098-
isa<VPActiveLaneMaskPHIRecipe>(CurRec))
1099-
continue;
1100-
1101-
// This recipe contributes to the address computation of a widen
1102-
// load/store. If the underlying instruction has poison-generating flags,
1103-
// drop them directly.
1104-
if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(CurRec)) {
1105-
RecWithFlags->dropPoisonGeneratingFlags();
1106-
} else {
1107-
Instruction *Instr = dyn_cast_or_null<Instruction>(
1108-
CurRec->getVPSingleValue()->getUnderlyingValue());
1109-
(void)Instr;
1110-
assert((!Instr || !Instr->hasPoisonGeneratingFlags()) &&
1111-
"found instruction with poison generating flags not covered by "
1112-
"VPRecipeWithIRFlags");
1113-
}
1114-
1115-
// Add new definitions to the worklist.
1116-
for (VPValue *operand : CurRec->operands())
1117-
if (VPRecipeBase *OpDef = operand->getDefiningRecipe())
1118-
Worklist.push_back(OpDef);
1119-
}
1120-
});
1121-
1122-
// Traverse all the recipes in the VPlan and collect the poison-generating
1123-
// recipes in the backward slice starting at the address of a VPWidenRecipe or
1124-
// VPInterleaveRecipe.
1125-
auto Iter = vp_depth_first_deep(State.Plan->getEntry());
1126-
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(Iter)) {
1127-
for (VPRecipeBase &Recipe : *VPBB) {
1128-
if (auto *WidenRec = dyn_cast<VPWidenMemoryInstructionRecipe>(&Recipe)) {
1129-
Instruction &UnderlyingInstr = WidenRec->getIngredient();
1130-
VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
1131-
if (AddrDef && WidenRec->isConsecutive() &&
1132-
Legal->blockNeedsPredication(UnderlyingInstr.getParent()))
1133-
collectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
1134-
} else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
1135-
VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
1136-
if (AddrDef) {
1137-
// Check if any member of the interleave group needs predication.
1138-
const InterleaveGroup<Instruction> *InterGroup =
1139-
InterleaveRec->getInterleaveGroup();
1140-
bool NeedPredication = false;
1141-
for (int I = 0, NumMembers = InterGroup->getNumMembers();
1142-
I < NumMembers; ++I) {
1143-
Instruction *Member = InterGroup->getMember(I);
1144-
if (Member)
1145-
NeedPredication |=
1146-
Legal->blockNeedsPredication(Member->getParent());
1147-
}
1148-
1149-
if (NeedPredication)
1150-
collectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
1151-
}
1152-
}
1153-
}
1154-
}
1155-
}
1156-
11571061
namespace llvm {
11581062

11591063
// Loop vectorization cost-model hints how the scalar epilogue loop should be
@@ -7591,8 +7495,6 @@ LoopVectorizationPlanner::executePlan(
75917495
State.LVer->prepareNoAliasMetadata();
75927496
}
75937497

7594-
ILV.collectPoisonGeneratingRecipes(State);
7595-
75967498
ILV.printDebugTracesAtStart();
75977499

75987500
//===------------------------------------------------===//
@@ -8869,6 +8771,10 @@ LoopVectorizationPlanner::tryToBuildVPlanWithVPRecipes(VFRange &Range) {
88698771
// in ways that accessing values using original IR values is incorrect.
88708772
Plan->disableValue2VPValue();
88718773

8774+
VPlanTransforms::dropPoisonGeneratingRecipes(*Plan, [this](BasicBlock *BB) {
8775+
return Legal->blockNeedsPredication(BB);
8776+
});
8777+
88728778
// Sink users of fixed-order recurrence past the recipe defining the previous
88738779
// value and introduce FirstOrderRecurrenceSplice VPInstructions.
88748780
if (!VPlanTransforms::adjustFixedOrderRecurrences(*Plan, Builder))

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,3 +1201,86 @@ void VPlanTransforms::addActiveLaneMask(
12011201
CompareToReplace->eraseFromParent();
12021202
}
12031203
}
1204+
1205+
void VPlanTransforms::dropPoisonGeneratingRecipes(
1206+
VPlan &Plan, function_ref<bool(BasicBlock *)> BlockNeedsPredication) {
1207+
// Collect recipes in the backward slice of `Root` that may generate a poison
1208+
// value that is used after vectorization.
1209+
SmallPtrSet<VPRecipeBase *, 16> Visited;
1210+
auto collectPoisonGeneratingInstrsInBackwardSlice([&](VPRecipeBase *Root) {
1211+
SmallVector<VPRecipeBase *, 16> Worklist;
1212+
Worklist.push_back(Root);
1213+
1214+
// Traverse the backward slice of Root through its use-def chain.
1215+
while (!Worklist.empty()) {
1216+
VPRecipeBase *CurRec = Worklist.back();
1217+
Worklist.pop_back();
1218+
1219+
if (!Visited.insert(CurRec).second)
1220+
continue;
1221+
1222+
// Prune search if we find another recipe generating a widen memory
1223+
// instruction. Widen memory instructions involved in address computation
1224+
// will lead to gather/scatter instructions, which don't need to be
1225+
// handled.
1226+
if (isa<VPWidenMemoryInstructionRecipe>(CurRec) ||
1227+
isa<VPInterleaveRecipe>(CurRec) ||
1228+
isa<VPScalarIVStepsRecipe>(CurRec) ||
1229+
isa<VPCanonicalIVPHIRecipe>(CurRec) ||
1230+
isa<VPActiveLaneMaskPHIRecipe>(CurRec))
1231+
continue;
1232+
1233+
// This recipe contributes to the address computation of a widen
1234+
// load/store. If the underlying instruction has poison-generating flags,
1235+
// drop them directly.
1236+
if (auto *RecWithFlags = dyn_cast<VPRecipeWithIRFlags>(CurRec)) {
1237+
RecWithFlags->dropPoisonGeneratingFlags();
1238+
} else {
1239+
Instruction *Instr = dyn_cast_or_null<Instruction>(
1240+
CurRec->getVPSingleValue()->getUnderlyingValue());
1241+
(void)Instr;
1242+
assert((!Instr || !Instr->hasPoisonGeneratingFlags()) &&
1243+
"found instruction with poison generating flags not covered by "
1244+
"VPRecipeWithIRFlags");
1245+
}
1246+
1247+
// Add new definitions to the worklist.
1248+
for (VPValue *operand : CurRec->operands())
1249+
if (VPRecipeBase *OpDef = operand->getDefiningRecipe())
1250+
Worklist.push_back(OpDef);
1251+
}
1252+
});
1253+
1254+
// Traverse all the recipes in the VPlan and collect the poison-generating
1255+
// recipes in the backward slice starting at the address of a VPWidenRecipe or
1256+
// VPInterleaveRecipe.
1257+
auto Iter = vp_depth_first_deep(Plan.getEntry());
1258+
for (VPBasicBlock *VPBB : VPBlockUtils::blocksOnly<VPBasicBlock>(Iter)) {
1259+
for (VPRecipeBase &Recipe : *VPBB) {
1260+
if (auto *WidenRec = dyn_cast<VPWidenMemoryInstructionRecipe>(&Recipe)) {
1261+
Instruction &UnderlyingInstr = WidenRec->getIngredient();
1262+
VPRecipeBase *AddrDef = WidenRec->getAddr()->getDefiningRecipe();
1263+
if (AddrDef && WidenRec->isConsecutive() &&
1264+
BlockNeedsPredication(UnderlyingInstr.getParent()))
1265+
collectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
1266+
} else if (auto *InterleaveRec = dyn_cast<VPInterleaveRecipe>(&Recipe)) {
1267+
VPRecipeBase *AddrDef = InterleaveRec->getAddr()->getDefiningRecipe();
1268+
if (AddrDef) {
1269+
// Check if any member of the interleave group needs predication.
1270+
const InterleaveGroup<Instruction> *InterGroup =
1271+
InterleaveRec->getInterleaveGroup();
1272+
bool NeedPredication = false;
1273+
for (int I = 0, NumMembers = InterGroup->getNumMembers();
1274+
I < NumMembers; ++I) {
1275+
Instruction *Member = InterGroup->getMember(I);
1276+
if (Member)
1277+
NeedPredication |= BlockNeedsPredication(Member->getParent());
1278+
}
1279+
1280+
if (NeedPredication)
1281+
collectPoisonGeneratingInstrsInBackwardSlice(AddrDef);
1282+
}
1283+
}
1284+
}
1285+
}
1286+
}

llvm/lib/Transforms/Vectorize/VPlanTransforms.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,21 @@ struct VPlanTransforms {
8484
const MapVector<Instruction *, uint64_t> &MinBWs,
8585
LLVMContext &Ctx);
8686

87+
/// Drop poison flags from recipes that may generate a poison value that is
88+
/// used after vectorization, even when their operands are not poison. Those
89+
/// recipes meet the following conditions:
90+
/// * Contribute to the address computation of a recipe generating a widen
91+
/// memory load/store (VPWidenMemoryInstructionRecipe or
92+
/// VPInterleaveRecipe).
93+
/// * Such a widen memory load/store has at least one underlying Instruction
94+
/// that is in a basic block that needs predication and after vectorization
95+
/// the generated instruction won't be predicated.
96+
/// Uses \p BlockNeedsPredication to check if a block needs predicating.
97+
/// TODO: Replace BlockNeedsPredication callback with retrieving info from
98+
/// VPlan directly.
99+
static void dropPoisonGeneratingRecipes(
100+
VPlan &Plan, function_ref<bool(BasicBlock *)> BlockNeedsPredication);
101+
87102
private:
88103
/// Remove redundant VPBasicBlocks by merging them into their predecessor if
89104
/// the predecessor has a single successor.

0 commit comments

Comments
 (0)