LLVM 21.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 "VPlanPatternMatch.h"
11#include "llvm/ADT/TypeSwitch.h"
13
14using namespace llvm;
15
17 return all_of(Def->users(),
18 [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); });
19}
20
22 return all_of(Def->users(),
23 [Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); });
24}
25
27 ScalarEvolution &SE) {
28 if (auto *Expanded = Plan.getSCEVExpansion(Expr))
29 return Expanded;
30 VPValue *Expanded = nullptr;
31 if (auto *E = dyn_cast<SCEVConstant>(Expr))
32 Expanded = Plan.getOrAddLiveIn(E->getValue());
33 else {
34 auto *U = dyn_cast<SCEVUnknown>(Expr);
35 // Skip SCEV expansion if Expr is a SCEVUnknown wrapping a non-instruction
36 // value. Otherwise the value may be defined in a loop and using it directly
37 // will break LCSSA form. The SCEV expansion takes care of preserving LCSSA
38 // form.
39 if (U && !isa<Instruction>(U->getValue())) {
40 Expanded = Plan.getOrAddLiveIn(U->getValue());
41 } else {
42 Expanded = new VPExpandSCEVRecipe(Expr, SE);
43 Plan.getEntry()->appendRecipe(Expanded->getDefiningRecipe());
44 }
45 }
46 Plan.addSCEVExpansion(Expr, Expanded);
47 return Expanded;
48}
49
50bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) {
51 if (isa<VPActiveLaneMaskPHIRecipe>(V))
52 return true;
53
54 auto IsWideCanonicalIV = [](VPValue *A) {
55 return isa<VPWidenCanonicalIVRecipe>(A) ||
56 (isa<VPWidenIntOrFpInductionRecipe>(A) &&
57 cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical());
58 };
59
60 VPValue *A, *B;
61 using namespace VPlanPatternMatch;
62
63 if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B))))
64 return B == Plan.getTripCount() &&
65 (match(A, m_ScalarIVSteps(m_CanonicalIV(), m_SpecificInt(1))) ||
66 IsWideCanonicalIV(A));
67
68 return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) &&
69 IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount();
70}
71
73 if (V->isLiveIn())
74 return SE.getSCEV(V->getLiveInIRValue());
75
76 // TODO: Support constructing SCEVs for more recipes as needed.
77 return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe())
79 [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
80 .Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
81}
82
84 using namespace VPlanPatternMatch;
85 // Live-ins are uniform.
86 if (V->isLiveIn())
87 return true;
88
89 VPRecipeBase *R = V->getDefiningRecipe();
90 if (R && V->isDefinedOutsideLoopRegions()) {
91 if (match(V->getDefiningRecipe(),
92 m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>(
93 m_VPValue())))
94 return false;
95 return all_of(R->operands(),
96 [](VPValue *Op) { return isUniformAcrossVFsAndUFs(Op); });
97 }
98
99 auto *CanonicalIV = R->getParent()->getPlan()->getCanonicalIV();
100 // Canonical IV chain is uniform.
101 if (V == CanonicalIV || V == CanonicalIV->getBackedgeValue())
102 return true;
103
105 .Case<VPDerivedIVRecipe>([](const auto *R) { return true; })
106 .Case<VPReplicateRecipe>([](const auto *R) {
107 // Loads and stores that are uniform across VF lanes are handled by
108 // VPReplicateRecipe.IsUniform. They are also uniform across UF parts if
109 // all their operands are invariant.
110 // TODO: Further relax the restrictions.
111 return R->isUniform() &&
112 (isa<LoadInst, StoreInst>(R->getUnderlyingValue())) &&
113 all_of(R->operands(),
114 [](VPValue *Op) { return isUniformAcrossVFsAndUFs(Op); });
115 })
116 .Case<VPScalarCastRecipe, VPWidenCastRecipe>([](const auto *R) {
117 // A cast is uniform according to its operand.
118 return isUniformAcrossVFsAndUFs(R->getOperand(0));
119 })
120 .Default([](const VPRecipeBase *) { // A value is considered non-uniform
121 // unless proven otherwise.
122 return false;
123 });
124}
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:87
This file implements the TypeSwitch template, which mimics a switch() statement whose cases are type ...
This class represents an Operation in the Expression.
This class represents an analyzed expression in the program.
The main scalar evolution driver.
const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
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
void appendRecipe(VPRecipeBase *Recipe)
Augment the existing recipes of a VPBasicBlock with an additional Recipe as the last recipe.
Definition: VPlan.h:3277
A recipe for converting the input value IV value to the corresponding value of an IV with different s...
Definition: VPlan.h:3076
Recipe to expand a SCEV expression.
Definition: VPlan.h:2860
VPRecipeBase is a base class modeling a sequence of one or more output IR instructions.
Definition: VPlan.h:366
This class augments VPValue with operands which provide the inverse def-use edges from VPValue's user...
Definition: VPlanValue.h:206
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:3478
VPBasicBlock * getEntry()
Definition: VPlan.h:3591
VPValue * getTripCount() const
The trip count of the original loop.
Definition: VPlan.h:3635
VPValue * getOrCreateBackedgeTakenCount()
The backedge taken count of the original loop.
Definition: VPlan.h:3649
void addSCEVExpansion(const SCEV *S, VPValue *V)
Definition: VPlan.h:3755
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:3710
VPValue * getSCEVExpansion(const SCEV *S) const
Definition: VPlan.h:3751
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
Definition: PatternMatch.h:982
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:49
VPValue * getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, ScalarEvolution &SE)
Get or create a VPValue that corresponds to the expansion of Expr.
Definition: VPlanUtils.cpp:26
bool isUniformAcrossVFsAndUFs(VPValue *V)
Checks if V is uniform across all VF lanes and UF parts.
Definition: VPlanUtils.cpp:83
bool onlyFirstPartUsed(const VPValue *Def)
Returns true if only the first part of Def is used.
Definition: VPlanUtils.cpp:21
const SCEV * getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE)
Return the SCEV expression for V.
Definition: VPlanUtils.cpp:72
bool onlyFirstLaneUsed(const VPValue *Def)
Returns true if only the first lane of Def is used.
Definition: VPlanUtils.cpp:16
bool isHeaderMask(const VPValue *V, VPlan &Plan)
Return true if V is a header mask in Plan.
Definition: VPlanUtils.cpp:50
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:1739
DWARFExpression::Operation Op