xref: /llvm-project/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp (revision 0d736e296c2feed7709e002d5972ed60844b6b56)
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"
12 #include "llvm/Analysis/ScalarEvolutionExpressions.h"
13 
14 using namespace llvm;
15 
16 bool vputils::onlyFirstLaneUsed(const VPValue *Def) {
17   return all_of(Def->users(),
18                 [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); });
19 }
20 
21 bool vputils::onlyFirstPartUsed(const VPValue *Def) {
22   return all_of(Def->users(),
23                 [Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); });
24 }
25 
26 VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,
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 if (auto *E = dyn_cast<SCEVUnknown>(Expr))
34     Expanded = Plan.getOrAddLiveIn(E->getValue());
35   else {
36     Expanded = new VPExpandSCEVRecipe(Expr, SE);
37     Plan.getPreheader()->appendRecipe(Expanded->getDefiningRecipe());
38   }
39   Plan.addSCEVExpansion(Expr, Expanded);
40   return Expanded;
41 }
42 
43 bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) {
44   if (isa<VPActiveLaneMaskPHIRecipe>(V))
45     return true;
46 
47   auto IsWideCanonicalIV = [](VPValue *A) {
48     return isa<VPWidenCanonicalIVRecipe>(A) ||
49            (isa<VPWidenIntOrFpInductionRecipe>(A) &&
50             cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical());
51   };
52 
53   VPValue *A, *B;
54   using namespace VPlanPatternMatch;
55 
56   if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B))))
57     return B == Plan.getTripCount() &&
58            (match(A, m_ScalarIVSteps(m_CanonicalIV(), m_SpecificInt(1))) ||
59             IsWideCanonicalIV(A));
60 
61   return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) &&
62          IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount();
63 }
64 
65 const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) {
66   if (V->isLiveIn())
67     return SE.getSCEV(V->getLiveInIRValue());
68 
69   // TODO: Support constructing SCEVs for more recipes as needed.
70   return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe())
71       .Case<VPExpandSCEVRecipe>(
72           [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })
73       .Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });
74 }
75