[llvm] [VPlan] Explicitly unroll replicate-regions without live-outs by VF. (PR #170212)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 27 03:31:45 PDT 2026
================
@@ -617,43 +653,144 @@ cloneForLane(VPlan &Plan, VPBuilder &Builder, Type *IdxTy,
// Skip lane 0: an absent start index is implicitly zero.
unsigned KnownLane = Lane.getKnownLane();
if (KnownLane != 0) {
- VPTypeAnalysis TypeInfo(Plan);
- Type *BaseIVTy = TypeInfo.inferScalarType(DefR->getOperand(0));
-
- VPValue *StartIndex = Steps->getStartIndex();
- VPValue *LaneOffset;
- unsigned AddOp;
- VPIRFlags Flags;
- if (BaseIVTy->isFloatingPointTy()) {
- int SignedLane = static_cast<int>(KnownLane);
- if (!StartIndex && Steps->getInductionOpcode() == Instruction::FSub)
- SignedLane = -SignedLane;
- LaneOffset =
- Plan.getOrAddLiveIn(ConstantFP::get(BaseIVTy, SignedLane));
- AddOp = Steps->getInductionOpcode();
- Flags = VPIRFlags(FastMathFlags());
- } else {
- unsigned BaseIVBits = BaseIVTy->getScalarSizeInBits();
- LaneOffset = Plan.getConstantInt(APInt(BaseIVBits, KnownLane,
- /*isSigned*/ false,
- /*implicitTrunc*/ true));
- AddOp = Instruction::Add;
- Flags = VPIRFlags(VPIRFlags::WrapFlagsTy(false, false));
- }
-
- if (StartIndex) {
- VPBuilder LaneBuilder(DefR);
- LaneOffset =
- LaneBuilder.createNaryOp(AddOp, {StartIndex, LaneOffset}, Flags);
- }
- Steps->setStartIndex(LaneOffset);
+ Steps->insertBefore(DefR);
+ addLaneToStartIndex(Steps, KnownLane, Plan);
+ return New;
}
}
}
New->insertBefore(DefR);
return New;
}
+/// Convert recipes in region blocks to operate on a single lane 0.
+/// VPReplicateRecipes are converted to single-scalar ones, branch-on-mask is
+/// converted into BranchOnCond and extracts are created as needed.
+static void convertRecipesInRegionBlocksToSingleScalar(VPlan &Plan, Type *IdxTy,
+ VPBlockBase *Entry) {
+ VPValue *Idx0 = Plan.getZero(IdxTy);
+ for (VPBlockBase *VPB : vp_depth_first_shallow(Entry)) {
+ for (VPRecipeBase &OldR : make_early_inc_range(cast<VPBasicBlock>(*VPB))) {
+ VPBuilder Builder(&OldR);
+ assert(!match(&OldR, m_ExtractElement(m_VPValue(), m_VPValue())) &&
+ "must not contain extracts before conversion");
+ for (const auto &[I, Op] : enumerate(OldR.operands())) {
+ // Skip operands that don't need extraction: values defined in the
+ // same block (already scalar), or values that are already single
+ // scalars.
+ auto *DefR = Op->getDefiningRecipe();
+ if ((DefR && DefR->getParent() == VPB) || vputils::isSingleScalar(Op))
+ continue;
----------------
ayalz wrote:
Hmm, may be missing something here, curious to see an example/test which fails when checking only isSingleScalar, dropping the check for same basic block.
https://github.com/llvm/llvm-project/pull/170212
More information about the llvm-commits
mailing list