Skip to content

Commit 6db3776

Browse files
authored
[LV][EVL] Simplify EVL recipe transformation by using a single EVL mask. nfc (#152479)
The EVL mask is always defined as `icmp ult (step-vector, EVL)`, so we only need to generate it once per plan in the header. Then, we replace all uses of the header mask with the EVL mask, and recursively optimize the users of EVL mask into EVL recipes. This way, the transformation to EVL recipes can be done with just a single loop.
1 parent 1c49935 commit 6db3776

File tree

1 file changed

+39
-37
lines changed

1 file changed

+39
-37
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,48 +2242,50 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
22422242
}
22432243
}
22442244

2245-
// Try to optimize header mask recipes away to their EVL variants.
2245+
// Replace header masks with a mask equivalent to predicating by EVL:
2246+
//
2247+
// icmp ule widen-canonical-iv backedge-taken-count
2248+
// ->
2249+
// icmp ult step-vector, EVL
2250+
VPRecipeBase *EVLR = EVL.getDefiningRecipe();
2251+
VPBuilder Builder(EVLR->getParent(), std::next(EVLR->getIterator()));
2252+
Type *EVLType = TypeInfo.inferScalarType(&EVL);
2253+
VPValue *EVLMask = Builder.createICmp(
2254+
CmpInst::ICMP_ULT,
2255+
Builder.createNaryOp(VPInstruction::StepVector, {}, EVLType), &EVL);
22462256
for (VPValue *HeaderMask : collectAllHeaderMasks(Plan)) {
2247-
// TODO: Split optimizeMaskToEVL out and move into
2248-
// VPlanTransforms::optimize. transformRecipestoEVLRecipes should be run in
2249-
// tryToBuildVPlanWithVPRecipes beforehand.
2250-
for (VPUser *U : collectUsersRecursively(HeaderMask)) {
2251-
auto *CurRecipe = cast<VPRecipeBase>(U);
2252-
VPRecipeBase *EVLRecipe =
2253-
optimizeMaskToEVL(HeaderMask, *CurRecipe, TypeInfo, *AllOneMask, EVL);
2254-
if (!EVLRecipe)
2255-
continue;
2256-
2257-
[[maybe_unused]] unsigned NumDefVal = EVLRecipe->getNumDefinedValues();
2258-
assert(NumDefVal == CurRecipe->getNumDefinedValues() &&
2259-
"New recipe must define the same number of values as the "
2260-
"original.");
2261-
assert(
2262-
NumDefVal <= 1 &&
2263-
"Only supports recipes with a single definition or without users.");
2264-
EVLRecipe->insertBefore(CurRecipe);
2265-
if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(EVLRecipe)) {
2266-
VPValue *CurVPV = CurRecipe->getVPSingleValue();
2267-
CurVPV->replaceAllUsesWith(EVLRecipe->getVPSingleValue());
2268-
}
2269-
ToErase.push_back(CurRecipe);
2270-
}
2271-
2272-
// Replace header masks with a mask equivalent to predicating by EVL:
2273-
//
2274-
// icmp ule widen-canonical-iv backedge-taken-count
2275-
// ->
2276-
// icmp ult step-vector, EVL
2277-
VPRecipeBase *EVLR = EVL.getDefiningRecipe();
2278-
VPBuilder Builder(EVLR->getParent(), std::next(EVLR->getIterator()));
2279-
Type *EVLType = TypeInfo.inferScalarType(&EVL);
2280-
VPValue *EVLMask = Builder.createICmp(
2281-
CmpInst::ICMP_ULT,
2282-
Builder.createNaryOp(VPInstruction::StepVector, {}, EVLType), &EVL);
22832257
HeaderMask->replaceAllUsesWith(EVLMask);
22842258
ToErase.push_back(HeaderMask->getDefiningRecipe());
22852259
}
22862260

2261+
// Try to optimize header mask recipes away to their EVL variants.
2262+
// TODO: Split optimizeMaskToEVL out and move into
2263+
// VPlanTransforms::optimize. transformRecipestoEVLRecipes should be run in
2264+
// tryToBuildVPlanWithVPRecipes beforehand.
2265+
for (VPUser *U : collectUsersRecursively(EVLMask)) {
2266+
auto *CurRecipe = cast<VPRecipeBase>(U);
2267+
VPRecipeBase *EVLRecipe =
2268+
optimizeMaskToEVL(EVLMask, *CurRecipe, TypeInfo, *AllOneMask, EVL);
2269+
if (!EVLRecipe)
2270+
continue;
2271+
2272+
[[maybe_unused]] unsigned NumDefVal = EVLRecipe->getNumDefinedValues();
2273+
assert(NumDefVal == CurRecipe->getNumDefinedValues() &&
2274+
"New recipe must define the same number of values as the "
2275+
"original.");
2276+
assert(NumDefVal <= 1 &&
2277+
"Only supports recipes with a single definition or without users.");
2278+
EVLRecipe->insertBefore(CurRecipe);
2279+
if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(EVLRecipe)) {
2280+
VPValue *CurVPV = CurRecipe->getVPSingleValue();
2281+
CurVPV->replaceAllUsesWith(EVLRecipe->getVPSingleValue());
2282+
}
2283+
ToErase.push_back(CurRecipe);
2284+
}
2285+
// Remove dead EVL mask.
2286+
if (EVLMask->getNumUsers() == 0)
2287+
EVLMask->getDefiningRecipe()->eraseFromParent();
2288+
22872289
for (VPRecipeBase *R : reverse(ToErase)) {
22882290
SmallVector<VPValue *> PossiblyDead(R->operands());
22892291
R->eraseFromParent();

0 commit comments

Comments
 (0)