Skip to content

Commit 114d74e

Browse files
authored
[VPlan] Expand VPBlendRecipes to select instructions. NFC (#133993)
When looking at some EVL tail folded code in SPEC CPU 2017 I noticed we sometimes have both VPBlendRecipes and select VPInstructions in the same plan: EMIT vp<%active.lane.mask> = active lane mask vp<%5>, vp<%3> EMIT vp<%7> = icmp ... EMIT vp<%8> = logical-and vp<%active.lane.mask>, vp<%7> BLEND ir<%8> = ir<%n.015> ir<%foo>/vp<%8> EMIT vp<%9> = select vp<%active.lane.mask>, ir<%8>, ir<%n.015> Since a blend will ultimately generate a chain of selects, we could fold the blend into the select: EMIT vp<%active.lane.mask> = active lane mask vp<%5>, vp<%3> EMIT vp<%7> = icmp ... EMIT vp<%8> = logical-and vp<%active.lane.mask>, vp<%7> EMIT ir<%8> = select vp<%8>, ir<%foo>, ir<%n.015> So as a first step, this patch expands blends to a series of select instructions, which may allow them to be simplified further with other select instructions.
1 parent d65cc97 commit 114d74e

File tree

3 files changed

+15
-39
lines changed

3 files changed

+15
-39
lines changed

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,8 +2335,9 @@ class LLVM_ABI_FOR_TEST VPBlendRecipe : public VPSingleDefRecipe {
23352335
return Idx == 0 ? getOperand(1) : getOperand(Idx * 2 + !isNormalized());
23362336
}
23372337

2338-
/// Generate the phi/select nodes.
2339-
void execute(VPTransformState &State) override;
2338+
void execute(VPTransformState &State) override {
2339+
llvm_unreachable("VPBlendRecipe should be expanded by simplifyBlends");
2340+
}
23402341

23412342
/// Return the cost of this VPWidenMemoryRecipe.
23422343
InstructionCost computeCost(ElementCount VF,

llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2411,42 +2411,6 @@ void VPVectorPointerRecipe::print(raw_ostream &O, const Twine &Indent,
24112411
}
24122412
#endif
24132413

2414-
void VPBlendRecipe::execute(VPTransformState &State) {
2415-
assert(isNormalized() && "Expected blend to be normalized!");
2416-
// We know that all PHIs in non-header blocks are converted into
2417-
// selects, so we don't have to worry about the insertion order and we
2418-
// can just use the builder.
2419-
// At this point we generate the predication tree. There may be
2420-
// duplications since this is a simple recursive scan, but future
2421-
// optimizations will clean it up.
2422-
2423-
unsigned NumIncoming = getNumIncomingValues();
2424-
2425-
// Generate a sequence of selects of the form:
2426-
// SELECT(Mask3, In3,
2427-
// SELECT(Mask2, In2,
2428-
// SELECT(Mask1, In1,
2429-
// In0)))
2430-
// Note that Mask0 is never used: lanes for which no path reaches this phi and
2431-
// are essentially undef are taken from In0.
2432-
bool OnlyFirstLaneUsed = vputils::onlyFirstLaneUsed(this);
2433-
Value *Result = nullptr;
2434-
for (unsigned In = 0; In < NumIncoming; ++In) {
2435-
// We might have single edge PHIs (blocks) - use an identity
2436-
// 'select' for the first PHI operand.
2437-
Value *In0 = State.get(getIncomingValue(In), OnlyFirstLaneUsed);
2438-
if (In == 0)
2439-
Result = In0; // Initialize with the first incoming value.
2440-
else {
2441-
// Select between the current value and the previous incoming edge
2442-
// based on the incoming mask.
2443-
Value *Cond = State.get(getMask(In), OnlyFirstLaneUsed);
2444-
Result = State.Builder.CreateSelect(Cond, In0, Result, "predphi");
2445-
}
2446-
}
2447-
State.set(this, Result, OnlyFirstLaneUsed);
2448-
}
2449-
24502414
InstructionCost VPBlendRecipe::computeCost(ElementCount VF,
24512415
VPCostContext &Ctx) const {
24522416
// Handle cases where only the first lane is used the same way as the legacy

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2711,6 +2711,18 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
27112711
continue;
27122712
}
27132713

2714+
// Expand VPBlendRecipe into VPInstruction::Select.
2715+
VPBuilder Builder(&R);
2716+
if (auto *Blend = dyn_cast<VPBlendRecipe>(&R)) {
2717+
VPValue *Select = Blend->getIncomingValue(0);
2718+
for (unsigned I = 1; I != Blend->getNumIncomingValues(); ++I)
2719+
Select = Builder.createSelect(Blend->getMask(I),
2720+
Blend->getIncomingValue(I), Select,
2721+
R.getDebugLoc(), "predphi");
2722+
Blend->replaceAllUsesWith(Select);
2723+
ToRemove.push_back(Blend);
2724+
}
2725+
27142726
if (auto *Expr = dyn_cast<VPExpressionRecipe>(&R)) {
27152727
Expr->decompose();
27162728
ToRemove.push_back(Expr);
@@ -2724,7 +2736,6 @@ void VPlanTransforms::convertToConcreteRecipes(VPlan &Plan,
27242736

27252737
// Expand WideIVStep.
27262738
auto *VPI = cast<VPInstruction>(&R);
2727-
VPBuilder Builder(VPI);
27282739
Type *IVTy = TypeInfo.inferScalarType(VPI);
27292740
if (TypeInfo.inferScalarType(VectorStep) != IVTy) {
27302741
Instruction::CastOps CastOp = IVTy->isFloatingPointTy()

0 commit comments

Comments
 (0)