[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:
Florian Hahn 2020-04-15 11:41:13 +01:00
parent ff18a6acea
commit 5b4b3e0b6e
2 changed files with 41 additions and 54 deletions

View File

@ -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;

View File

@ -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.