Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 69 additions & 5 deletions llvm/lib/Transforms/Vectorize/VPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -1415,6 +1415,11 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,

unsigned getOpcode() const { return Opcode; }

/// Add \p Op as operand of this VPInstruction. Only supported for AnyOf,
/// ComputeReductionResult, BuildVector, BuildStructVector, ExtractLane,
/// ExtractLastActive, FirstActiveLane, LastActiveLane.
void addOperand(VPValue *Op);

/// Generate the instruction.
/// TODO: We currently execute only per-part unless a specific instance is
/// provided.
Expand Down Expand Up @@ -1473,7 +1478,9 @@ class LLVM_ABI_FOR_TEST VPInstruction : public VPRecipeWithIRFlags,
assert(!isMasked() && "recipe is already masked");
if (alwaysUnmasked())
return;
addOperand(Mask);
assert(Mask->getScalarType()->isIntegerTy(1) &&
"Mask must be an i1 (vector)");
VPUser::addOperand(Mask);
}

/// Returns the mask for the VPInstruction. Returns nullptr for unmasked
Expand Down Expand Up @@ -1647,6 +1654,15 @@ class VPPhiAccessors {
/// predecessor.
void removeIncomingValueFor(VPBlockBase *IncomingBlock) const;

/// Append \p IncomingV as an incoming value to the phi-like recipe.
void addIncoming(VPValue *IncomingV) {
auto *R = const_cast<VPRecipeBase *>(getAsRecipe());
assert((R->getNumOperands() == 0 ||
IncomingV->getScalarType() == R->getOperand(0)->getScalarType()) &&
"all incoming values must have the same type");
R->addOperand(IncomingV);
}

#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Print the recipe.
void printPhiOperands(raw_ostream &O, VPSlotTracker &SlotTracker) const;
Expand Down Expand Up @@ -2278,6 +2294,14 @@ class VPVectorEndPointerRecipe : public VPRecipeWithIRFlags {
/// Offset = Stride * (VF - 1) + Part * Stride * VF.
void materializeOffset(unsigned Part = 0);

/// Append \p Offset as the offset operand. The offset is an integer index
/// expressed in units of SourceElementTy.
void addOffset(VPValue *Offset) {
assert(Offset->getScalarType()->isIntegerTy() &&
"offset must be an integer index");
VPUser::addOperand(Offset);
}

void execute(VPTransformState &State) override;

bool usesFirstLaneOnly(const VPValue *Op) const override {
Expand Down Expand Up @@ -2306,7 +2330,7 @@ class VPVectorEndPointerRecipe : public VPRecipeWithIRFlags {
getPointer(), getVFValue(), getSourceElementType(), getStride(),
getGEPNoWrapFlags(), getDebugLoc());
if (auto *Offset = getOffset())
VEPR->addOperand(Offset);
VEPR->addOffset(Offset);
return VEPR;
}

Expand Down Expand Up @@ -2341,6 +2365,13 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
return getNumOperands() > 2 ? getOperand(2) : nullptr;
}

/// Add the per-part offset (VFxPart) used for unrolled parts > 0.
void addPerPartOffset(VPValue *VFxPart) {
assert(VFxPart->getScalarType()->isIntegerTy() &&
"per-part offset must be an integer index");
VPUser::addOperand(VFxPart);
}

void execute(VPTransformState &State) override;

Type *getSourceElementType() const { return SourceElementTy; }
Expand All @@ -2364,7 +2395,7 @@ class VPVectorPointerRecipe : public VPRecipeWithIRFlags {
new VPVectorPointerRecipe(getOperand(0), SourceElementTy, getStride(),
getGEPNoWrapFlags(), getDebugLoc());
if (auto *VFxPart = getVFxPart())
Clone->addOperand(VFxPart);
Clone->addPerPartOffset(VFxPart);
return Clone;
}

Expand Down Expand Up @@ -2457,6 +2488,15 @@ class LLVM_ABI_FOR_TEST VPHeaderPHIRecipe : public VPSingleDefRecipe,
/// Update the incoming value from the loop backedge.
void setBackedgeValue(VPValue *V) { setOperand(1, V); }

/// Add \p V as the incoming value from the loop backedge.
void addBackedgeValue(VPValue *V) {
assert(getNumOperands() == 1 &&
"backedge value must be appended right after construction");
assert(V->getScalarType() == getScalarType() &&
"backedge value must have the same type as the start value");
VPUser::addOperand(V);
}

/// Returns the backedge value as a recipe. The backedge value is guaranteed
/// to be a recipe.
virtual VPRecipeBase &getBackedgeRecipe() {
Expand Down Expand Up @@ -2491,6 +2531,20 @@ class VPWidenInductionRecipe : public VPHeaderPHIRecipe {
addOperand(Step);
}

/// After unrolling, append the splat-VF step (`VF * step`) and the value of
/// the induction at the last unrolled part.
void addUnrolledPartOperands(VPValue *SplatVFStep, VPValue *LastPart) {
assert(LastPart->getScalarType() == getScalarType() &&
"last-part value must match the induction recipe's scalar type");
assert((getScalarType()->isPointerTy()
? SplatVFStep->getScalarType()->isIntegerTy()
: SplatVFStep->getScalarType() == getScalarType()) &&
"splat-step must match the induction type for non-pointer "
"inductions, or be an integer index for pointer inductions");
VPUser::addOperand(SplatVFStep);
VPUser::addOperand(LastPart);
}

static inline bool classof(const VPRecipeBase *R) {
return R->getVPRecipeID() == VPRecipeBase::VPWidenIntOrFpInductionSC ||
R->getVPRecipeID() == VPRecipeBase::VPWidenPointerInductionSC;
Expand Down Expand Up @@ -2964,6 +3018,7 @@ class LLVM_ABI_FOR_TEST VPBlendRecipe : public VPRecipeWithIRFlags {
/// Set mask number \p Idx to \p V.
void setMask(unsigned Idx, VPValue *V) {
assert((Idx > 0 || !isNormalized()) && "First index has no mask!");
assert(V->getScalarType()->isIntegerTy(1) && "Mask must be an i1 (vector)");
Idx == 0 ? setOperand(1, V) : setOperand(Idx * 2 + !isNormalized(), V);
}

Expand Down Expand Up @@ -3683,6 +3738,8 @@ class LLVM_ABI_FOR_TEST VPWidenMemoryRecipe : public VPIRMetadata {
assert(!IsMasked && "cannot re-set mask");
if (!Mask)
return;
assert(Mask->getScalarType()->isIntegerTy(1) &&
"Mask must be an i1 (vector)");
getAsRecipe()->addOperand(Mask);
IsMasked = true;
}
Expand Down Expand Up @@ -3979,7 +4036,7 @@ class VPActiveLaneMaskPHIRecipe : public VPHeaderPHIRecipe {
VPActiveLaneMaskPHIRecipe *clone() override {
auto *R = new VPActiveLaneMaskPHIRecipe(getOperand(0), getDebugLoc());
if (getNumOperands() == 2)
R->addOperand(getOperand(1));
R->addBackedgeValue(getOperand(1));
return R;
}

Expand Down Expand Up @@ -4057,7 +4114,7 @@ class VPWidenCanonicalIVRecipe : public VPRecipeWithIRFlags {
auto *WideCanIV =
new VPWidenCanonicalIVRecipe(getCanonicalIV(), getNoWrapFlags());
if (VPValue *Step = getStepValue())
WideCanIV->addOperand(Step);
WideCanIV->addPerPartStep(Step);
return WideCanIV;
}

Expand All @@ -4083,6 +4140,13 @@ class VPWidenCanonicalIVRecipe : public VPRecipeWithIRFlags {
return getNumOperands() == 2 ? getOperand(1) : nullptr;
}

/// Add the per-part step (VF * Part) used for unrolled parts.
void addPerPartStep(VPValue *Step) {
assert(Step->getScalarType() == getScalarType() &&
"per-part step must have the same type as the canonical IV");
VPUser::addOperand(Step);
}

protected:
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
/// Print the recipe.
Expand Down
12 changes: 6 additions & 6 deletions llvm/lib/Transforms/Vectorize/VPlanConstruction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ void PlainCFGBuilder::fixHeaderPhis() {
assert(Phi->getNumOperands() == 2 &&
"header phi must have exactly 2 operands");
for (BasicBlock *Pred : predecessors(Phi->getParent()))
PhiR->addOperand(
PhiR->addIncoming(
getOrCreateVPOperand(Phi->getIncomingValueForBlock(Pred)));
}
}
Expand Down Expand Up @@ -244,7 +244,7 @@ void PlainCFGBuilder::createVPInstructionsForVPBB(VPBasicBlock *VPBB,
getOrCreateVPOperand(Phi->getIncomingValue(I));
}
for (VPBlockBase *Pred : VPBB->getPredecessors())
NewR->addOperand(
cast<VPPhi>(NewR)->addIncoming(
VPPredToIncomingValue.lookup(Pred->getExitingBasicBlock()));
}
} else {
Expand Down Expand Up @@ -371,7 +371,7 @@ std::unique_ptr<VPlan> PlainCFGBuilder::buildPlainCFG() {
assert(PhiR->getNumOperands() == 0 &&
"no phi operands should be added yet");
for (BasicBlock *Pred : predecessors(EB->getIRBasicBlock()))
PhiR->addOperand(
PhiR->addIncoming(
getOrCreateVPOperand(Phi.getIncomingValueForBlock(Pred)));
}
}
Expand Down Expand Up @@ -591,7 +591,7 @@ static void addInitialSkeleton(VPlan &Plan, Type *InductionTy,
auto *ResumePhiR = ScalarPHBuilder.createScalarPhi(
{ResumeFromVectorLoop, VectorPhiR->getOperand(0)},
VectorPhiR->getDebugLoc());
cast<VPIRPhi>(&ScalarPhiR)->addOperand(ResumePhiR);
cast<VPIRPhi>(&ScalarPhiR)->addIncoming(ResumePhiR);
}
}

Expand Down Expand Up @@ -1456,7 +1456,7 @@ static void insertCheckBlockBeforeVectorLoop(VPlan &Plan,
auto *Phi = cast<VPPhi>(&R);
assert(Phi->getNumIncoming() == NumPreds - 1 &&
"must have incoming values for all predecessors");
Phi->addOperand(Phi->getOperand(NumPreds - 2));
Phi->addIncoming(Phi->getOperand(NumPreds - 2));
}
}

Expand Down Expand Up @@ -1889,7 +1889,7 @@ bool VPlanTransforms::handleFindLastReductions(VPlan &Plan) {

VPValue *AnyOf = Builder.createNaryOp(VPInstruction::AnyOf, {Cond});
VPValue *MaskSelect = Builder.createSelect(AnyOf, Cond, MaskPHI);
MaskPHI->addOperand(MaskSelect);
MaskPHI->addIncoming(MaskSelect);

// Replace select for data.
VPValue *DataSelect =
Expand Down
43 changes: 42 additions & 1 deletion llvm/lib/Transforms/Vectorize/VPlanRecipes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1443,6 +1443,47 @@ bool VPInstruction::isSingleScalar() const {
}
}

void VPInstruction::addOperand(VPValue *Op) {
#ifndef NDEBUG
Type *Ty = Op->getScalarType();
switch (getOpcode()) {
case VPInstruction::AnyOf:
case VPInstruction::FirstActiveLane:
case VPInstruction::LastActiveLane:
assert(Ty == getOperand(0)->getScalarType() && Ty->isIntegerTy(1) &&
"appended operand must be an i1 (vector) matching operand 0");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we assert that getOperand(0)->getScalarType()->isIntegerTy(1) earlier in the VPInstruction constructor?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I'll do that separately, and removed the bool check here

break;
case VPInstruction::ComputeReductionResult:
case VPInstruction::BuildVector:
case VPInstruction::BuildStructVector:
assert(Ty == getOperand(0)->getScalarType() &&
"appended operand must match operand 0's scalar type");
break;
case VPInstruction::ExtractLane:
assert(Ty == getOperand(1)->getScalarType() &&
"appended operand must match operand 1's scalar type");
break;
case VPInstruction::ExtractLastActive: {
// The recipe is constructed with 3 operands (result, data, mask). Extra
// operands beyond that are appended in (data, mask) pairs.
constexpr unsigned NumInitialOperands = 3;
assert(getNumOperands() >= NumInitialOperands &&
"ExtractLastActive must have at least the initial 3 operands");
bool IsMaskSlot = ((getNumOperands() - NumInitialOperands) & 1u) == 1u;
assert((IsMaskSlot ? Ty->isIntegerTy(1)
: Ty == getOperand(1)->getScalarType()) &&
"ExtractLastActive expects alternating data/mask operands "
"matching operand 1's type and i1, respectively");
break;
}
default:
llvm_unreachable("opcode does not support growing the operand list "
"outside of construction");
}
#endif
VPUser::addOperand(Op);
}

void VPInstruction::execute(VPTransformState &State) {
assert(!isMasked() && "cannot execute masked VPInstruction");
IRBuilderBase::FastMathFlagGuard FMFGuard(State.Builder);
Expand Down Expand Up @@ -2954,7 +2995,7 @@ void VPVectorEndPointerRecipe::materializeOffset(unsigned Part) {
VPValue *Offset = Builder.createAdd(
Offset0,
Builder.createOverflowingOp(Instruction::Mul, {PartxStride, VF}));
addOperand(Offset);
addOffset(Offset);
}

void VPVectorEndPointerRecipe::execute(VPTransformState &State) {
Expand Down
12 changes: 6 additions & 6 deletions llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2883,7 +2883,7 @@ addVPLaneMaskPhiAndUpdateExitBranch(VPlan &Plan) {
auto *ALM = Builder.createNaryOp(VPInstruction::ActiveLaneMask,
{InLoopIncrement, TC, ALMMultiplier}, DL,
"active.lane.mask.next");
LaneMaskPhi->addOperand(ALM);
LaneMaskPhi->addBackedgeValue(ALM);

// Replace the original terminator with BranchOnCond. We have to invert the
// mask here because a true condition means jumping to the exit block.
Expand Down Expand Up @@ -3348,12 +3348,12 @@ void VPlanTransforms::addExplicitVectorLength(
auto *NextIter = Builder.createAdd(
OpVPEVL, CurrentIteration, CanonicalIVIncrement->getDebugLoc(),
"current.iteration.next", CanonicalIVIncrement->getNoWrapFlags());
CurrentIteration->addOperand(NextIter);
CurrentIteration->addBackedgeValue(NextIter);

VPValue *NextAVL =
Builder.createSub(AVLPhi, OpVPEVL, DebugLoc::getCompilerGenerated(),
"avl.next", {/*NUW=*/true, /*NSW=*/false});
AVLPhi->addOperand(NextAVL);
AVLPhi->addIncoming(NextAVL);

fixupVFUsersForEVL(Plan, *VPEVL);
removeDeadRecipes(Plan);
Expand Down Expand Up @@ -3834,7 +3834,7 @@ expandVPWidenIntOrFpInduction(VPWidenIntOrFpInductionRecipe *WidenIVR) {
auto *Next = Builder.createNaryOp(AddOp, {Prev, Inc}, Flags,
WidenIVR->getDebugLoc(), "vec.ind.next");

WidePHI->addOperand(Next);
WidePHI->addIncoming(Next);

WidenIVR->replaceAllUsesWith(WidePHI);
}
Expand Down Expand Up @@ -3897,7 +3897,7 @@ static void expandVPWidenPointerInduction(VPWidenPointerInductionRecipe *R) {

VPValue *InductionGEP =
Builder.createPtrAdd(ScalarPtrPhi, Inc, DL, "ptr.ind");
ScalarPtrPhi->addOperand(InductionGEP);
ScalarPtrPhi->addIncoming(InductionGEP);
}

/// Expand a VPDerivedIVRecipe into executable recipes.
Expand Down Expand Up @@ -4344,7 +4344,7 @@ void VPlanTransforms::handleUncountableEarlyExits(VPlan &Plan,
DebugLoc::getUnknown(), "early.exit.value");
}
ExitIRI->removeIncomingValueFor(EarlyExitingVPBB);
ExitIRI->addOperand(NewIncoming);
ExitIRI->addIncoming(NewIncoming);
}

EarlyExitingVPBB->getTerminator()->eraseFromParent();
Expand Down
Loading