| 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" |
| 13 | #include "llvm/Analysis/ScalarEvolutionExpressions.h" |
| 14 | |
| 15 | using namespace llvm; |
| 16 | |
| 17 | bool vputils::onlyFirstLaneUsed(const VPValue *Def) { |
| 18 | return all_of(Range: Def->users(), |
| 19 | P: [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Op: Def); }); |
| 20 | } |
| 21 | |
| 22 | bool vputils::onlyFirstPartUsed(const VPValue *Def) { |
| 23 | return all_of(Range: Def->users(), |
| 24 | P: [Def](const VPUser *U) { return U->onlyFirstPartUsed(Op: Def); }); |
| 25 | } |
| 26 | |
| 27 | VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, |
| 28 | ScalarEvolution &SE) { |
| 29 | if (auto *Expanded = Plan.getSCEVExpansion(S: Expr)) |
| 30 | return Expanded; |
| 31 | VPValue *Expanded = nullptr; |
| 32 | if (auto *E = dyn_cast<SCEVConstant>(Val: Expr)) |
| 33 | Expanded = Plan.getOrAddLiveIn(V: E->getValue()); |
| 34 | else { |
| 35 | auto *U = dyn_cast<SCEVUnknown>(Val: Expr); |
| 36 | // Skip SCEV expansion if Expr is a SCEVUnknown wrapping a non-instruction |
| 37 | // value. Otherwise the value may be defined in a loop and using it directly |
| 38 | // will break LCSSA form. The SCEV expansion takes care of preserving LCSSA |
| 39 | // form. |
| 40 | if (U && !isa<Instruction>(Val: U->getValue())) { |
| 41 | Expanded = Plan.getOrAddLiveIn(V: U->getValue()); |
| 42 | } else { |
| 43 | Expanded = new VPExpandSCEVRecipe(Expr, SE); |
| 44 | Plan.getEntry()->appendRecipe(Recipe: Expanded->getDefiningRecipe()); |
| 45 | } |
| 46 | } |
| 47 | Plan.addSCEVExpansion(S: Expr, V: Expanded); |
| 48 | return Expanded; |
| 49 | } |
| 50 | |
| 51 | bool vputils::(const VPValue *V, VPlan &Plan) { |
| 52 | if (isa<VPActiveLaneMaskPHIRecipe>(Val: V)) |
| 53 | return true; |
| 54 | |
| 55 | auto IsWideCanonicalIV = [](VPValue *A) { |
| 56 | return isa<VPWidenCanonicalIVRecipe>(Val: A) || |
| 57 | (isa<VPWidenIntOrFpInductionRecipe>(Val: A) && |
| 58 | cast<VPWidenIntOrFpInductionRecipe>(Val: A)->isCanonical()); |
| 59 | }; |
| 60 | |
| 61 | VPValue *A, *B; |
| 62 | using namespace VPlanPatternMatch; |
| 63 | |
| 64 | if (match(V, P: m_ActiveLaneMask(Op0: m_VPValue(V&: A), Op1: m_VPValue(V&: B)))) |
| 65 | return B == Plan.getTripCount() && |
| 66 | (match(V: A, P: m_ScalarIVSteps(Op0: m_Specific(VPV: Plan.getCanonicalIV()), |
| 67 | Op1: m_SpecificInt(V: 1), |
| 68 | Op2: m_Specific(VPV: &Plan.getVF()))) || |
| 69 | IsWideCanonicalIV(A)); |
| 70 | |
| 71 | return match(V, P: m_Binary<Instruction::ICmp>(Op0: m_VPValue(V&: A), Op1: m_VPValue(V&: B))) && |
| 72 | IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount(); |
| 73 | } |
| 74 | |
| 75 | const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) { |
| 76 | if (V->isLiveIn()) |
| 77 | return SE.getSCEV(V: V->getLiveInIRValue()); |
| 78 | |
| 79 | // TODO: Support constructing SCEVs for more recipes as needed. |
| 80 | return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe()) |
| 81 | .Case<VPExpandSCEVRecipe>( |
| 82 | caseFn: [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); }) |
| 83 | .Default(defaultFn: [&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); }); |
| 84 | } |
| 85 | |
| 86 | bool vputils::isUniformAcrossVFsAndUFs(VPValue *V) { |
| 87 | using namespace VPlanPatternMatch; |
| 88 | // Live-ins are uniform. |
| 89 | if (V->isLiveIn()) |
| 90 | return true; |
| 91 | |
| 92 | VPRecipeBase *R = V->getDefiningRecipe(); |
| 93 | if (R && V->isDefinedOutsideLoopRegions()) { |
| 94 | if (match(V: V->getDefiningRecipe(), |
| 95 | P: m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>( |
| 96 | Op0: m_VPValue()))) |
| 97 | return false; |
| 98 | return all_of(Range: R->operands(), P: isUniformAcrossVFsAndUFs); |
| 99 | } |
| 100 | |
| 101 | auto *CanonicalIV = R->getParent()->getPlan()->getCanonicalIV(); |
| 102 | // Canonical IV chain is uniform. |
| 103 | if (V == CanonicalIV || V == CanonicalIV->getBackedgeValue()) |
| 104 | return true; |
| 105 | |
| 106 | return TypeSwitch<const VPRecipeBase *, bool>(R) |
| 107 | .Case<VPDerivedIVRecipe>(caseFn: [](const auto *R) { return true; }) |
| 108 | .Case<VPReplicateRecipe>(caseFn: [](const auto *R) { |
| 109 | // Loads and stores that are uniform across VF lanes are handled by |
| 110 | // VPReplicateRecipe.IsUniform. They are also uniform across UF parts if |
| 111 | // all their operands are invariant. |
| 112 | // TODO: Further relax the restrictions. |
| 113 | return R->isSingleScalar() && |
| 114 | (isa<LoadInst, StoreInst>(R->getUnderlyingValue())) && |
| 115 | all_of(R->operands(), isUniformAcrossVFsAndUFs); |
| 116 | }) |
| 117 | .Case<VPInstruction>(caseFn: [](const auto *VPI) { |
| 118 | return VPI->isScalarCast() && |
| 119 | isUniformAcrossVFsAndUFs(VPI->getOperand(0)); |
| 120 | }) |
| 121 | .Case<VPWidenCastRecipe>(caseFn: [](const auto *R) { |
| 122 | // A cast is uniform according to its operand. |
| 123 | return isUniformAcrossVFsAndUFs(R->getOperand(0)); |
| 124 | }) |
| 125 | .Default(defaultFn: [](const VPRecipeBase *) { // A value is considered non-uniform |
| 126 | // unless proven otherwise. |
| 127 | return false; |
| 128 | }); |
| 129 | } |
| 130 | |
| 131 | VPBasicBlock *vputils::(VPlan &Plan, VPDominatorTree &VPDT) { |
| 132 | auto DepthFirst = vp_depth_first_shallow(G: Plan.getEntry()); |
| 133 | auto I = find_if(Range&: DepthFirst, P: [&VPDT](VPBlockBase *VPB) { |
| 134 | return VPBlockUtils::isHeader(VPB, VPDT); |
| 135 | }); |
| 136 | return I == DepthFirst.end() ? nullptr : cast<VPBasicBlock>(Val: *I); |
| 137 | } |
| 138 | |