Skip to content

Commit 93f6c6b

Browse files
committed
Recommit "[VPlan] Use VPValue def for VPMemoryInstructionRecipe."
This reverts the revert commit 710aceb and includes a fix for a memsan failure. Original message: This patch turns VPMemoryInstructionRecipe into a VPValue and uses it during VPlan construction and codegeneration instead of the plain IR reference where possible.
1 parent b967b9a commit 93f6c6b

File tree

4 files changed

+114
-35
lines changed

4 files changed

+114
-35
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,10 @@ class InnerLoopVectorizer {
531531
/// value into a vector.
532532
Value *getOrCreateVectorValue(Value *V, unsigned Part);
533533

534+
void setVectorValue(Value *Scalar, unsigned Part, Value *Vector) {
535+
VectorLoopValueMap.setVectorValue(Scalar, Part, Vector);
536+
}
537+
534538
/// Return a value in the new loop corresponding to \p V from the original
535539
/// loop at unroll and vector indices \p Instance. If the value has been
536540
/// vectorized but not scalarized, the necessary extractelement instruction
@@ -553,8 +557,8 @@ class InnerLoopVectorizer {
553557
/// non-null. Use \p State to translate given VPValues to IR values in the
554558
/// vectorized loop.
555559
void vectorizeMemoryInstruction(Instruction *Instr, VPTransformState &State,
556-
VPValue *Addr, VPValue *StoredValue,
557-
VPValue *BlockInMask);
560+
VPValue *Def, VPValue *Addr,
561+
VPValue *StoredValue, VPValue *BlockInMask);
558562

559563
/// Set the debug location in the builder using the debug location in
560564
/// the instruction.
@@ -2503,11 +2507,9 @@ void InnerLoopVectorizer::vectorizeInterleaveGroup(
25032507
}
25042508
}
25052509

2506-
void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr,
2507-
VPTransformState &State,
2508-
VPValue *Addr,
2509-
VPValue *StoredValue,
2510-
VPValue *BlockInMask) {
2510+
void InnerLoopVectorizer::vectorizeMemoryInstruction(
2511+
Instruction *Instr, VPTransformState &State, VPValue *Def, VPValue *Addr,
2512+
VPValue *StoredValue, VPValue *BlockInMask) {
25112513
// Attempt to issue a wide load.
25122514
LoadInst *LI = dyn_cast<LoadInst>(Instr);
25132515
StoreInst *SI = dyn_cast<StoreInst>(Instr);
@@ -2636,7 +2638,8 @@ void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr,
26362638
if (Reverse)
26372639
NewLI = reverseVector(NewLI);
26382640
}
2639-
VectorLoopValueMap.setVectorValue(Instr, Part, NewLI);
2641+
2642+
State.set(Def, Instr, NewLI, Part);
26402643
}
26412644
}
26422645

@@ -7763,6 +7766,16 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
77637766

77647767
if (auto Recipe =
77657768
RecipeBuilder.tryToCreateWidenRecipe(Instr, Range, Plan)) {
7769+
// Check if the recipe can be converted to a VPValue. We need the extra
7770+
// down-casting step until VPRecipeBase inherits from VPValue.
7771+
VPValue *MaybeVPValue = Recipe->toVPValue();
7772+
if (!Instr->getType()->isVoidTy() && MaybeVPValue) {
7773+
if (NeedDef.contains(Instr))
7774+
Plan->addOrReplaceVPValue(Instr, MaybeVPValue);
7775+
else
7776+
Plan->addVPValue(Instr, MaybeVPValue);
7777+
}
7778+
77667779
RecipeBuilder.setRecipe(Instr, Recipe);
77677780
VPBB->appendRecipe(Recipe);
77687781
continue;
@@ -7812,6 +7825,11 @@ VPlanPtr LoopVectorizationPlanner::buildVPlanWithVPRecipes(
78127825

78137826
for (unsigned i = 0; i < IG->getFactor(); ++i)
78147827
if (Instruction *Member = IG->getMember(i)) {
7828+
if (!Member->getType()->isVoidTy()) {
7829+
VPValue *OriginalV = Plan->getVPValue(Member);
7830+
Plan->removeVPValueFor(Member);
7831+
OriginalV->replaceAllUsesWith(Plan->getOrAddVPValue(Member));
7832+
}
78157833
RecipeBuilder.getRecipe(Member)->eraseFromParent();
78167834
}
78177835
}
@@ -8154,9 +8172,11 @@ void VPPredInstPHIRecipe::execute(VPTransformState &State) {
81548172
}
81558173

81568174
void VPWidenMemoryInstructionRecipe::execute(VPTransformState &State) {
8175+
Instruction *Instr = getUnderlyingInstr();
81578176
VPValue *StoredValue = isa<StoreInst>(Instr) ? getStoredValue() : nullptr;
8158-
State.ILV->vectorizeMemoryInstruction(&Instr, State, getAddr(), StoredValue,
8159-
getMask());
8177+
State.ILV->vectorizeMemoryInstruction(Instr, State,
8178+
StoredValue ? nullptr : this, getAddr(),
8179+
StoredValue, getMask());
81608180
}
81618181

81628182
// Determine how to lower the scalar epilogue, which depends on 1) optimising
@@ -8202,6 +8222,12 @@ static ScalarEpilogueLowering getScalarEpilogueLowering(
82028222
return CM_ScalarEpilogueAllowed;
82038223
}
82048224

8225+
void VPTransformState::set(VPValue *Def, Value *IRDef, Value *V,
8226+
unsigned Part) {
8227+
set(Def, V, Part);
8228+
ILV->setVectorValue(IRDef, Part, V);
8229+
}
8230+
82058231
// Process the loop in the VPlan-native vectorization path. This path builds
82068232
// VPlan upfront in the vectorization pipeline, which allows to apply
82078233
// VPlan-to-VPlan transformations from the very beginning without modifying the

llvm/lib/Transforms/Vectorize/VPlan.cpp

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ VPUser *VPRecipeBase::toVPUser() {
101101
return nullptr;
102102
}
103103

104+
VPValue *VPRecipeBase::toVPValue() {
105+
if (auto *V = dyn_cast<VPInstruction>(this))
106+
return V;
107+
if (auto *V = dyn_cast<VPWidenMemoryInstructionRecipe>(this))
108+
return V;
109+
return nullptr;
110+
}
111+
112+
const VPValue *VPRecipeBase::toVPValue() const {
113+
if (auto *V = dyn_cast<VPInstruction>(this))
114+
return V;
115+
if (auto *V = dyn_cast<VPWidenMemoryInstructionRecipe>(this))
116+
return V;
117+
return nullptr;
118+
}
119+
104120
// Get the top-most entry block of \p Start. This is the entry block of the
105121
// containing VPlan. This function is templated to support both const and non-const blocks
106122
template <typename T> static T *getPlanEntry(T *Start) {
@@ -405,12 +421,6 @@ void VPRecipeBase::removeFromParent() {
405421
Parent = nullptr;
406422
}
407423

408-
VPValue *VPRecipeBase::toVPValue() {
409-
if (auto *V = dyn_cast<VPInstruction>(this))
410-
return V;
411-
return nullptr;
412-
}
413-
414424
iplist<VPRecipeBase>::iterator VPRecipeBase::eraseFromParent() {
415425
assert(getParent() && "Recipe not in any VPBasicBlock");
416426
return getParent()->getRecipeList().erase(getIterator());
@@ -903,7 +913,8 @@ void VPPredInstPHIRecipe::print(raw_ostream &O, const Twine &Indent,
903913

904914
void VPWidenMemoryInstructionRecipe::print(raw_ostream &O, const Twine &Indent,
905915
VPSlotTracker &SlotTracker) const {
906-
O << "\"WIDEN " << Instruction::getOpcodeName(Instr.getOpcode()) << " ";
916+
O << "\"WIDEN "
917+
<< Instruction::getOpcodeName(getUnderlyingInstr()->getOpcode()) << " ";
907918

908919
bool First = true;
909920
for (VPValue *Op : operands()) {

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,10 @@ struct VPTransformState {
282282
// delegates the call to ILV below.
283283
if (Data.PerPartOutput.count(Def)) {
284284
auto *VecPart = Data.PerPartOutput[Def][Instance.Part];
285+
if (!VecPart->getType()->isVectorTy()) {
286+
assert(Instance.Lane == 0 && "cannot get lane > 0 for scalar");
287+
return VecPart;
288+
}
285289
// TODO: Cache created scalar values.
286290
return Builder.CreateExtractElement(VecPart,
287291
Builder.getInt32(Instance.Lane));
@@ -298,6 +302,7 @@ struct VPTransformState {
298302
}
299303
Data.PerPartOutput[Def][Part] = V;
300304
}
305+
void set(VPValue *Def, Value *IRDef, Value *V, unsigned Part);
301306

302307
/// Hold state information used when constructing the CFG of the output IR,
303308
/// traversing the VPBasicBlocks and generating corresponding IR BasicBlocks.
@@ -684,6 +689,20 @@ class VPRecipeBase : public ilist_node_with_parent<VPRecipeBase, VPBasicBlock> {
684689
/// Returns a pointer to a VPValue, if the recipe inherits from VPValue or
685690
/// nullptr otherwise.
686691
VPValue *toVPValue();
692+
const VPValue *toVPValue() const;
693+
694+
/// Returns the underlying instruction, if the recipe is a VPValue or nullptr
695+
/// otherwise.
696+
Instruction *getUnderlyingInstr() {
697+
if (auto *VPV = toVPValue())
698+
return cast_or_null<Instruction>(VPV->getUnderlyingValue());
699+
return nullptr;
700+
}
701+
const Instruction *getUnderlyingInstr() const {
702+
if (auto *VPV = toVPValue())
703+
return cast_or_null<Instruction>(VPV->getUnderlyingValue());
704+
return nullptr;
705+
}
687706
};
688707

689708
inline bool VPUser::classof(const VPRecipeBase *Recipe) {
@@ -725,10 +744,6 @@ class VPInstruction : public VPUser, public VPValue, public VPRecipeBase {
725744
void generateInstruction(VPTransformState &State, unsigned Part);
726745

727746
protected:
728-
Instruction *getUnderlyingInstr() {
729-
return cast_or_null<Instruction>(getUnderlyingValue());
730-
}
731-
732747
void setUnderlyingInstr(Instruction *I) { setUnderlyingValue(I); }
733748

734749
public:
@@ -1207,8 +1222,9 @@ class VPPredInstPHIRecipe : public VPRecipeBase {
12071222
/// - For store: Address, stored value, optional mask
12081223
/// TODO: We currently execute only per-part unless a specific instance is
12091224
/// provided.
1210-
class VPWidenMemoryInstructionRecipe : public VPRecipeBase, public VPUser {
1211-
Instruction &Instr;
1225+
class VPWidenMemoryInstructionRecipe : public VPRecipeBase,
1226+
public VPValue,
1227+
public VPUser {
12121228

12131229
void setMask(VPValue *Mask) {
12141230
if (!Mask)
@@ -1217,20 +1233,22 @@ class VPWidenMemoryInstructionRecipe : public VPRecipeBase, public VPUser {
12171233
}
12181234

12191235
bool isMasked() const {
1220-
return (isa<LoadInst>(Instr) && getNumOperands() == 2) ||
1221-
(isa<StoreInst>(Instr) && getNumOperands() == 3);
1236+
return (isa<LoadInst>(getUnderlyingInstr()) && getNumOperands() == 2) ||
1237+
(isa<StoreInst>(getUnderlyingInstr()) && getNumOperands() == 3);
12221238
}
12231239

12241240
public:
12251241
VPWidenMemoryInstructionRecipe(LoadInst &Load, VPValue *Addr, VPValue *Mask)
1226-
: VPRecipeBase(VPWidenMemoryInstructionSC), VPUser({Addr}), Instr(Load) {
1242+
: VPRecipeBase(VPWidenMemoryInstructionSC),
1243+
VPValue(VPValue::VPMemoryInstructionSC, &Load), VPUser({Addr}) {
12271244
setMask(Mask);
12281245
}
12291246

12301247
VPWidenMemoryInstructionRecipe(StoreInst &Store, VPValue *Addr,
12311248
VPValue *StoredValue, VPValue *Mask)
1232-
: VPRecipeBase(VPWidenMemoryInstructionSC), VPUser({Addr, StoredValue}),
1233-
Instr(Store) {
1249+
: VPRecipeBase(VPWidenMemoryInstructionSC),
1250+
VPValue(VPValue::VPMemoryInstructionSC, &Store),
1251+
VPUser({Addr, StoredValue}) {
12341252
setMask(Mask);
12351253
}
12361254

@@ -1253,7 +1271,7 @@ class VPWidenMemoryInstructionRecipe : public VPRecipeBase, public VPUser {
12531271

12541272
/// Return the address accessed by this recipe.
12551273
VPValue *getStoredValue() const {
1256-
assert(isa<StoreInst>(Instr) &&
1274+
assert(isa<StoreInst>(getUnderlyingInstr()) &&
12571275
"Stored value only available for store instructions");
12581276
return getOperand(1); // Stored value is the 2nd, mandatory operand.
12591277
}
@@ -1619,6 +1637,10 @@ class VPlan {
16191637
/// VPlan.
16201638
Value2VPValueTy Value2VPValue;
16211639

1640+
/// Contains all VPValues that been allocated by addVPValue directly and need
1641+
/// to be free when the plan's destructor is called.
1642+
SmallVector<VPValue *, 16> VPValuesToFree;
1643+
16221644
/// Holds the VPLoopInfo analysis for this VPlan.
16231645
VPLoopInfo VPLInfo;
16241646

@@ -1634,8 +1656,8 @@ class VPlan {
16341656
~VPlan() {
16351657
if (Entry)
16361658
VPBlockBase::deleteCFG(Entry);
1637-
for (auto &MapEntry : Value2VPValue)
1638-
delete MapEntry.second;
1659+
for (VPValue *VPV : VPValuesToFree)
1660+
delete VPV;
16391661
if (BackedgeTakenCount)
16401662
delete BackedgeTakenCount;
16411663
for (VPValue *Def : VPExternalDefs)
@@ -1685,7 +1707,24 @@ class VPlan {
16851707
void addVPValue(Value *V) {
16861708
assert(V && "Trying to add a null Value to VPlan");
16871709
assert(!Value2VPValue.count(V) && "Value already exists in VPlan");
1688-
Value2VPValue[V] = new VPValue(V);
1710+
VPValue *VPV = new VPValue(V);
1711+
Value2VPValue[V] = VPV;
1712+
VPValuesToFree.push_back(VPV);
1713+
}
1714+
1715+
void addVPValue(Value *V, VPValue *VPV) {
1716+
assert(V && "Trying to add a null Value to VPlan");
1717+
assert(!Value2VPValue.count(V) && "Value already exists in VPlan");
1718+
Value2VPValue[V] = VPV;
1719+
}
1720+
1721+
void addOrReplaceVPValue(Value *V, VPValue *VPV) {
1722+
assert(V && "Trying to add a null Value to VPlan");
1723+
auto I = Value2VPValue.find(V);
1724+
if (I == Value2VPValue.end())
1725+
Value2VPValue[V] = VPV;
1726+
else
1727+
I->second = VPV;
16891728
}
16901729

16911730
VPValue *getVPValue(Value *V) {
@@ -1701,6 +1740,8 @@ class VPlan {
17011740
return getVPValue(V);
17021741
}
17031742

1743+
void removeVPValueFor(Value *V) { Value2VPValue.erase(V); }
1744+
17041745
/// Return the VPLoopInfo analysis for this VPlan.
17051746
VPLoopInfo &getVPLoopInfo() { return VPLInfo; }
17061747
const VPLoopInfo &getVPLoopInfo() const { return VPLInfo; }
@@ -1782,9 +1823,9 @@ class VPlanPrinter {
17821823
};
17831824

17841825
struct VPlanIngredient {
1785-
Value *V;
1826+
const Value *V;
17861827

1787-
VPlanIngredient(Value *V) : V(V) {}
1828+
VPlanIngredient(const Value *V) : V(V) {}
17881829
};
17891830

17901831
inline raw_ostream &operator<<(raw_ostream &OS, const VPlanIngredient &I) {

llvm/lib/Transforms/Vectorize/VPlanValue.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class VPValue {
4343
friend class VPBasicBlock;
4444
friend class VPInterleavedAccessInfo;
4545
friend class VPSlotTracker;
46+
friend class VPRecipeBase;
4647

4748
const unsigned char SubclassID; ///< Subclass identifier (for isa/dyn_cast).
4849

@@ -77,7 +78,7 @@ class VPValue {
7778
/// are actually instantiated. Values of this enumeration are kept in the
7879
/// SubclassID field of the VPValue objects. They are used for concrete
7980
/// type identification.
80-
enum { VPValueSC, VPInstructionSC };
81+
enum { VPValueSC, VPInstructionSC, VPMemoryInstructionSC };
8182

8283
VPValue(Value *UV = nullptr) : VPValue(VPValueSC, UV) {}
8384
VPValue(const VPValue &) = delete;

0 commit comments

Comments
 (0)