171ede8d8SRamkumar Ramachandra //===- VPlanUtils.cpp - VPlan-related utilities ---------------------------===// 271ede8d8SRamkumar Ramachandra // 371ede8d8SRamkumar Ramachandra // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 471ede8d8SRamkumar Ramachandra // See https://llvm.org/LICENSE.txt for license information. 571ede8d8SRamkumar Ramachandra // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 671ede8d8SRamkumar Ramachandra // 771ede8d8SRamkumar Ramachandra //===----------------------------------------------------------------------===// 871ede8d8SRamkumar Ramachandra 971ede8d8SRamkumar Ramachandra #include "VPlanUtils.h" 1071ede8d8SRamkumar Ramachandra #include "VPlanPatternMatch.h" 110d736e29SFlorian Hahn #include "llvm/ADT/TypeSwitch.h" 1271ede8d8SRamkumar Ramachandra #include "llvm/Analysis/ScalarEvolutionExpressions.h" 1371ede8d8SRamkumar Ramachandra 1471ede8d8SRamkumar Ramachandra using namespace llvm; 1571ede8d8SRamkumar Ramachandra 1671ede8d8SRamkumar Ramachandra bool vputils::onlyFirstLaneUsed(const VPValue *Def) { 1771ede8d8SRamkumar Ramachandra return all_of(Def->users(), 1871ede8d8SRamkumar Ramachandra [Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); }); 1971ede8d8SRamkumar Ramachandra } 2071ede8d8SRamkumar Ramachandra 2171ede8d8SRamkumar Ramachandra bool vputils::onlyFirstPartUsed(const VPValue *Def) { 2271ede8d8SRamkumar Ramachandra return all_of(Def->users(), 2371ede8d8SRamkumar Ramachandra [Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); }); 2471ede8d8SRamkumar Ramachandra } 2571ede8d8SRamkumar Ramachandra 2671ede8d8SRamkumar Ramachandra VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr, 2771ede8d8SRamkumar Ramachandra ScalarEvolution &SE) { 2871ede8d8SRamkumar Ramachandra if (auto *Expanded = Plan.getSCEVExpansion(Expr)) 2971ede8d8SRamkumar Ramachandra return Expanded; 3071ede8d8SRamkumar Ramachandra VPValue *Expanded = nullptr; 3171ede8d8SRamkumar Ramachandra if (auto *E = dyn_cast<SCEVConstant>(Expr)) 3271ede8d8SRamkumar Ramachandra Expanded = Plan.getOrAddLiveIn(E->getValue()); 3371ede8d8SRamkumar Ramachandra else if (auto *E = dyn_cast<SCEVUnknown>(Expr)) 3471ede8d8SRamkumar Ramachandra Expanded = Plan.getOrAddLiveIn(E->getValue()); 3571ede8d8SRamkumar Ramachandra else { 3671ede8d8SRamkumar Ramachandra Expanded = new VPExpandSCEVRecipe(Expr, SE); 37*6c8f41d3SFlorian Hahn Plan.getEntry()->appendRecipe(Expanded->getDefiningRecipe()); 3871ede8d8SRamkumar Ramachandra } 3971ede8d8SRamkumar Ramachandra Plan.addSCEVExpansion(Expr, Expanded); 4071ede8d8SRamkumar Ramachandra return Expanded; 4171ede8d8SRamkumar Ramachandra } 4271ede8d8SRamkumar Ramachandra 4371ede8d8SRamkumar Ramachandra bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) { 4471ede8d8SRamkumar Ramachandra if (isa<VPActiveLaneMaskPHIRecipe>(V)) 4571ede8d8SRamkumar Ramachandra return true; 4671ede8d8SRamkumar Ramachandra 4771ede8d8SRamkumar Ramachandra auto IsWideCanonicalIV = [](VPValue *A) { 4871ede8d8SRamkumar Ramachandra return isa<VPWidenCanonicalIVRecipe>(A) || 4971ede8d8SRamkumar Ramachandra (isa<VPWidenIntOrFpInductionRecipe>(A) && 5071ede8d8SRamkumar Ramachandra cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical()); 5171ede8d8SRamkumar Ramachandra }; 5271ede8d8SRamkumar Ramachandra 5371ede8d8SRamkumar Ramachandra VPValue *A, *B; 5471ede8d8SRamkumar Ramachandra using namespace VPlanPatternMatch; 5571ede8d8SRamkumar Ramachandra 5671ede8d8SRamkumar Ramachandra if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B)))) 5771ede8d8SRamkumar Ramachandra return B == Plan.getTripCount() && 5871ede8d8SRamkumar Ramachandra (match(A, m_ScalarIVSteps(m_CanonicalIV(), m_SpecificInt(1))) || 5971ede8d8SRamkumar Ramachandra IsWideCanonicalIV(A)); 6071ede8d8SRamkumar Ramachandra 6171ede8d8SRamkumar Ramachandra return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) && 6271ede8d8SRamkumar Ramachandra IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount(); 6371ede8d8SRamkumar Ramachandra } 640d736e29SFlorian Hahn 650d736e29SFlorian Hahn const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) { 660d736e29SFlorian Hahn if (V->isLiveIn()) 670d736e29SFlorian Hahn return SE.getSCEV(V->getLiveInIRValue()); 680d736e29SFlorian Hahn 690d736e29SFlorian Hahn // TODO: Support constructing SCEVs for more recipes as needed. 700d736e29SFlorian Hahn return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe()) 710d736e29SFlorian Hahn .Case<VPExpandSCEVRecipe>( 720d736e29SFlorian Hahn [](const VPExpandSCEVRecipe *R) { return R->getSCEV(); }) 730d736e29SFlorian Hahn .Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); }); 740d736e29SFlorian Hahn } 758ec40675SFlorian Hahn 768ec40675SFlorian Hahn bool vputils::isUniformAcrossVFsAndUFs(VPValue *V) { 778ec40675SFlorian Hahn using namespace VPlanPatternMatch; 788ec40675SFlorian Hahn // Live-ins are uniform. 798ec40675SFlorian Hahn if (V->isLiveIn()) 808ec40675SFlorian Hahn return true; 818ec40675SFlorian Hahn 828ec40675SFlorian Hahn VPRecipeBase *R = V->getDefiningRecipe(); 838ec40675SFlorian Hahn if (R && V->isDefinedOutsideLoopRegions()) { 848ec40675SFlorian Hahn if (match(V->getDefiningRecipe(), 858ec40675SFlorian Hahn m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>( 868ec40675SFlorian Hahn m_VPValue()))) 878ec40675SFlorian Hahn return false; 888ec40675SFlorian Hahn return all_of(R->operands(), 898ec40675SFlorian Hahn [](VPValue *Op) { return isUniformAcrossVFsAndUFs(Op); }); 908ec40675SFlorian Hahn } 918ec40675SFlorian Hahn 928ec40675SFlorian Hahn auto *CanonicalIV = R->getParent()->getPlan()->getCanonicalIV(); 938ec40675SFlorian Hahn // Canonical IV chain is uniform. 948ec40675SFlorian Hahn if (V == CanonicalIV || V == CanonicalIV->getBackedgeValue()) 958ec40675SFlorian Hahn return true; 968ec40675SFlorian Hahn 978ec40675SFlorian Hahn return TypeSwitch<const VPRecipeBase *, bool>(R) 988ec40675SFlorian Hahn .Case<VPDerivedIVRecipe>([](const auto *R) { return true; }) 998ec40675SFlorian Hahn .Case<VPReplicateRecipe>([](const auto *R) { 1008ec40675SFlorian Hahn // Loads and stores that are uniform across VF lanes are handled by 1018ec40675SFlorian Hahn // VPReplicateRecipe.IsUniform. They are also uniform across UF parts if 1028ec40675SFlorian Hahn // all their operands are invariant. 1038ec40675SFlorian Hahn // TODO: Further relax the restrictions. 1048ec40675SFlorian Hahn return R->isUniform() && 1058ec40675SFlorian Hahn (isa<LoadInst, StoreInst>(R->getUnderlyingValue())) && 1068ec40675SFlorian Hahn all_of(R->operands(), 1078ec40675SFlorian Hahn [](VPValue *Op) { return isUniformAcrossVFsAndUFs(Op); }); 1088ec40675SFlorian Hahn }) 1098ec40675SFlorian Hahn .Case<VPScalarCastRecipe, VPWidenCastRecipe>([](const auto *R) { 1108ec40675SFlorian Hahn // A cast is uniform according to its operand. 1118ec40675SFlorian Hahn return isUniformAcrossVFsAndUFs(R->getOperand(0)); 1128ec40675SFlorian Hahn }) 1138ec40675SFlorian Hahn .Default([](const VPRecipeBase *) { // A value is considered non-uniform 1148ec40675SFlorian Hahn // unless proven otherwise. 1158ec40675SFlorian Hahn return false; 1168ec40675SFlorian Hahn }); 1178ec40675SFlorian Hahn } 118