Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Vectorize/VPlanUtils.cpp
213799 views
//===- VPlanUtils.cpp - VPlan-related utilities ---------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "VPlanUtils.h"9#include "VPlanCFG.h"10#include "VPlanPatternMatch.h"11#include "llvm/ADT/TypeSwitch.h"12#include "llvm/Analysis/ScalarEvolutionExpressions.h"1314using namespace llvm;1516bool vputils::onlyFirstLaneUsed(const VPValue *Def) {17return all_of(Def->users(),18[Def](const VPUser *U) { return U->onlyFirstLaneUsed(Def); });19}2021bool vputils::onlyFirstPartUsed(const VPValue *Def) {22return all_of(Def->users(),23[Def](const VPUser *U) { return U->onlyFirstPartUsed(Def); });24}2526VPValue *vputils::getOrCreateVPValueForSCEVExpr(VPlan &Plan, const SCEV *Expr,27ScalarEvolution &SE) {28if (auto *Expanded = Plan.getSCEVExpansion(Expr))29return Expanded;30VPValue *Expanded = nullptr;31if (auto *E = dyn_cast<SCEVConstant>(Expr))32Expanded = Plan.getOrAddLiveIn(E->getValue());33else {34auto *U = dyn_cast<SCEVUnknown>(Expr);35// Skip SCEV expansion if Expr is a SCEVUnknown wrapping a non-instruction36// value. Otherwise the value may be defined in a loop and using it directly37// will break LCSSA form. The SCEV expansion takes care of preserving LCSSA38// form.39if (U && !isa<Instruction>(U->getValue())) {40Expanded = Plan.getOrAddLiveIn(U->getValue());41} else {42Expanded = new VPExpandSCEVRecipe(Expr, SE);43Plan.getEntry()->appendRecipe(Expanded->getDefiningRecipe());44}45}46Plan.addSCEVExpansion(Expr, Expanded);47return Expanded;48}4950bool vputils::isHeaderMask(const VPValue *V, VPlan &Plan) {51if (isa<VPActiveLaneMaskPHIRecipe>(V))52return true;5354auto IsWideCanonicalIV = [](VPValue *A) {55return isa<VPWidenCanonicalIVRecipe>(A) ||56(isa<VPWidenIntOrFpInductionRecipe>(A) &&57cast<VPWidenIntOrFpInductionRecipe>(A)->isCanonical());58};5960VPValue *A, *B;61using namespace VPlanPatternMatch;6263if (match(V, m_ActiveLaneMask(m_VPValue(A), m_VPValue(B))))64return B == Plan.getTripCount() &&65(match(A, m_ScalarIVSteps(m_Specific(Plan.getCanonicalIV()),66m_SpecificInt(1),67m_Specific(&Plan.getVF()))) ||68IsWideCanonicalIV(A));6970return match(V, m_Binary<Instruction::ICmp>(m_VPValue(A), m_VPValue(B))) &&71IsWideCanonicalIV(A) && B == Plan.getOrCreateBackedgeTakenCount();72}7374const SCEV *vputils::getSCEVExprForVPValue(VPValue *V, ScalarEvolution &SE) {75if (V->isLiveIn())76return SE.getSCEV(V->getLiveInIRValue());7778// TODO: Support constructing SCEVs for more recipes as needed.79return TypeSwitch<const VPRecipeBase *, const SCEV *>(V->getDefiningRecipe())80.Case<VPExpandSCEVRecipe>(81[](const VPExpandSCEVRecipe *R) { return R->getSCEV(); })82.Default([&SE](const VPRecipeBase *) { return SE.getCouldNotCompute(); });83}8485bool vputils::isUniformAcrossVFsAndUFs(VPValue *V) {86using namespace VPlanPatternMatch;87// Live-ins are uniform.88if (V->isLiveIn())89return true;9091VPRecipeBase *R = V->getDefiningRecipe();92if (R && V->isDefinedOutsideLoopRegions()) {93if (match(V->getDefiningRecipe(),94m_VPInstruction<VPInstruction::CanonicalIVIncrementForPart>(95m_VPValue())))96return false;97return all_of(R->operands(), isUniformAcrossVFsAndUFs);98}99100auto *CanonicalIV = R->getParent()->getPlan()->getCanonicalIV();101// Canonical IV chain is uniform.102if (V == CanonicalIV || V == CanonicalIV->getBackedgeValue())103return true;104105return TypeSwitch<const VPRecipeBase *, bool>(R)106.Case<VPDerivedIVRecipe>([](const auto *R) { return true; })107.Case<VPReplicateRecipe>([](const auto *R) {108// Loads and stores that are uniform across VF lanes are handled by109// VPReplicateRecipe.IsUniform. They are also uniform across UF parts if110// all their operands are invariant.111// TODO: Further relax the restrictions.112return R->isSingleScalar() &&113(isa<LoadInst, StoreInst>(R->getUnderlyingValue())) &&114all_of(R->operands(), isUniformAcrossVFsAndUFs);115})116.Case<VPInstruction>([](const auto *VPI) {117return VPI->isScalarCast() &&118isUniformAcrossVFsAndUFs(VPI->getOperand(0));119})120.Case<VPWidenCastRecipe>([](const auto *R) {121// A cast is uniform according to its operand.122return isUniformAcrossVFsAndUFs(R->getOperand(0));123})124.Default([](const VPRecipeBase *) { // A value is considered non-uniform125// unless proven otherwise.126return false;127});128}129130VPBasicBlock *vputils::getFirstLoopHeader(VPlan &Plan, VPDominatorTree &VPDT) {131auto DepthFirst = vp_depth_first_shallow(Plan.getEntry());132auto I = find_if(DepthFirst, [&VPDT](VPBlockBase *VPB) {133return VPBlockUtils::isHeader(VPB, VPDT);134});135return I == DepthFirst.end() ? nullptr : cast<VPBasicBlock>(*I);136}137138139