Skip to content

Commit 7df9397

Browse files
committed
[LV][VPlan] Extract the implementation of transform Recipe to EVLRecipe into a small function
1 parent 77b6910 commit 7df9397

File tree

1 file changed

+96
-99
lines changed

1 file changed

+96
-99
lines changed

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 96 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,13 +1438,100 @@ void VPlanTransforms::addActiveLaneMask(
14381438
HeaderMask->replaceAllUsesWith(LaneMask);
14391439
}
14401440

1441+
static VPRecipeBase *createEVLRecipe(VPValue &EVL, VPValue *HeaderMask,
1442+
VPValue *AllOneMask,
1443+
VPRecipeBase *CurRecipe,
1444+
VPTypeAnalysis TypeInfo) {
1445+
using namespace llvm::VPlanPatternMatch;
1446+
auto GetNewMask = [&](VPValue *OrigMask) -> VPValue * {
1447+
assert(OrigMask && "Unmasked recipe when folding tail");
1448+
return HeaderMask == OrigMask ? nullptr : OrigMask;
1449+
};
1450+
1451+
return TypeSwitch<VPRecipeBase *, VPRecipeBase *>(CurRecipe)
1452+
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
1453+
VPValue *NewMask = GetNewMask(L->getMask());
1454+
return new VPWidenLoadEVLRecipe(*L, EVL, NewMask);
1455+
})
1456+
.Case<VPWidenStoreRecipe>([&](VPWidenStoreRecipe *S) {
1457+
VPValue *NewMask = GetNewMask(S->getMask());
1458+
return new VPWidenStoreEVLRecipe(*S, EVL, NewMask);
1459+
})
1460+
.Case<VPWidenRecipe>([&](VPWidenRecipe *W) -> VPRecipeBase * {
1461+
unsigned Opcode = W->getOpcode();
1462+
if (!Instruction::isBinaryOp(Opcode) && !Instruction::isUnaryOp(Opcode))
1463+
return nullptr;
1464+
return new VPWidenEVLRecipe(*W, EVL);
1465+
})
1466+
.Case<VPReductionRecipe>([&](VPReductionRecipe *Red) {
1467+
VPValue *NewMask = GetNewMask(Red->getCondOp());
1468+
return new VPReductionEVLRecipe(*Red, EVL, NewMask);
1469+
})
1470+
.Case<VPWidenIntrinsicRecipe>(
1471+
[&](VPWidenIntrinsicRecipe *CInst) -> VPRecipeBase * {
1472+
auto *CI = cast<CallInst>(CInst->getUnderlyingInstr());
1473+
Intrinsic::ID VPID = VPIntrinsic::getForIntrinsic(
1474+
CI->getCalledFunction()->getIntrinsicID());
1475+
assert(VPID != Intrinsic::not_intrinsic &&
1476+
"Expected VP Instrinsic");
1477+
1478+
SmallVector<VPValue *> Ops(CInst->operands());
1479+
assert(VPIntrinsic::getMaskParamPos(VPID) &&
1480+
VPIntrinsic::getVectorLengthParamPos(VPID) &&
1481+
"Expected VP intrinsic");
1482+
1483+
Ops.push_back(AllOneMask);
1484+
Ops.push_back(&EVL);
1485+
return new VPWidenIntrinsicRecipe(*CI, VPID, Ops,
1486+
TypeInfo.inferScalarType(CInst),
1487+
CInst->getDebugLoc());
1488+
})
1489+
.Case<VPWidenCastRecipe>([&](VPWidenCastRecipe *CInst) -> VPRecipeBase * {
1490+
auto *CI = dyn_cast<CastInst>(CInst->getUnderlyingInstr());
1491+
Intrinsic::ID VPID = VPIntrinsic::getForOpcode(CI->getOpcode());
1492+
assert(VPID != Intrinsic::not_intrinsic &&
1493+
"Expected vp.casts Instrinsic");
1494+
1495+
SmallVector<VPValue *> Ops(CInst->operands());
1496+
assert(VPIntrinsic::getMaskParamPos(VPID) &&
1497+
VPIntrinsic::getVectorLengthParamPos(VPID) &&
1498+
"Expected VP intrinsic");
1499+
Ops.push_back(AllOneMask);
1500+
Ops.push_back(&EVL);
1501+
return new VPWidenIntrinsicRecipe(
1502+
VPID, Ops, TypeInfo.inferScalarType(CInst), CInst->getDebugLoc());
1503+
})
1504+
.Case<VPWidenSelectRecipe>([&](VPWidenSelectRecipe *Sel) {
1505+
SmallVector<VPValue *> Ops(Sel->operands());
1506+
Ops.push_back(&EVL);
1507+
return new VPWidenIntrinsicRecipe(Intrinsic::vp_select, Ops,
1508+
TypeInfo.inferScalarType(Sel),
1509+
Sel->getDebugLoc());
1510+
})
1511+
.Case<VPInstruction>([&](VPInstruction *VPI) -> VPRecipeBase * {
1512+
VPValue *LHS, *RHS;
1513+
// Transform select with a header mask condition
1514+
// select(header_mask, LHS, RHS)
1515+
// into vector predication merge.
1516+
// vp.merge(all-true, LHS, RHS, EVL)
1517+
if (!match(VPI, m_Select(m_Specific(HeaderMask), m_VPValue(LHS),
1518+
m_VPValue(RHS))))
1519+
return nullptr;
1520+
// Use all true as the condition because this transformation is
1521+
// limited to selects whose condition is a header mask.
1522+
return new VPWidenIntrinsicRecipe(
1523+
Intrinsic::vp_merge, {AllOneMask, LHS, RHS, &EVL},
1524+
TypeInfo.inferScalarType(LHS), VPI->getDebugLoc());
1525+
})
1526+
.Default([&](VPRecipeBase *R) { return nullptr; });
1527+
}
1528+
14411529
/// Replace recipes with their EVL variants.
14421530
static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
1443-
using namespace llvm::VPlanPatternMatch;
14441531
Type *CanonicalIVType = Plan.getCanonicalIV()->getScalarType();
14451532
VPTypeAnalysis TypeInfo(CanonicalIVType);
14461533
LLVMContext &Ctx = CanonicalIVType->getContext();
1447-
SmallVector<VPValue *> HeaderMasks = collectAllHeaderMasks(Plan);
1534+
VPValue *AllOneMask = Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
14481535

14491536
for (VPUser *U : Plan.getVF().users()) {
14501537
if (auto *R = dyn_cast<VPReverseVectorPointerRecipe>(U))
@@ -1454,112 +1541,22 @@ static void transformRecipestoEVLRecipes(VPlan &Plan, VPValue &EVL) {
14541541
for (VPValue *HeaderMask : collectAllHeaderMasks(Plan)) {
14551542
for (VPUser *U : collectUsersRecursively(HeaderMask)) {
14561543
auto *CurRecipe = cast<VPRecipeBase>(U);
1457-
auto GetNewMask = [&](VPValue *OrigMask) -> VPValue * {
1458-
assert(OrigMask && "Unmasked recipe when folding tail");
1459-
return HeaderMask == OrigMask ? nullptr : OrigMask;
1460-
};
1461-
1462-
VPRecipeBase *NewRecipe =
1463-
TypeSwitch<VPRecipeBase *, VPRecipeBase *>(CurRecipe)
1464-
.Case<VPWidenLoadRecipe>([&](VPWidenLoadRecipe *L) {
1465-
VPValue *NewMask = GetNewMask(L->getMask());
1466-
return new VPWidenLoadEVLRecipe(*L, EVL, NewMask);
1467-
})
1468-
.Case<VPWidenStoreRecipe>([&](VPWidenStoreRecipe *S) {
1469-
VPValue *NewMask = GetNewMask(S->getMask());
1470-
return new VPWidenStoreEVLRecipe(*S, EVL, NewMask);
1471-
})
1472-
.Case<VPWidenRecipe>([&](VPWidenRecipe *W) -> VPRecipeBase * {
1473-
unsigned Opcode = W->getOpcode();
1474-
if (!Instruction::isBinaryOp(Opcode) &&
1475-
!Instruction::isUnaryOp(Opcode))
1476-
return nullptr;
1477-
return new VPWidenEVLRecipe(*W, EVL);
1478-
})
1479-
.Case<VPReductionRecipe>([&](VPReductionRecipe *Red) {
1480-
VPValue *NewMask = GetNewMask(Red->getCondOp());
1481-
return new VPReductionEVLRecipe(*Red, EVL, NewMask);
1482-
})
1483-
.Case<VPWidenIntrinsicRecipe>(
1484-
[&](VPWidenIntrinsicRecipe *CInst) -> VPRecipeBase * {
1485-
auto *CI = cast<CallInst>(CInst->getUnderlyingInstr());
1486-
Intrinsic::ID VPID = VPIntrinsic::getForIntrinsic(
1487-
CI->getCalledFunction()->getIntrinsicID());
1488-
if (VPID == Intrinsic::not_intrinsic)
1489-
return nullptr;
1490-
1491-
SmallVector<VPValue *> Ops(CInst->operands());
1492-
assert(VPIntrinsic::getMaskParamPos(VPID) &&
1493-
VPIntrinsic::getVectorLengthParamPos(VPID) &&
1494-
"Expected VP intrinsic");
1495-
VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::getTrue(
1496-
IntegerType::getInt1Ty(CI->getContext())));
1497-
Ops.push_back(Mask);
1498-
Ops.push_back(&EVL);
1499-
return new VPWidenIntrinsicRecipe(
1500-
*CI, VPID, Ops, TypeInfo.inferScalarType(CInst),
1501-
CInst->getDebugLoc());
1502-
})
1503-
.Case<VPWidenCastRecipe>(
1504-
[&](VPWidenCastRecipe *CInst) -> VPRecipeBase * {
1505-
auto *CI = dyn_cast<CastInst>(CInst->getUnderlyingInstr());
1506-
Intrinsic::ID VPID =
1507-
VPIntrinsic::getForOpcode(CI->getOpcode());
1508-
assert(VPID != Intrinsic::not_intrinsic &&
1509-
"Expected vp.casts Instrinsic");
1510-
1511-
SmallVector<VPValue *> Ops(CInst->operands());
1512-
assert(VPIntrinsic::getMaskParamPos(VPID) &&
1513-
VPIntrinsic::getVectorLengthParamPos(VPID) &&
1514-
"Expected VP intrinsic");
1515-
VPValue *Mask = Plan.getOrAddLiveIn(ConstantInt::getTrue(
1516-
IntegerType::getInt1Ty(CI->getContext())));
1517-
Ops.push_back(Mask);
1518-
Ops.push_back(&EVL);
1519-
return new VPWidenIntrinsicRecipe(
1520-
VPID, Ops, TypeInfo.inferScalarType(CInst),
1521-
CInst->getDebugLoc());
1522-
})
1523-
.Case<VPWidenSelectRecipe>([&](VPWidenSelectRecipe *Sel) {
1524-
SmallVector<VPValue *> Ops(Sel->operands());
1525-
Ops.push_back(&EVL);
1526-
return new VPWidenIntrinsicRecipe(Intrinsic::vp_select, Ops,
1527-
TypeInfo.inferScalarType(Sel),
1528-
Sel->getDebugLoc());
1529-
})
1530-
.Case<VPInstruction>([&](VPInstruction *VPI) -> VPRecipeBase * {
1531-
VPValue *LHS, *RHS;
1532-
// Transform select with a header mask condition
1533-
// select(header_mask, LHS, RHS)
1534-
// into vector predication merge.
1535-
// vp.merge(all-true, LHS, RHS, EVL)
1536-
if (!match(VPI, m_Select(m_Specific(HeaderMask), m_VPValue(LHS),
1537-
m_VPValue(RHS))))
1538-
return nullptr;
1539-
// Use all true as the condition because this transformation is
1540-
// limited to selects whose condition is a header mask.
1541-
VPValue *AllTrue =
1542-
Plan.getOrAddLiveIn(ConstantInt::getTrue(Ctx));
1543-
return new VPWidenIntrinsicRecipe(
1544-
Intrinsic::vp_merge, {AllTrue, LHS, RHS, &EVL},
1545-
TypeInfo.inferScalarType(LHS), VPI->getDebugLoc());
1546-
})
1547-
.Default([&](VPRecipeBase *R) { return nullptr; });
1548-
1549-
if (!NewRecipe)
1544+
VPRecipeBase *EVLRecipe =
1545+
createEVLRecipe(EVL, HeaderMask, AllOneMask, CurRecipe, TypeInfo);
1546+
if (!EVLRecipe)
15501547
continue;
15511548

1552-
[[maybe_unused]] unsigned NumDefVal = NewRecipe->getNumDefinedValues();
1549+
[[maybe_unused]] unsigned NumDefVal = EVLRecipe->getNumDefinedValues();
15531550
assert(NumDefVal == CurRecipe->getNumDefinedValues() &&
15541551
"New recipe must define the same number of values as the "
15551552
"original.");
15561553
assert(
15571554
NumDefVal <= 1 &&
15581555
"Only supports recipes with a single definition or without users.");
1559-
NewRecipe->insertBefore(CurRecipe);
1560-
if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(NewRecipe)) {
1556+
EVLRecipe->insertBefore(CurRecipe);
1557+
if (isa<VPSingleDefRecipe, VPWidenLoadEVLRecipe>(EVLRecipe)) {
15611558
VPValue *CurVPV = CurRecipe->getVPSingleValue();
1562-
CurVPV->replaceAllUsesWith(NewRecipe->getVPSingleValue());
1559+
CurVPV->replaceAllUsesWith(EVLRecipe->getVPSingleValue());
15631560
}
15641561
CurRecipe->eraseFromParent();
15651562
}

0 commit comments

Comments
 (0)