LLVM 22.0.0git
VPlanUtils.cpp
Go to the documentation of this file.
1//===- VPlanUtils.cpp - VPlan-related utilities ---------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "VPlanUtils.h"
10#include "VPlanCFG.h"
11#include "VPlanPatternMatch.h"
12#include "llvm/ADT/TypeSwitch.h"
14
15using namespace llvm;
16
18 return all_of(Def->users(),
19 [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); });
20}
21
23 return all_of(Def->users(),
24 [Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); });
25}
26
28 return all_of(Def->users(),
29 [Def](const VPUser *U) { return U->usesScalars(Def); });
30}
31
33 if (auto *Expanded = Plan.getSCEVExpansion(Expr))
34 return Expanded;
35 VPValue *Expanded = nullptr;
36 if (auto *E = dyn_cast<SCEVConstant>(Expr))
37 Expanded = Plan.getOrAddLiveIn(E->getValue());
38 else {
39 auto *U = dyn_cast<SCEVUnknown>(Expr);
40 // Skip SCEV expansion if Expr is a SCEVUnknown wrapping a non-instruction
41 // value. Otherwise the value may be defined in a loop and using it directly
42 // will break LCSSA form. The SCEV expansion takes care of preserving LCSSA
43 // form.
44 if (U && !isa<Instruction>(U->getValue())) {
45 Expanded = Plan.getOrAddLiveIn(U->getValue());
46 } else {
47 Expanded = new VPExpandSCEVRecipe(Expr);
48 Plan.getEntry()->appendRecipe(Expanded->getDefiningRecipe());
49 }
50 }
51 Plan.addSCEVExpansion(Expr, Expanded);
52 return Expanded;
53}
54
55bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) {
56 if (isa<VPActiveLaneMaskPHIRecipe>(V))
57 return true;
58
59 auto IsWideCanonicalIV = [](VPValue *A) {
60 return isa<VPWidenCanonicalIVRecipe>(A) ||
61 (isa<VPWidenIntOrFpInductionRecipe>(A) &&
62 cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical());
63 };
64
65 VPValue *A, *B;
66 using namespace VPlanPatternMatch;
67
68 if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B))))
69 return B == Plan.getTripCount() &&
70 (match(A, m_ScalarIVSteps(m_Specific(Plan.getCanonicalIV()),
72 m_Specific(&Plan.getVF()))) ||
73 IsWideCanonicalIV(A));
74
75 return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) &&
76 IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount();
77}
78
80 if (V->isLiveIn()) {
81 if (Value *LiveIn = V->getLiveInIRValue())
82 return SE.getSCEV(LiveIn);
83 return SE.getCouldNotCompute();
84 }
85
86 // TODO: Support constructing SCEVs for more recipes as needed.
87 return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe())
89 [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
90 .Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
91}
92
94 using namespace VPlanPatternMatch;
95 // Live-ins are uniform.
96 if (V->isLiveIn())
97 return true;
98
99 VPRecipeBase *R = V->getDefiningRecipe();
100 if (R && V->isDefinedOutsideLoopRegions()) {
101 if (match(V->getDefiningRecipe(),
102 m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>(
103 m_VPValue())))
104 return false;
105 return all_of(R->operands(), isUniformAcrossVFsAndUFs);
106 }
107
108 auto *CanonicalIV = R->getParent()->getPlan()->getCanonicalIV();
109 // Canonical IV chain is uniform.
110 if (V == CanonicalIV || V == CanonicalIV->getBackedgeValue())
111 return true;
112
114 .Case<VPDerivedIVRecipe>([](const auto *R) { return true; })
115 .Case<VPReplicateRecipe>([](const auto *R) {
116 // Loads and stores that are uniform across VF lanes are handled by
117 // VPReplicateRecipe.IsUniform. They are also uniform across UF parts if
118 // all their operands are invariant.
119 // TODO: Further relax the restrictions.
120 return R->isSingleScalar() &&
121 (isa<LoadInst, StoreInst>(R->getUnderlyingValue())) &&
122 all_of(R->operands(), isUniformAcrossVFsAndUFs);
123 })
124 .Case<VPInstruction>([](const auto *VPI) {
125 return VPI->isScalarCast() &&
126 isUniformAcrossVFsAndUFs(VPI->getOperand(0));
127 })
128 .Case<VPWidenCastRecipe>([](const auto *R) {
129 // A cast is uniform according to its operand.
130 return isUniformAcrossVFsAndUFs(R->getOperand(0));
131 })
132 .Default([](const VPRecipeBase *) { // A value is considered non-uniform
133 // unless proven otherwise.
134 return false;
135 });
136}
137
139 auto DepthFirst = vp_depth_first_shallow(Plan.getEntry());
140 auto I = find_if(DepthFirst, [&VPDT](VPBlockBase *VPB) {
141 return VPBlockUtils::isHeader(VPB, VPDT);
142 });
143 return I == DepthFirst.end() ? nullptr : cast<VPBasicBlock>(*I);
144}
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
@ Default
Definition: DwarfDebug.cpp:86
#define I(x, y, z)
Definition: MD5.cpp:58
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This class represents an analyzed expression in the program.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
LLVM_ABI const SCEV * getCouldNotCompute()
This class implements a switch-like dispatch statement for a value of 'T' using dyn_cast functionalit...
Definition: TypeSwitch.h:87
TypeSwitch< T, ResultT > & Case(CallableT &&caseFn)
Add a case on the given type.
Definition: TypeSwitch.h:96
VPBasicBlock serves as the leaf of the Hierarchical Control-Flow Graph.
Definition: VPlan.h:3639
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition: VPlan.h:3714
VPBlockBase is the building block of the Hierarchical Control-Flow Graph.
Definition: VPlan.h:81
static bool isHeader(const VPBlockBase *VPB, const VPDominatorTree &VPDT)
Returns true if VPB is a loop header, based on regions or VPDT in their absence.
Definition: VPlan.cpp:210
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition: VPlan.h:3460
Template specialization of the standard LLVM dominator tree utility for VPBlockBases.
Recipe to expand a SCEV expression.
Definition: VPlan.h:3258
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition: VPlan.h:391
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition: VPlanValue.h:197
VPRecipeBase * getDefiningRecipe()
Returns the recipe defining this VPValue or nullptr if it is not defined by a recipe,...
Definition: VPlan.cpp:125
VPlan models a candidate for vectorization, encoding various decisions take to produce efficient outp...
Definition: VPlan.h:3930
VPBasicBlock * getEntry()
Definition: VPlan.h:4029
VPValue & getVF()
Returns the VF of the vector loop region.
Definition: VPlan.h:4122
VPValue * getTripCount() const
The trip count of the original loop.
Definition: VPlan.h:4091
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
Definition: VPlan.h:4112
void addSCEVExpansion(const SCEV *S, VPValue *V)
Definition: VPlan.h:4248
VPValue * getOrAddLiveIn(Value *V)
Gets the live-in VPValue for V or adds a new live-in (if none exists yet) for V.
Definition: VPlan.h:4181
VPCanonicalIVPHIRecipe * getCanonicalIV()
Returns the canonical induction recipe of the vector loop.
Definition: VPlan.h:4235
VPValue * getSCEVExpansion(const SCEV *S) const
Definition: VPlan.h:4244
LLVM Value Representation.
Definition: Value.h:75
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:49
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
Definition: PatternMatch.h:962
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
Definition: VPlanUtils.cpp:93
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr)
Get or create a VPValue that corresponds to the expansion of Expr.
Definition: VPlanUtils.cpp:32
VPBasicBlock * getFirstLoopHeader(VPlan &Plan, VPDominatorTree &VPDT)
Returns the header block of the first, top-level loop, or null if none exist.
Definition: VPlanUtils.cpp:138
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
Definition: VPlanUtils.cpp:22
const SCEV * getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE)
Return the SCEV expression for V.
Definition: VPlanUtils.cpp:79
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
Definition: VPlanUtils.cpp:17
bool isHeaderMask(const VPValue *V, VPlan &Plan)
Return true if V is a header mask in Plan.
Definition: VPlanUtils.cpp:55
bool onlyScalarValuesUsed(const VPValue *Def)
Returns true if only scalar values of Def are used by all users.
Definition: VPlanUtils.cpp:27
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1744
iterator_range< df_iterator< VPBlockShallowTraversalWrapper< VPBlockBase * > > > vp_depth_first_shallow(VPBlockBase *G)
Returns an iterator range to traverse the graph starting at G in depth-first order.
Definition: VPlanCFG.h:216
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1777