Skip to content

Commit 078c863

Browse files
committed
[LV] Replace stored value with a VPValue (NFCI)
InnerLoopVectorizer's code called during VPlan execution still relies on original IR's def-use relations to decide which vector code to generate, limiting VPlan transformations ability to modify def-use relations and still have ILV generate the vector code. This commit introduces a VPValue for VPWidenMemoryInstructionRecipe to use as the stored value. The recipe is generated with a VPValue wrapping the stored value of the scalar store. This reduces ingredient def-use usage by ILV as a step towards full VPlan-based def-use relations. Differential Revision: https://reviews.llvm.org/D76373
1 parent d72c586 commit 078c863

File tree

3 files changed

+54
-14
lines changed

3 files changed

+54
-14
lines changed

llvm/lib/Transforms/Vectorize/LoopVectorize.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,8 @@ class InnerLoopVectorizer {
486486
/// non-null. Use \p State to translate given VPValues to IR values in the
487487
/// vectorized loop.
488488
void vectorizeMemoryInstruction(Instruction *Instr, VPTransformState &State,
489-
VPValue *Addr,
490-
VPValue *BlockInMask = nullptr);
489+
VPValue *Addr, VPValue *StoredValue,
490+
VPValue *BlockInMask);
491491

492492
/// Set the debug location in the builder using the debug location in
493493
/// the instruction.
@@ -2348,12 +2348,15 @@ void InnerLoopVectorizer::vectorizeInterleaveGroup(Instruction *Instr,
23482348
void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr,
23492349
VPTransformState &State,
23502350
VPValue *Addr,
2351+
VPValue *StoredValue,
23512352
VPValue *BlockInMask) {
23522353
// Attempt to issue a wide load.
23532354
LoadInst *LI = dyn_cast<LoadInst>(Instr);
23542355
StoreInst *SI = dyn_cast<StoreInst>(Instr);
23552356

23562357
assert((LI || SI) && "Invalid Load/Store instruction");
2358+
assert((!SI || StoredValue) && "No stored value provided for widened store");
2359+
assert((!LI || !StoredValue) && "Stored value provided for widened load");
23572360

23582361
LoopVectorizationCostModel::InstWidening Decision =
23592362
Cost->getWideningDecision(Instr, VF);
@@ -2425,7 +2428,7 @@ void InnerLoopVectorizer::vectorizeMemoryInstruction(Instruction *Instr,
24252428

24262429
for (unsigned Part = 0; Part < UF; ++Part) {
24272430
Instruction *NewSI = nullptr;
2428-
Value *StoredVal = getOrCreateVectorValue(SI->getValueOperand(), Part);
2431+
Value *StoredVal = State.get(StoredValue, Part);
24292432
if (CreateGatherScatter) {
24302433
Value *MaskPart = isMaskRequired ? BlockInMaskParts[Part] : nullptr;
24312434
Value *VectorGep = State.get(Addr, Part);
@@ -6807,7 +6810,12 @@ VPRecipeBuilder::tryToWidenMemory(Instruction *I, VFRange &Range,
68076810
Mask = createBlockInMask(I->getParent(), Plan);
68086811

68096812
VPValue *Addr = Plan->getOrAddVPValue(getLoadStorePointerOperand(I));
6810-
return new VPWidenMemoryInstructionRecipe(*I, Addr, Mask);
6813+
if (LoadInst *Load = dyn_cast<LoadInst>(I))
6814+
return new VPWidenMemoryInstructionRecipe(*Load, Addr, Mask);
6815+
6816+
StoreInst *Store = cast<StoreInst>(I);
6817+
VPValue *StoredValue = Plan->getOrAddVPValue(Store->getValueOperand());
6818+
return new VPWidenMemoryInstructionRecipe(*Store, Addr, StoredValue, Mask);
68116819
}
68126820

68136821
VPWidenIntOrFpInductionRecipe *
@@ -7515,7 +7523,9 @@ void VPPredInstPHIRecipe::execute(VPTransformState &State) {
75157523
}
75167524

75177525
void VPWidenMemoryInstructionRecipe::execute(VPTransformState &State) {
7518-
State.ILV->vectorizeMemoryInstruction(&Instr, State, getAddr(), getMask());
7526+
VPValue *StoredValue = isa<StoreInst>(Instr) ? getStoredValue() : nullptr;
7527+
State.ILV->vectorizeMemoryInstruction(&Instr, State, getAddr(), StoredValue,
7528+
getMask());
75197529
}
75207530

75217531
// Determine how to lower the scalar epilogue, which depends on 1) optimising

llvm/lib/Transforms/Vectorize/VPlan.h

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,19 +1061,38 @@ class VPPredInstPHIRecipe : public VPRecipeBase {
10611061
};
10621062

10631063
/// A Recipe for widening load/store operations.
1064+
/// The recipe uses the following VPValues:
1065+
/// - For load: Address, optional mask
1066+
/// - For store: Address, stored value, optional mask
10641067
/// TODO: We currently execute only per-part unless a specific instance is
10651068
/// provided.
10661069
class VPWidenMemoryInstructionRecipe : public VPRecipeBase {
10671070
private:
10681071
Instruction &Instr;
10691072
VPUser User;
10701073

1074+
void setMask(VPValue *Mask) {
1075+
if (!Mask)
1076+
return;
1077+
User.addOperand(Mask);
1078+
}
1079+
1080+
bool isMasked() const {
1081+
return (isa<LoadInst>(Instr) && User.getNumOperands() == 2) ||
1082+
(isa<StoreInst>(Instr) && User.getNumOperands() == 3);
1083+
}
1084+
10711085
public:
1072-
VPWidenMemoryInstructionRecipe(Instruction &Instr, VPValue *Addr,
1073-
VPValue *Mask)
1074-
: VPRecipeBase(VPWidenMemoryInstructionSC), Instr(Instr), User({Addr}) {
1075-
if (Mask)
1076-
User.addOperand(Mask);
1086+
VPWidenMemoryInstructionRecipe(LoadInst &Load, VPValue *Addr, VPValue *Mask)
1087+
: VPRecipeBase(VPWidenMemoryInstructionSC), Instr(Load), User({Addr}) {
1088+
setMask(Mask);
1089+
}
1090+
1091+
VPWidenMemoryInstructionRecipe(StoreInst &Store, VPValue *Addr,
1092+
VPValue *StoredValue, VPValue *Mask)
1093+
: VPRecipeBase(VPWidenMemoryInstructionSC), Instr(Store),
1094+
User({Addr, StoredValue}) {
1095+
setMask(Mask);
10771096
}
10781097

10791098
/// Method to support type inquiry through isa, cast, and dyn_cast.
@@ -1089,8 +1108,15 @@ class VPWidenMemoryInstructionRecipe : public VPRecipeBase {
10891108
/// Return the mask used by this recipe. Note that a full mask is represented
10901109
/// by a nullptr.
10911110
VPValue *getMask() const {
1092-
// Mask is optional and therefore the last, currently 2nd operand.
1093-
return User.getNumOperands() == 2 ? User.getOperand(1) : nullptr;
1111+
// Mask is optional and therefore the last operand.
1112+
return isMasked() ? User.getOperand(User.getNumOperands() - 1) : nullptr;
1113+
}
1114+
1115+
/// Return the address accessed by this recipe.
1116+
VPValue *getStoredValue() const {
1117+
assert(isa<StoreInst>(Instr) &&
1118+
"Stored value only available for store instructions");
1119+
return User.getOperand(1); // Stored value is the 2nd, mandatory operand.
10941120
}
10951121

10961122
/// Generate the wide load/store.

llvm/lib/Transforms/Vectorize/VPlanTransforms.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,14 @@ void VPlanTransforms::VPInstructionsToVPRecipes(
5555

5656
VPRecipeBase *NewRecipe = nullptr;
5757
// Create VPWidenMemoryInstructionRecipe for loads and stores.
58-
if (isa<LoadInst>(Inst) || isa<StoreInst>(Inst))
58+
if (LoadInst *Load = dyn_cast<LoadInst>(Inst))
5959
NewRecipe = new VPWidenMemoryInstructionRecipe(
60-
*Inst, Plan->getOrAddVPValue(getLoadStorePointerOperand(Inst)),
60+
*Load, Plan->getOrAddVPValue(getLoadStorePointerOperand(Inst)),
6161
nullptr /*Mask*/);
62+
else if (StoreInst *Store = dyn_cast<StoreInst>(Inst))
63+
NewRecipe = new VPWidenMemoryInstructionRecipe(
64+
*Store, Plan->getOrAddVPValue(getLoadStorePointerOperand(Inst)),
65+
Plan->getOrAddVPValue(Store->getValueOperand()), nullptr /*Mask*/);
6266
else if (PHINode *Phi = dyn_cast<PHINode>(Inst)) {
6367
InductionDescriptor II = Inductions.lookup(Phi);
6468
if (II.getKind() == InductionDescriptor::IK_IntInduction ||

0 commit comments

Comments
 (0)