forked from OSchip/llvm-project
[VPlan] Move widening check for non-memory/non-calls to function (NFC).
After introducing VPWidenSelectRecipe, the duplicated logic can be shared. Reviewers: gilr, rengolin, Ayal, hsaito Reviewed By: Ayal Differential Revision: https://reviews.llvm.org/D77973
This commit is contained in:
parent
ff18a6acea
commit
5b4b3e0b6e
|
@ -6931,22 +6931,24 @@ VPRecipeBuilder::tryToWidenCall(Instruction *I, VFRange &Range, VPlan &Plan) {
|
|||
return new VPWidenCallRecipe(*CI, VPValues);
|
||||
}
|
||||
|
||||
VPWidenSelectRecipe *VPRecipeBuilder::tryToWidenSelect(Instruction *I,
|
||||
VFRange &Range) {
|
||||
bool VPRecipeBuilder::shouldWiden(Instruction *I, VFRange &Range) const {
|
||||
assert(!isa<PHINode>(I) && !isa<LoadInst>(I) && !isa<StoreInst>(I) &&
|
||||
"Instruction should have been handled earlier");
|
||||
// Instruction should be widened, unless it is scalar after vectorization,
|
||||
// scalarization is profitable or it is predicated.
|
||||
auto WillScalarize = [this, I](unsigned VF) -> bool {
|
||||
return CM.isScalarAfterVectorization(I, VF) ||
|
||||
CM.isProfitableToScalarize(I, VF) ||
|
||||
CM.isScalarWithPredication(I, VF);
|
||||
};
|
||||
return !LoopVectorizationPlanner::getDecisionAndClampRange(WillScalarize,
|
||||
Range);
|
||||
}
|
||||
|
||||
VPWidenSelectRecipe *VPRecipeBuilder::tryToWidenSelect(Instruction *I) {
|
||||
auto *SI = dyn_cast<SelectInst>(I);
|
||||
if (!SI)
|
||||
return nullptr;
|
||||
|
||||
// SI should be widened, unless it is scalar after vectorization,
|
||||
// scalarization is profitable or it is predicated.
|
||||
auto willWiden = [this, SI](unsigned VF) -> bool {
|
||||
return !CM.isScalarAfterVectorization(SI, VF) &&
|
||||
!CM.isProfitableToScalarize(SI, VF) &&
|
||||
!CM.isScalarWithPredication(SI, VF);
|
||||
};
|
||||
if (!LoopVectorizationPlanner::getDecisionAndClampRange(willWiden, Range))
|
||||
return nullptr;
|
||||
|
||||
auto *SE = PSE.getSE();
|
||||
bool InvariantCond =
|
||||
SE->isLoopInvariant(PSE.getSCEV(SI->getOperand(0)), OrigLoop);
|
||||
|
@ -6954,14 +6956,7 @@ VPWidenSelectRecipe *VPRecipeBuilder::tryToWidenSelect(Instruction *I,
|
|||
return new VPWidenSelectRecipe(*SI, InvariantCond);
|
||||
}
|
||||
|
||||
VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VFRange &Range) {
|
||||
bool IsPredicated = LoopVectorizationPlanner::getDecisionAndClampRange(
|
||||
[&](unsigned VF) { return CM.isScalarWithPredication(I, VF); }, Range);
|
||||
|
||||
if (IsPredicated)
|
||||
return nullptr;
|
||||
|
||||
assert(!isa<PHINode>(I) && "PHIs should have been handled earlier");
|
||||
VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VPlan &Plan) {
|
||||
auto IsVectorizableOpcode = [](unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Instruction::Add:
|
||||
|
@ -7007,14 +7002,6 @@ VPWidenRecipe *VPRecipeBuilder::tryToWiden(Instruction *I, VFRange &Range) {
|
|||
if (!IsVectorizableOpcode(I->getOpcode()))
|
||||
return nullptr;
|
||||
|
||||
auto willWiden = [&](unsigned VF) -> bool {
|
||||
return !CM.isScalarAfterVectorization(I, VF) &&
|
||||
!CM.isProfitableToScalarize(I, VF);
|
||||
};
|
||||
|
||||
if (!LoopVectorizationPlanner::getDecisionAndClampRange(willWiden, Range))
|
||||
return nullptr;
|
||||
|
||||
// Success: widen this instruction.
|
||||
return new VPWidenRecipe(*I);
|
||||
}
|
||||
|
@ -7095,7 +7082,6 @@ bool VPRecipeBuilder::tryToCreateRecipe(Instruction *Instr, VFRange &Range,
|
|||
// operations, inductions and Phi nodes.
|
||||
if ((Recipe = tryToWidenCall(Instr, Range, *Plan)) ||
|
||||
(Recipe = tryToWidenMemory(Instr, Range, Plan)) ||
|
||||
(Recipe = tryToWidenSelect(Instr, Range)) ||
|
||||
(Recipe = tryToOptimizeInduction(Instr, Range)) ||
|
||||
(Recipe = tryToBlend(Instr, Plan)) ||
|
||||
(isa<PHINode>(Instr) &&
|
||||
|
@ -7105,24 +7091,19 @@ bool VPRecipeBuilder::tryToCreateRecipe(Instruction *Instr, VFRange &Range,
|
|||
return true;
|
||||
}
|
||||
|
||||
// Handle GEP widening.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Instr)) {
|
||||
auto Scalarize = [&](unsigned VF) {
|
||||
return CM.isScalarWithPredication(Instr, VF) ||
|
||||
CM.isScalarAfterVectorization(Instr, VF) ||
|
||||
CM.isProfitableToScalarize(Instr, VF);
|
||||
};
|
||||
if (LoopVectorizationPlanner::getDecisionAndClampRange(Scalarize, Range))
|
||||
return false;
|
||||
VPWidenGEPRecipe *Recipe = new VPWidenGEPRecipe(GEP, OrigLoop);
|
||||
setRecipe(Instr, Recipe);
|
||||
VPBB->appendRecipe(Recipe);
|
||||
return true;
|
||||
}
|
||||
// Calls and memory instructions are widened by the specialized recipes above,
|
||||
// or scalarized.
|
||||
if (isa<CallInst>(Instr) || isa<LoadInst>(Instr) || isa<StoreInst>(Instr))
|
||||
return false;
|
||||
|
||||
// Check if Instr is to be widened by a general VPWidenRecipe, after
|
||||
// having first checked for specific widening recipes.
|
||||
if ((Recipe = tryToWiden(Instr, Range))) {
|
||||
if (!shouldWiden(Instr, Range))
|
||||
return false;
|
||||
|
||||
if ((Recipe = tryToWidenSelect(Instr)) ||
|
||||
(isa<GetElementPtrInst>(Instr) &&
|
||||
(Recipe =
|
||||
new VPWidenGEPRecipe(cast<GetElementPtrInst>(Instr), OrigLoop))) ||
|
||||
(Recipe = tryToWiden(Instr, *Plan))) {
|
||||
setRecipe(Instr, Recipe);
|
||||
VPBB->appendRecipe(Recipe);
|
||||
return true;
|
||||
|
|
|
@ -64,6 +64,11 @@ class VPRecipeBuilder {
|
|||
Ingredient2Recipe[I] = R;
|
||||
}
|
||||
|
||||
/// Check if \p I can be widened at the start of \p Range and possibly
|
||||
/// decrease the range such that the returned value holds for the entire \p
|
||||
/// Range. The function should not be called for memory instructions or calls.
|
||||
bool shouldWiden(Instruction *I, VFRange &Range) const;
|
||||
|
||||
public:
|
||||
/// A helper function that computes the predicate of the block BB, assuming
|
||||
/// that the header block of the loop is set to True. It returns the *entry*
|
||||
|
@ -114,14 +119,15 @@ public:
|
|||
/// ensure same decision from \p Range.Start to \p Range.End.
|
||||
VPWidenCallRecipe *tryToWidenCall(Instruction *I, VFRange &Range,
|
||||
VPlan &Plan);
|
||||
/// Check if \p I is a SelectInst and return a VPWidenSelectRecipe if it is.
|
||||
/// The function should only be called if the cost-model indicates that
|
||||
/// widening should be performed.
|
||||
VPWidenSelectRecipe *tryToWidenSelect(Instruction *I);
|
||||
|
||||
VPWidenSelectRecipe *tryToWidenSelect(Instruction *I, VFRange &Range);
|
||||
|
||||
/// Check if \p I can be widened within the given VF \p Range. If \p I can be
|
||||
/// widened for \p Range.Start, build a new VPWidenRecipe and return it.
|
||||
/// Range.End may be decreased to ensure same decision from \p Range.Start to
|
||||
/// \p Range.End.
|
||||
VPWidenRecipe *tryToWiden(Instruction *I, VFRange &Range);
|
||||
/// Check if \p I has an opcode that can be widened and return a VPWidenRecipe
|
||||
/// if it can. The function should only be called if the cost-model indicates
|
||||
/// that widening should be performed.
|
||||
VPWidenRecipe *tryToWiden(Instruction *I, VPlan &Plan);
|
||||
|
||||
/// Create a replicating region for instruction \p I that requires
|
||||
/// predication. \p PredRecipe is a VPReplicateRecipe holding \p I.
|
||||
|
|
Loading…
Reference in New Issue