forked from OSchip/llvm-project
[LV] Move VPWidenGEPRecipe::execute to VPlanRecipes.cpp (NFC).
This commit is contained in:
parent
86b8c1d9c4
commit
6a4bc452f8
|
@ -9158,79 +9158,6 @@ void VPWidenCallRecipe::execute(VPTransformState &State) {
|
|||
*this, State);
|
||||
}
|
||||
|
||||
void VPWidenGEPRecipe::execute(VPTransformState &State) {
|
||||
auto *GEP = cast<GetElementPtrInst>(getUnderlyingInstr());
|
||||
// Construct a vector GEP by widening the operands of the scalar GEP as
|
||||
// necessary. We mark the vector GEP 'inbounds' if appropriate. A GEP
|
||||
// results in a vector of pointers when at least one operand of the GEP
|
||||
// is vector-typed. Thus, to keep the representation compact, we only use
|
||||
// vector-typed operands for loop-varying values.
|
||||
|
||||
if (State.VF.isVector() && IsPtrLoopInvariant && IsIndexLoopInvariant.all()) {
|
||||
// If we are vectorizing, but the GEP has only loop-invariant operands,
|
||||
// the GEP we build (by only using vector-typed operands for
|
||||
// loop-varying values) would be a scalar pointer. Thus, to ensure we
|
||||
// produce a vector of pointers, we need to either arbitrarily pick an
|
||||
// operand to broadcast, or broadcast a clone of the original GEP.
|
||||
// Here, we broadcast a clone of the original.
|
||||
//
|
||||
// TODO: If at some point we decide to scalarize instructions having
|
||||
// loop-invariant operands, this special case will no longer be
|
||||
// required. We would add the scalarization decision to
|
||||
// collectLoopScalars() and teach getVectorValue() to broadcast
|
||||
// the lane-zero scalar value.
|
||||
auto *Clone = State.Builder.Insert(GEP->clone());
|
||||
for (unsigned Part = 0; Part < State.UF; ++Part) {
|
||||
Value *EntryPart = State.Builder.CreateVectorSplat(State.VF, Clone);
|
||||
State.set(this, EntryPart, Part);
|
||||
State.addMetadata(EntryPart, GEP);
|
||||
}
|
||||
} else {
|
||||
// If the GEP has at least one loop-varying operand, we are sure to
|
||||
// produce a vector of pointers. But if we are only unrolling, we want
|
||||
// to produce a scalar GEP for each unroll part. Thus, the GEP we
|
||||
// produce with the code below will be scalar (if VF == 1) or vector
|
||||
// (otherwise). Note that for the unroll-only case, we still maintain
|
||||
// values in the vector mapping with initVector, as we do for other
|
||||
// instructions.
|
||||
for (unsigned Part = 0; Part < State.UF; ++Part) {
|
||||
// The pointer operand of the new GEP. If it's loop-invariant, we
|
||||
// won't broadcast it.
|
||||
auto *Ptr = IsPtrLoopInvariant
|
||||
? State.get(getOperand(0), VPIteration(0, 0))
|
||||
: State.get(getOperand(0), Part);
|
||||
|
||||
// Collect all the indices for the new GEP. If any index is
|
||||
// loop-invariant, we won't broadcast it.
|
||||
SmallVector<Value *, 4> Indices;
|
||||
for (unsigned I = 1, E = getNumOperands(); I < E; I++) {
|
||||
VPValue *Operand = getOperand(I);
|
||||
if (IsIndexLoopInvariant[I - 1])
|
||||
Indices.push_back(State.get(Operand, VPIteration(0, 0)));
|
||||
else
|
||||
Indices.push_back(State.get(Operand, Part));
|
||||
}
|
||||
|
||||
// If the GEP instruction is vectorized and was in a basic block that
|
||||
// needed predication, we can't propagate the poison-generating 'inbounds'
|
||||
// flag. The control flow has been linearized and the GEP is no longer
|
||||
// guarded by the predicate, which could make the 'inbounds' properties to
|
||||
// no longer hold.
|
||||
bool IsInBounds =
|
||||
GEP->isInBounds() && State.MayGeneratePoisonRecipes.count(this) == 0;
|
||||
|
||||
// Create the new GEP. Note that this GEP may be a scalar if VF == 1,
|
||||
// but it should be a vector, otherwise.
|
||||
auto *NewGEP = State.Builder.CreateGEP(GEP->getSourceElementType(), Ptr,
|
||||
Indices, "", IsInBounds);
|
||||
assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) &&
|
||||
"NewGEP is not a pointer vector");
|
||||
State.set(this, NewGEP, Part);
|
||||
State.addMetadata(NewGEP, GEP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VPWidenIntOrFpInductionRecipe::execute(VPTransformState &State) {
|
||||
assert(!State.Instance && "Int or FP induction being replicated.");
|
||||
|
||||
|
|
|
@ -641,7 +641,82 @@ void VPScalarIVStepsRecipe::print(raw_ostream &O, const Twine &Indent,
|
|||
O << Indent << "= SCALAR-STEPS ";
|
||||
printOperands(O, SlotTracker);
|
||||
}
|
||||
#endif
|
||||
|
||||
void VPWidenGEPRecipe::execute(VPTransformState &State) {
|
||||
auto *GEP = cast<GetElementPtrInst>(getUnderlyingInstr());
|
||||
// Construct a vector GEP by widening the operands of the scalar GEP as
|
||||
// necessary. We mark the vector GEP 'inbounds' if appropriate. A GEP
|
||||
// results in a vector of pointers when at least one operand of the GEP
|
||||
// is vector-typed. Thus, to keep the representation compact, we only use
|
||||
// vector-typed operands for loop-varying values.
|
||||
|
||||
if (State.VF.isVector() && IsPtrLoopInvariant && IsIndexLoopInvariant.all()) {
|
||||
// If we are vectorizing, but the GEP has only loop-invariant operands,
|
||||
// the GEP we build (by only using vector-typed operands for
|
||||
// loop-varying values) would be a scalar pointer. Thus, to ensure we
|
||||
// produce a vector of pointers, we need to either arbitrarily pick an
|
||||
// operand to broadcast, or broadcast a clone of the original GEP.
|
||||
// Here, we broadcast a clone of the original.
|
||||
//
|
||||
// TODO: If at some point we decide to scalarize instructions having
|
||||
// loop-invariant operands, this special case will no longer be
|
||||
// required. We would add the scalarization decision to
|
||||
// collectLoopScalars() and teach getVectorValue() to broadcast
|
||||
// the lane-zero scalar value.
|
||||
auto *Clone = State.Builder.Insert(GEP->clone());
|
||||
for (unsigned Part = 0; Part < State.UF; ++Part) {
|
||||
Value *EntryPart = State.Builder.CreateVectorSplat(State.VF, Clone);
|
||||
State.set(this, EntryPart, Part);
|
||||
State.addMetadata(EntryPart, GEP);
|
||||
}
|
||||
} else {
|
||||
// If the GEP has at least one loop-varying operand, we are sure to
|
||||
// produce a vector of pointers. But if we are only unrolling, we want
|
||||
// to produce a scalar GEP for each unroll part. Thus, the GEP we
|
||||
// produce with the code below will be scalar (if VF == 1) or vector
|
||||
// (otherwise). Note that for the unroll-only case, we still maintain
|
||||
// values in the vector mapping with initVector, as we do for other
|
||||
// instructions.
|
||||
for (unsigned Part = 0; Part < State.UF; ++Part) {
|
||||
// The pointer operand of the new GEP. If it's loop-invariant, we
|
||||
// won't broadcast it.
|
||||
auto *Ptr = IsPtrLoopInvariant
|
||||
? State.get(getOperand(0), VPIteration(0, 0))
|
||||
: State.get(getOperand(0), Part);
|
||||
|
||||
// Collect all the indices for the new GEP. If any index is
|
||||
// loop-invariant, we won't broadcast it.
|
||||
SmallVector<Value *, 4> Indices;
|
||||
for (unsigned I = 1, E = getNumOperands(); I < E; I++) {
|
||||
VPValue *Operand = getOperand(I);
|
||||
if (IsIndexLoopInvariant[I - 1])
|
||||
Indices.push_back(State.get(Operand, VPIteration(0, 0)));
|
||||
else
|
||||
Indices.push_back(State.get(Operand, Part));
|
||||
}
|
||||
|
||||
// If the GEP instruction is vectorized and was in a basic block that
|
||||
// needed predication, we can't propagate the poison-generating 'inbounds'
|
||||
// flag. The control flow has been linearized and the GEP is no longer
|
||||
// guarded by the predicate, which could make the 'inbounds' properties to
|
||||
// no longer hold.
|
||||
bool IsInBounds =
|
||||
GEP->isInBounds() && State.MayGeneratePoisonRecipes.count(this) == 0;
|
||||
|
||||
// Create the new GEP. Note that this GEP may be a scalar if VF == 1,
|
||||
// but it should be a vector, otherwise.
|
||||
auto *NewGEP = State.Builder.CreateGEP(GEP->getSourceElementType(), Ptr,
|
||||
Indices, "", IsInBounds);
|
||||
assert((State.VF.isScalar() || NewGEP->getType()->isVectorTy()) &&
|
||||
"NewGEP is not a pointer vector");
|
||||
State.set(this, NewGEP, Part);
|
||||
State.addMetadata(NewGEP, GEP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
void VPWidenGEPRecipe::print(raw_ostream &O, const Twine &Indent,
|
||||
VPSlotTracker &SlotTracker) const {
|
||||
O << Indent << "WIDEN-GEP ";
|
||||
|
|
Loading…
Reference in New Issue