Skip to content

Commit

Permalink
[VPlan] Handle scalarized values in VPTransformState.
Browse files Browse the repository at this point in the history
This patch adds plumbing to handle scalarized values directly in
VPTransformState.

Reviewed By: gilr

Differential Revision: https://reviews.llvm.org/D92282
  • Loading branch information
fhahn committed Jan 25, 2021
1 parent 05d5125 commit 3201274
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 23 deletions.
12 changes: 9 additions & 3 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Expand Up @@ -7718,9 +7718,15 @@ void LoopVectorizationPlanner::executePlan(InnerLoopVectorizer &ILV,

assert(BestVF.hasValue() && "Vectorization Factor is missing");

VPTransformState State{*BestVF, BestUF, LI,
DT, ILV.Builder, ILV.VectorLoopValueMap,
&ILV, CallbackILV};
VPTransformState State{*BestVF,
BestUF,
OrigLoop,
LI,
DT,
ILV.Builder,
ILV.VectorLoopValueMap,
&ILV,
CallbackILV};
State.CFG.PrevBB = ILV.createVectorizedLoopSkeleton();
State.TripCount = ILV.getOrCreateTripCount(nullptr);
State.CanonicalIV = ILV.Induction;
Expand Down
21 changes: 21 additions & 0 deletions llvm/lib/Transforms/Vectorize/VPlan.cpp
Expand Up @@ -216,6 +216,27 @@ VPBasicBlock::iterator VPBasicBlock::getFirstNonPhi() {
return It;
}

Value *VPTransformState::get(VPValue *Def, const VPIteration &Instance) {
if (!Def->getDef() && OrigLoop->isLoopInvariant(Def->getLiveInIRValue()))
return Def->getLiveInIRValue();

if (hasScalarValue(Def, Instance))
return Data.PerPartScalars[Def][Instance.Part][Instance.Lane];

if (hasVectorValue(Def, Instance.Part)) {
assert(Data.PerPartOutput.count(Def));
auto *VecPart = Data.PerPartOutput[Def][Instance.Part];
if (!VecPart->getType()->isVectorTy()) {
assert(Instance.Lane == 0 && "cannot get lane > 0 for scalar");
return VecPart;
}
// TODO: Cache created scalar values.
return Builder.CreateExtractElement(VecPart,
Builder.getInt32(Instance.Lane));
}
return Callback.getOrCreateScalarValue(VPValue2Value[Def], Instance);
}

BasicBlock *
VPBasicBlock::createEmptyBasicBlock(VPTransformState::CFGState &CFG) {
// BB stands for IR BasicBlocks. VPBB stands for VPlan VPBasicBlocks.
Expand Down
54 changes: 34 additions & 20 deletions llvm/lib/Transforms/Vectorize/VPlan.h
Expand Up @@ -246,12 +246,12 @@ struct VPCallback {
/// VPTransformState holds information passed down when "executing" a VPlan,
/// needed for generating the output IR.
struct VPTransformState {
VPTransformState(ElementCount VF, unsigned UF, LoopInfo *LI,
VPTransformState(ElementCount VF, unsigned UF, Loop *OrigLoop, LoopInfo *LI,
DominatorTree *DT, IRBuilder<> &Builder,
VectorizerValueMap &ValueMap, InnerLoopVectorizer *ILV,
VPCallback &Callback)
: VF(VF), UF(UF), Instance(), LI(LI), DT(DT), Builder(Builder),
ValueMap(ValueMap), ILV(ILV), Callback(Callback) {}
: VF(VF), UF(UF), Instance(), OrigLoop(OrigLoop), LI(LI), DT(DT),
Builder(Builder), ValueMap(ValueMap), ILV(ILV), Callback(Callback) {}

/// The chosen Vectorization and Unroll Factors of the loop being vectorized.
ElementCount VF;
Expand All @@ -269,6 +269,9 @@ struct VPTransformState {
typedef SmallVector<Value *, 2> PerPartValuesTy;

DenseMap<VPValue *, PerPartValuesTy> PerPartOutput;

using ScalarsPerPartValuesTy = SmallVector<SmallVector<Value *, 4>, 2>;
DenseMap<VPValue *, ScalarsPerPartValuesTy> PerPartScalars;
} Data;

/// Get the generated Value for a given VPValue and a given Part. Note that
Expand All @@ -285,24 +288,21 @@ struct VPTransformState {
}

/// Get the generated Value for a given VPValue and given Part and Lane.
Value *get(VPValue *Def, const VPIteration &Instance) {
// If the Def is managed directly by VPTransformState, extract the lane from
// the relevant part. Note that currently only VPInstructions and external
// defs are managed by VPTransformState. Other Defs are still created by ILV
// and managed in its ValueMap. For those this method currently just
// delegates the call to ILV below.
if (Data.PerPartOutput.count(Def)) {
auto *VecPart = Data.PerPartOutput[Def][Instance.Part];
if (!VecPart->getType()->isVectorTy()) {
assert(Instance.Lane == 0 && "cannot get lane > 0 for scalar");
return VecPart;
}
// TODO: Cache created scalar values.
return Builder.CreateExtractElement(VecPart,
Builder.getInt32(Instance.Lane));
}
Value *get(VPValue *Def, const VPIteration &Instance);

return Callback.getOrCreateScalarValue(VPValue2Value[Def], Instance);
bool hasVectorValue(VPValue *Def, unsigned Part) {
auto I = Data.PerPartOutput.find(Def);
return I != Data.PerPartOutput.end() && Part < I->second.size() &&
I->second[Part];
}

bool hasScalarValue(VPValue *Def, VPIteration Instance) {
auto I = Data.PerPartScalars.find(Def);
if (I == Data.PerPartScalars.end())
return false;
return Instance.Part < I->second.size() &&
Instance.Lane < I->second[Instance.Part].size() &&
I->second[Instance.Part][Instance.Lane];
}

/// Set the generated Value for a given VPValue and a given Part.
Expand All @@ -315,6 +315,17 @@ struct VPTransformState {
}
void set(VPValue *Def, Value *IRDef, Value *V, unsigned Part);

void set(VPValue *Def, Value *V, const VPIteration &Instance) {
auto Iter = Data.PerPartScalars.insert({Def, {}});
auto &PerPartVec = Iter.first->second;
while (PerPartVec.size() <= Instance.Part)
PerPartVec.emplace_back();
auto &Scalars = PerPartVec[Instance.Part];
while (Scalars.size() <= Instance.Lane)
Scalars.push_back(nullptr);
Scalars[Instance.Lane] = V;
}

/// Hold state information used when constructing the CFG of the output IR,
/// traversing the VPBasicBlocks and generating corresponding IR BasicBlocks.
struct CFGState {
Expand All @@ -340,6 +351,9 @@ struct VPTransformState {
CFGState() = default;
} CFG;

/// Hold a pointer to the original loop.
Loop *OrigLoop;

/// Hold a pointer to LoopInfo to register new basic blocks in the loop.
LoopInfo *LI;

Expand Down

0 comments on commit 3201274

Please sign in to comment.