11db4dbbaSSimon Moll //===----- CodeGen/ExpandVectorPredication.cpp - Expand VP intrinsics -----===// 21db4dbbaSSimon Moll // 31db4dbbaSSimon Moll // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 41db4dbbaSSimon Moll // See https://llvm.org/LICENSE.txt for license information. 51db4dbbaSSimon Moll // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 61db4dbbaSSimon Moll // 71db4dbbaSSimon Moll //===----------------------------------------------------------------------===// 81db4dbbaSSimon Moll // 91db4dbbaSSimon Moll // This pass implements IR expansion for vector predication intrinsics, allowing 101db4dbbaSSimon Moll // targets to enable vector predication until just before codegen. 111db4dbbaSSimon Moll // 121db4dbbaSSimon Moll //===----------------------------------------------------------------------===// 131db4dbbaSSimon Moll 141db4dbbaSSimon Moll #include "llvm/CodeGen/ExpandVectorPredication.h" 151db4dbbaSSimon Moll #include "llvm/ADT/Statistic.h" 161db4dbbaSSimon Moll #include "llvm/Analysis/TargetTransformInfo.h" 171db4dbbaSSimon Moll #include "llvm/Analysis/ValueTracking.h" 18f390781cSLorenzo Albano #include "llvm/Analysis/VectorUtils.h" 191db4dbbaSSimon Moll #include "llvm/CodeGen/Passes.h" 201db4dbbaSSimon Moll #include "llvm/IR/Constants.h" 211db4dbbaSSimon Moll #include "llvm/IR/Function.h" 221db4dbbaSSimon Moll #include "llvm/IR/IRBuilder.h" 231db4dbbaSSimon Moll #include "llvm/IR/InstIterator.h" 241db4dbbaSSimon Moll #include "llvm/IR/Instructions.h" 251db4dbbaSSimon Moll #include "llvm/IR/IntrinsicInst.h" 261db4dbbaSSimon Moll #include "llvm/IR/Intrinsics.h" 271db4dbbaSSimon Moll #include "llvm/InitializePasses.h" 281db4dbbaSSimon Moll #include "llvm/Pass.h" 291db4dbbaSSimon Moll #include "llvm/Support/CommandLine.h" 301db4dbbaSSimon Moll #include "llvm/Support/Compiler.h" 311db4dbbaSSimon Moll #include "llvm/Support/Debug.h" 321db4dbbaSSimon Moll 331db4dbbaSSimon Moll using namespace llvm; 341db4dbbaSSimon Moll 351db4dbbaSSimon Moll using VPLegalization = TargetTransformInfo::VPLegalization; 361db4dbbaSSimon Moll using VPTransform = TargetTransformInfo::VPLegalization::VPTransform; 371db4dbbaSSimon Moll 381db4dbbaSSimon Moll // Keep this in sync with TargetTransformInfo::VPLegalization. 391db4dbbaSSimon Moll #define VPINTERNAL_VPLEGAL_CASES \ 401db4dbbaSSimon Moll VPINTERNAL_CASE(Legal) \ 411db4dbbaSSimon Moll VPINTERNAL_CASE(Discard) \ 421db4dbbaSSimon Moll VPINTERNAL_CASE(Convert) 431db4dbbaSSimon Moll 441db4dbbaSSimon Moll #define VPINTERNAL_CASE(X) "|" #X 451db4dbbaSSimon Moll 461db4dbbaSSimon Moll // Override options. 471db4dbbaSSimon Moll static cl::opt<std::string> EVLTransformOverride( 481db4dbbaSSimon Moll "expandvp-override-evl-transform", cl::init(""), cl::Hidden, 491db4dbbaSSimon Moll cl::desc("Options: <empty>" VPINTERNAL_VPLEGAL_CASES 501db4dbbaSSimon Moll ". If non-empty, ignore " 511db4dbbaSSimon Moll "TargetTransformInfo and " 521db4dbbaSSimon Moll "always use this transformation for the %evl parameter (Used in " 531db4dbbaSSimon Moll "testing).")); 541db4dbbaSSimon Moll 551db4dbbaSSimon Moll static cl::opt<std::string> MaskTransformOverride( 561db4dbbaSSimon Moll "expandvp-override-mask-transform", cl::init(""), cl::Hidden, 571db4dbbaSSimon Moll cl::desc("Options: <empty>" VPINTERNAL_VPLEGAL_CASES 581db4dbbaSSimon Moll ". If non-empty, Ignore " 591db4dbbaSSimon Moll "TargetTransformInfo and " 601db4dbbaSSimon Moll "always use this transformation for the %mask parameter (Used in " 611db4dbbaSSimon Moll "testing).")); 621db4dbbaSSimon Moll 631db4dbbaSSimon Moll #undef VPINTERNAL_CASE 641db4dbbaSSimon Moll #define VPINTERNAL_CASE(X) .Case(#X, VPLegalization::X) 651db4dbbaSSimon Moll 661db4dbbaSSimon Moll static VPTransform parseOverrideOption(const std::string &TextOpt) { 671db4dbbaSSimon Moll return StringSwitch<VPTransform>(TextOpt) VPINTERNAL_VPLEGAL_CASES; 681db4dbbaSSimon Moll } 691db4dbbaSSimon Moll 701db4dbbaSSimon Moll #undef VPINTERNAL_VPLEGAL_CASES 711db4dbbaSSimon Moll 721db4dbbaSSimon Moll // Whether any override options are set. 731db4dbbaSSimon Moll static bool anyExpandVPOverridesSet() { 741db4dbbaSSimon Moll return !EVLTransformOverride.empty() || !MaskTransformOverride.empty(); 751db4dbbaSSimon Moll } 761db4dbbaSSimon Moll 771db4dbbaSSimon Moll #define DEBUG_TYPE "expandvp" 781db4dbbaSSimon Moll 791db4dbbaSSimon Moll STATISTIC(NumFoldedVL, "Number of folded vector length params"); 801db4dbbaSSimon Moll STATISTIC(NumLoweredVPOps, "Number of folded vector predication operations"); 811db4dbbaSSimon Moll 821db4dbbaSSimon Moll ///// Helpers { 831db4dbbaSSimon Moll 841db4dbbaSSimon Moll /// \returns Whether the vector mask \p MaskVal has all lane bits set. 851db4dbbaSSimon Moll static bool isAllTrueMask(Value *MaskVal) { 86f390781cSLorenzo Albano if (Value *SplattedVal = getSplatValue(MaskVal)) 87f390781cSLorenzo Albano if (auto *ConstValue = dyn_cast<Constant>(SplattedVal)) 88f390781cSLorenzo Albano return ConstValue->isAllOnesValue(); 89f390781cSLorenzo Albano 90f390781cSLorenzo Albano return false; 911db4dbbaSSimon Moll } 921db4dbbaSSimon Moll 931db4dbbaSSimon Moll /// \returns A non-excepting divisor constant for this type. 941db4dbbaSSimon Moll static Constant *getSafeDivisor(Type *DivTy) { 951db4dbbaSSimon Moll assert(DivTy->isIntOrIntVectorTy() && "Unsupported divisor type"); 961db4dbbaSSimon Moll return ConstantInt::get(DivTy, 1u, false); 971db4dbbaSSimon Moll } 981db4dbbaSSimon Moll 991db4dbbaSSimon Moll /// Transfer operation properties from \p OldVPI to \p NewVal. 1001db4dbbaSSimon Moll static void transferDecorations(Value &NewVal, VPIntrinsic &VPI) { 1011db4dbbaSSimon Moll auto *NewInst = dyn_cast<Instruction>(&NewVal); 1021db4dbbaSSimon Moll if (!NewInst || !isa<FPMathOperator>(NewVal)) 1031db4dbbaSSimon Moll return; 1041db4dbbaSSimon Moll 1051db4dbbaSSimon Moll auto *OldFMOp = dyn_cast<FPMathOperator>(&VPI); 1061db4dbbaSSimon Moll if (!OldFMOp) 1071db4dbbaSSimon Moll return; 1081db4dbbaSSimon Moll 1091db4dbbaSSimon Moll NewInst->setFastMathFlags(OldFMOp->getFastMathFlags()); 1101db4dbbaSSimon Moll } 1111db4dbbaSSimon Moll 1121db4dbbaSSimon Moll /// Transfer all properties from \p OldOp to \p NewOp and replace all uses. 1131db4dbbaSSimon Moll /// OldVP gets erased. 1141db4dbbaSSimon Moll static void replaceOperation(Value &NewOp, VPIntrinsic &OldOp) { 1151db4dbbaSSimon Moll transferDecorations(NewOp, OldOp); 1161db4dbbaSSimon Moll OldOp.replaceAllUsesWith(&NewOp); 1171db4dbbaSSimon Moll OldOp.eraseFromParent(); 1181db4dbbaSSimon Moll } 1191db4dbbaSSimon Moll 1206e127110SSimon Moll static bool maySpeculateLanes(VPIntrinsic &VPI) { 1216e127110SSimon Moll // The result of VP reductions depends on the mask and evl. 1226e127110SSimon Moll if (isa<VPReductionIntrinsic>(VPI)) 1236e127110SSimon Moll return false; 1246e127110SSimon Moll // Fallback to whether the intrinsic is speculatable. 12518c1ee04SSimon Moll Optional<unsigned> OpcOpt = VPI.getFunctionalOpcode(); 126129b531cSKazu Hirata unsigned FunctionalOpc = OpcOpt.value_or((unsigned)Instruction::Call); 127f96cb66dSNikita Popov return isSafeToSpeculativelyExecuteWithOpcode(FunctionalOpc, &VPI); 1286e127110SSimon Moll } 1296e127110SSimon Moll 1301db4dbbaSSimon Moll //// } Helpers 1311db4dbbaSSimon Moll 1321db4dbbaSSimon Moll namespace { 1331db4dbbaSSimon Moll 1341db4dbbaSSimon Moll // Expansion pass state at function scope. 1351db4dbbaSSimon Moll struct CachingVPExpander { 1361db4dbbaSSimon Moll Function &F; 1371db4dbbaSSimon Moll const TargetTransformInfo &TTI; 1381db4dbbaSSimon Moll 1391db4dbbaSSimon Moll /// \returns A (fixed length) vector with ascending integer indices 1401db4dbbaSSimon Moll /// (<0, 1, ..., NumElems-1>). 1411db4dbbaSSimon Moll /// \p Builder 1421db4dbbaSSimon Moll /// Used for instruction creation. 1431db4dbbaSSimon Moll /// \p LaneTy 1441db4dbbaSSimon Moll /// Integer element type of the result vector. 1451db4dbbaSSimon Moll /// \p NumElems 1461db4dbbaSSimon Moll /// Number of vector elements. 1471db4dbbaSSimon Moll Value *createStepVector(IRBuilder<> &Builder, Type *LaneTy, 1481db4dbbaSSimon Moll unsigned NumElems); 1491db4dbbaSSimon Moll 1501db4dbbaSSimon Moll /// \returns A bitmask that is true where the lane position is less-than \p 1511db4dbbaSSimon Moll /// EVLParam 1521db4dbbaSSimon Moll /// 1531db4dbbaSSimon Moll /// \p Builder 1541db4dbbaSSimon Moll /// Used for instruction creation. 1551db4dbbaSSimon Moll /// \p VLParam 1561db4dbbaSSimon Moll /// The explicit vector length parameter to test against the lane 1571db4dbbaSSimon Moll /// positions. 1581db4dbbaSSimon Moll /// \p ElemCount 1591db4dbbaSSimon Moll /// Static (potentially scalable) number of vector elements. 1601db4dbbaSSimon Moll Value *convertEVLToMask(IRBuilder<> &Builder, Value *EVLParam, 1611db4dbbaSSimon Moll ElementCount ElemCount); 1621db4dbbaSSimon Moll 1631db4dbbaSSimon Moll Value *foldEVLIntoMask(VPIntrinsic &VPI); 1641db4dbbaSSimon Moll 1651db4dbbaSSimon Moll /// "Remove" the %evl parameter of \p PI by setting it to the static vector 1661db4dbbaSSimon Moll /// length of the operation. 1671db4dbbaSSimon Moll void discardEVLParameter(VPIntrinsic &PI); 1681db4dbbaSSimon Moll 1691db4dbbaSSimon Moll /// \brief Lower this VP binary operator to a unpredicated binary operator. 1701db4dbbaSSimon Moll Value *expandPredicationInBinaryOperator(IRBuilder<> &Builder, 1711db4dbbaSSimon Moll VPIntrinsic &PI); 1721db4dbbaSSimon Moll 173f3e90472SFraser Cormack /// \brief Lower this VP reduction to a call to an unpredicated reduction 174f3e90472SFraser Cormack /// intrinsic. 175f3e90472SFraser Cormack Value *expandPredicationInReduction(IRBuilder<> &Builder, 176f3e90472SFraser Cormack VPReductionIntrinsic &PI); 177f3e90472SFraser Cormack 178f390781cSLorenzo Albano /// \brief Lower this VP memory operation to a non-VP intrinsic. 179f390781cSLorenzo Albano Value *expandPredicationInMemoryIntrinsic(IRBuilder<> &Builder, 180f390781cSLorenzo Albano VPIntrinsic &VPI); 181f390781cSLorenzo Albano 1821db4dbbaSSimon Moll /// \brief Query TTI and expand the vector predication in \p P accordingly. 1831db4dbbaSSimon Moll Value *expandPredication(VPIntrinsic &PI); 1841db4dbbaSSimon Moll 1851db4dbbaSSimon Moll /// \brief Determine how and whether the VPIntrinsic \p VPI shall be 1861db4dbbaSSimon Moll /// expanded. This overrides TTI with the cl::opts listed at the top of this 1871db4dbbaSSimon Moll /// file. 1881db4dbbaSSimon Moll VPLegalization getVPLegalizationStrategy(const VPIntrinsic &VPI) const; 1891db4dbbaSSimon Moll bool UsingTTIOverrides; 1901db4dbbaSSimon Moll 1911db4dbbaSSimon Moll public: 1921db4dbbaSSimon Moll CachingVPExpander(Function &F, const TargetTransformInfo &TTI) 1931db4dbbaSSimon Moll : F(F), TTI(TTI), UsingTTIOverrides(anyExpandVPOverridesSet()) {} 1941db4dbbaSSimon Moll 1951db4dbbaSSimon Moll bool expandVectorPredication(); 1961db4dbbaSSimon Moll }; 1971db4dbbaSSimon Moll 1981db4dbbaSSimon Moll //// CachingVPExpander { 1991db4dbbaSSimon Moll 2001db4dbbaSSimon Moll Value *CachingVPExpander::createStepVector(IRBuilder<> &Builder, Type *LaneTy, 2011db4dbbaSSimon Moll unsigned NumElems) { 2021db4dbbaSSimon Moll // TODO add caching 2031db4dbbaSSimon Moll SmallVector<Constant *, 16> ConstElems; 2041db4dbbaSSimon Moll 2051db4dbbaSSimon Moll for (unsigned Idx = 0; Idx < NumElems; ++Idx) 2061db4dbbaSSimon Moll ConstElems.push_back(ConstantInt::get(LaneTy, Idx, false)); 2071db4dbbaSSimon Moll 2081db4dbbaSSimon Moll return ConstantVector::get(ConstElems); 2091db4dbbaSSimon Moll } 2101db4dbbaSSimon Moll 2111db4dbbaSSimon Moll Value *CachingVPExpander::convertEVLToMask(IRBuilder<> &Builder, 2121db4dbbaSSimon Moll Value *EVLParam, 2131db4dbbaSSimon Moll ElementCount ElemCount) { 2141db4dbbaSSimon Moll // TODO add caching 2151db4dbbaSSimon Moll // Scalable vector %evl conversion. 2161db4dbbaSSimon Moll if (ElemCount.isScalable()) { 2171db4dbbaSSimon Moll auto *M = Builder.GetInsertBlock()->getModule(); 2181db4dbbaSSimon Moll Type *BoolVecTy = VectorType::get(Builder.getInt1Ty(), ElemCount); 2191db4dbbaSSimon Moll Function *ActiveMaskFunc = Intrinsic::getDeclaration( 2201db4dbbaSSimon Moll M, Intrinsic::get_active_lane_mask, {BoolVecTy, EVLParam->getType()}); 2211db4dbbaSSimon Moll // `get_active_lane_mask` performs an implicit less-than comparison. 2221db4dbbaSSimon Moll Value *ConstZero = Builder.getInt32(0); 2231db4dbbaSSimon Moll return Builder.CreateCall(ActiveMaskFunc, {ConstZero, EVLParam}); 2241db4dbbaSSimon Moll } 2251db4dbbaSSimon Moll 2261db4dbbaSSimon Moll // Fixed vector %evl conversion. 2271db4dbbaSSimon Moll Type *LaneTy = EVLParam->getType(); 2281db4dbbaSSimon Moll unsigned NumElems = ElemCount.getFixedValue(); 2291db4dbbaSSimon Moll Value *VLSplat = Builder.CreateVectorSplat(NumElems, EVLParam); 2301db4dbbaSSimon Moll Value *IdxVec = createStepVector(Builder, LaneTy, NumElems); 2311db4dbbaSSimon Moll return Builder.CreateICmp(CmpInst::ICMP_ULT, IdxVec, VLSplat); 2321db4dbbaSSimon Moll } 2331db4dbbaSSimon Moll 2341db4dbbaSSimon Moll Value * 2351db4dbbaSSimon Moll CachingVPExpander::expandPredicationInBinaryOperator(IRBuilder<> &Builder, 2361db4dbbaSSimon Moll VPIntrinsic &VPI) { 2376e127110SSimon Moll assert((maySpeculateLanes(VPI) || VPI.canIgnoreVectorLengthParam()) && 2381db4dbbaSSimon Moll "Implicitly dropping %evl in non-speculatable operator!"); 2391db4dbbaSSimon Moll 24066963bf3SSimon Moll auto OC = static_cast<Instruction::BinaryOps>(*VPI.getFunctionalOpcode()); 2411db4dbbaSSimon Moll assert(Instruction::isBinaryOp(OC)); 2421db4dbbaSSimon Moll 2431db4dbbaSSimon Moll Value *Op0 = VPI.getOperand(0); 2441db4dbbaSSimon Moll Value *Op1 = VPI.getOperand(1); 2451db4dbbaSSimon Moll Value *Mask = VPI.getMaskParam(); 2461db4dbbaSSimon Moll 2471db4dbbaSSimon Moll // Blend in safe operands. 2481db4dbbaSSimon Moll if (Mask && !isAllTrueMask(Mask)) { 2491db4dbbaSSimon Moll switch (OC) { 2501db4dbbaSSimon Moll default: 2511db4dbbaSSimon Moll // Can safely ignore the predicate. 2521db4dbbaSSimon Moll break; 2531db4dbbaSSimon Moll 2541db4dbbaSSimon Moll // Division operators need a safe divisor on masked-off lanes (1). 2551db4dbbaSSimon Moll case Instruction::UDiv: 2561db4dbbaSSimon Moll case Instruction::SDiv: 2571db4dbbaSSimon Moll case Instruction::URem: 2581db4dbbaSSimon Moll case Instruction::SRem: 2591db4dbbaSSimon Moll // 2nd operand must not be zero. 2601db4dbbaSSimon Moll Value *SafeDivisor = getSafeDivisor(VPI.getType()); 2611db4dbbaSSimon Moll Op1 = Builder.CreateSelect(Mask, Op1, SafeDivisor); 2621db4dbbaSSimon Moll } 2631db4dbbaSSimon Moll } 2641db4dbbaSSimon Moll 2651db4dbbaSSimon Moll Value *NewBinOp = Builder.CreateBinOp(OC, Op0, Op1, VPI.getName()); 2661db4dbbaSSimon Moll 2671db4dbbaSSimon Moll replaceOperation(*NewBinOp, VPI); 2681db4dbbaSSimon Moll return NewBinOp; 2691db4dbbaSSimon Moll } 2701db4dbbaSSimon Moll 271f3e90472SFraser Cormack static Value *getNeutralReductionElement(const VPReductionIntrinsic &VPI, 272f3e90472SFraser Cormack Type *EltTy) { 273f3e90472SFraser Cormack bool Negative = false; 274f3e90472SFraser Cormack unsigned EltBits = EltTy->getScalarSizeInBits(); 275f3e90472SFraser Cormack switch (VPI.getIntrinsicID()) { 276f3e90472SFraser Cormack default: 277f3e90472SFraser Cormack llvm_unreachable("Expecting a VP reduction intrinsic"); 278f3e90472SFraser Cormack case Intrinsic::vp_reduce_add: 279f3e90472SFraser Cormack case Intrinsic::vp_reduce_or: 280f3e90472SFraser Cormack case Intrinsic::vp_reduce_xor: 281f3e90472SFraser Cormack case Intrinsic::vp_reduce_umax: 282f3e90472SFraser Cormack return Constant::getNullValue(EltTy); 283f3e90472SFraser Cormack case Intrinsic::vp_reduce_mul: 284f3e90472SFraser Cormack return ConstantInt::get(EltTy, 1, /*IsSigned*/ false); 285f3e90472SFraser Cormack case Intrinsic::vp_reduce_and: 286f3e90472SFraser Cormack case Intrinsic::vp_reduce_umin: 287f3e90472SFraser Cormack return ConstantInt::getAllOnesValue(EltTy); 288f3e90472SFraser Cormack case Intrinsic::vp_reduce_smin: 289f3e90472SFraser Cormack return ConstantInt::get(EltTy->getContext(), 290f3e90472SFraser Cormack APInt::getSignedMaxValue(EltBits)); 291f3e90472SFraser Cormack case Intrinsic::vp_reduce_smax: 292f3e90472SFraser Cormack return ConstantInt::get(EltTy->getContext(), 293f3e90472SFraser Cormack APInt::getSignedMinValue(EltBits)); 294f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmax: 295f3e90472SFraser Cormack Negative = true; 296f3e90472SFraser Cormack LLVM_FALLTHROUGH; 297f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmin: { 298f3e90472SFraser Cormack FastMathFlags Flags = VPI.getFastMathFlags(); 299f3e90472SFraser Cormack const fltSemantics &Semantics = EltTy->getFltSemantics(); 300f3e90472SFraser Cormack return !Flags.noNaNs() ? ConstantFP::getQNaN(EltTy, Negative) 301f3e90472SFraser Cormack : !Flags.noInfs() 302f3e90472SFraser Cormack ? ConstantFP::getInfinity(EltTy, Negative) 303f3e90472SFraser Cormack : ConstantFP::get(EltTy, 304f3e90472SFraser Cormack APFloat::getLargest(Semantics, Negative)); 305f3e90472SFraser Cormack } 306f3e90472SFraser Cormack case Intrinsic::vp_reduce_fadd: 307f3e90472SFraser Cormack return ConstantFP::getNegativeZero(EltTy); 308f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmul: 309f3e90472SFraser Cormack return ConstantFP::get(EltTy, 1.0); 310f3e90472SFraser Cormack } 311f3e90472SFraser Cormack } 312f3e90472SFraser Cormack 313f3e90472SFraser Cormack Value * 314f3e90472SFraser Cormack CachingVPExpander::expandPredicationInReduction(IRBuilder<> &Builder, 315f3e90472SFraser Cormack VPReductionIntrinsic &VPI) { 3166e127110SSimon Moll assert((maySpeculateLanes(VPI) || VPI.canIgnoreVectorLengthParam()) && 317f3e90472SFraser Cormack "Implicitly dropping %evl in non-speculatable operator!"); 318f3e90472SFraser Cormack 319f3e90472SFraser Cormack Value *Mask = VPI.getMaskParam(); 320f3e90472SFraser Cormack Value *RedOp = VPI.getOperand(VPI.getVectorParamPos()); 321f3e90472SFraser Cormack 322f3e90472SFraser Cormack // Insert neutral element in masked-out positions 323f3e90472SFraser Cormack if (Mask && !isAllTrueMask(Mask)) { 324f3e90472SFraser Cormack auto *NeutralElt = getNeutralReductionElement(VPI, VPI.getType()); 325f3e90472SFraser Cormack auto *NeutralVector = Builder.CreateVectorSplat( 326f3e90472SFraser Cormack cast<VectorType>(RedOp->getType())->getElementCount(), NeutralElt); 327f3e90472SFraser Cormack RedOp = Builder.CreateSelect(Mask, RedOp, NeutralVector); 328f3e90472SFraser Cormack } 329f3e90472SFraser Cormack 330f3e90472SFraser Cormack Value *Reduction; 331f3e90472SFraser Cormack Value *Start = VPI.getOperand(VPI.getStartParamPos()); 332f3e90472SFraser Cormack 333f3e90472SFraser Cormack switch (VPI.getIntrinsicID()) { 334f3e90472SFraser Cormack default: 335f3e90472SFraser Cormack llvm_unreachable("Impossible reduction kind"); 336f3e90472SFraser Cormack case Intrinsic::vp_reduce_add: 337f3e90472SFraser Cormack Reduction = Builder.CreateAddReduce(RedOp); 338f3e90472SFraser Cormack Reduction = Builder.CreateAdd(Reduction, Start); 339f3e90472SFraser Cormack break; 340f3e90472SFraser Cormack case Intrinsic::vp_reduce_mul: 341f3e90472SFraser Cormack Reduction = Builder.CreateMulReduce(RedOp); 342f3e90472SFraser Cormack Reduction = Builder.CreateMul(Reduction, Start); 343f3e90472SFraser Cormack break; 344f3e90472SFraser Cormack case Intrinsic::vp_reduce_and: 345f3e90472SFraser Cormack Reduction = Builder.CreateAndReduce(RedOp); 346f3e90472SFraser Cormack Reduction = Builder.CreateAnd(Reduction, Start); 347f3e90472SFraser Cormack break; 348f3e90472SFraser Cormack case Intrinsic::vp_reduce_or: 349f3e90472SFraser Cormack Reduction = Builder.CreateOrReduce(RedOp); 350f3e90472SFraser Cormack Reduction = Builder.CreateOr(Reduction, Start); 351f3e90472SFraser Cormack break; 352f3e90472SFraser Cormack case Intrinsic::vp_reduce_xor: 353f3e90472SFraser Cormack Reduction = Builder.CreateXorReduce(RedOp); 354f3e90472SFraser Cormack Reduction = Builder.CreateXor(Reduction, Start); 355f3e90472SFraser Cormack break; 356f3e90472SFraser Cormack case Intrinsic::vp_reduce_smax: 357f3e90472SFraser Cormack Reduction = Builder.CreateIntMaxReduce(RedOp, /*IsSigned*/ true); 358f3e90472SFraser Cormack Reduction = 359f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::smax, Reduction, Start); 360f3e90472SFraser Cormack break; 361f3e90472SFraser Cormack case Intrinsic::vp_reduce_smin: 362f3e90472SFraser Cormack Reduction = Builder.CreateIntMinReduce(RedOp, /*IsSigned*/ true); 363f3e90472SFraser Cormack Reduction = 364f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::smin, Reduction, Start); 365f3e90472SFraser Cormack break; 366f3e90472SFraser Cormack case Intrinsic::vp_reduce_umax: 367f3e90472SFraser Cormack Reduction = Builder.CreateIntMaxReduce(RedOp, /*IsSigned*/ false); 368f3e90472SFraser Cormack Reduction = 369f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::umax, Reduction, Start); 370f3e90472SFraser Cormack break; 371f3e90472SFraser Cormack case Intrinsic::vp_reduce_umin: 372f3e90472SFraser Cormack Reduction = Builder.CreateIntMinReduce(RedOp, /*IsSigned*/ false); 373f3e90472SFraser Cormack Reduction = 374f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::umin, Reduction, Start); 375f3e90472SFraser Cormack break; 376f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmax: 377f3e90472SFraser Cormack Reduction = Builder.CreateFPMaxReduce(RedOp); 378f3e90472SFraser Cormack transferDecorations(*Reduction, VPI); 379f3e90472SFraser Cormack Reduction = 380f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::maxnum, Reduction, Start); 381f3e90472SFraser Cormack break; 382f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmin: 383f3e90472SFraser Cormack Reduction = Builder.CreateFPMinReduce(RedOp); 384f3e90472SFraser Cormack transferDecorations(*Reduction, VPI); 385f3e90472SFraser Cormack Reduction = 386f3e90472SFraser Cormack Builder.CreateBinaryIntrinsic(Intrinsic::minnum, Reduction, Start); 387f3e90472SFraser Cormack break; 388f3e90472SFraser Cormack case Intrinsic::vp_reduce_fadd: 389f3e90472SFraser Cormack Reduction = Builder.CreateFAddReduce(Start, RedOp); 390f3e90472SFraser Cormack break; 391f3e90472SFraser Cormack case Intrinsic::vp_reduce_fmul: 392f3e90472SFraser Cormack Reduction = Builder.CreateFMulReduce(Start, RedOp); 393f3e90472SFraser Cormack break; 394f3e90472SFraser Cormack } 395f3e90472SFraser Cormack 396f3e90472SFraser Cormack replaceOperation(*Reduction, VPI); 397f3e90472SFraser Cormack return Reduction; 398f3e90472SFraser Cormack } 399f3e90472SFraser Cormack 400f390781cSLorenzo Albano Value * 401f390781cSLorenzo Albano CachingVPExpander::expandPredicationInMemoryIntrinsic(IRBuilder<> &Builder, 402f390781cSLorenzo Albano VPIntrinsic &VPI) { 403f390781cSLorenzo Albano assert(VPI.canIgnoreVectorLengthParam()); 404f390781cSLorenzo Albano 405*c00a44faSLorenzo Albano const auto &DL = F.getParent()->getDataLayout(); 406*c00a44faSLorenzo Albano 407f390781cSLorenzo Albano Value *MaskParam = VPI.getMaskParam(); 408f390781cSLorenzo Albano Value *PtrParam = VPI.getMemoryPointerParam(); 409f390781cSLorenzo Albano Value *DataParam = VPI.getMemoryDataParam(); 410f390781cSLorenzo Albano bool IsUnmasked = isAllTrueMask(MaskParam); 411f390781cSLorenzo Albano 412f390781cSLorenzo Albano MaybeAlign AlignOpt = VPI.getPointerAlignment(); 413f390781cSLorenzo Albano 414f390781cSLorenzo Albano Value *NewMemoryInst = nullptr; 415f390781cSLorenzo Albano switch (VPI.getIntrinsicID()) { 416f390781cSLorenzo Albano default: 417f390781cSLorenzo Albano llvm_unreachable("Not a VP memory intrinsic"); 418f390781cSLorenzo Albano case Intrinsic::vp_store: 419f390781cSLorenzo Albano if (IsUnmasked) { 420f390781cSLorenzo Albano StoreInst *NewStore = 421f390781cSLorenzo Albano Builder.CreateStore(DataParam, PtrParam, /*IsVolatile*/ false); 422f390781cSLorenzo Albano if (AlignOpt.hasValue()) 423f390781cSLorenzo Albano NewStore->setAlignment(AlignOpt.getValue()); 424f390781cSLorenzo Albano NewMemoryInst = NewStore; 425f390781cSLorenzo Albano } else 426f390781cSLorenzo Albano NewMemoryInst = Builder.CreateMaskedStore( 427f390781cSLorenzo Albano DataParam, PtrParam, AlignOpt.valueOrOne(), MaskParam); 428f390781cSLorenzo Albano 429f390781cSLorenzo Albano break; 430f390781cSLorenzo Albano case Intrinsic::vp_load: 431f390781cSLorenzo Albano if (IsUnmasked) { 432f390781cSLorenzo Albano LoadInst *NewLoad = 433f390781cSLorenzo Albano Builder.CreateLoad(VPI.getType(), PtrParam, /*IsVolatile*/ false); 434f390781cSLorenzo Albano if (AlignOpt.hasValue()) 435f390781cSLorenzo Albano NewLoad->setAlignment(AlignOpt.getValue()); 436f390781cSLorenzo Albano NewMemoryInst = NewLoad; 437f390781cSLorenzo Albano } else 438f390781cSLorenzo Albano NewMemoryInst = Builder.CreateMaskedLoad( 439f390781cSLorenzo Albano VPI.getType(), PtrParam, AlignOpt.valueOrOne(), MaskParam); 440f390781cSLorenzo Albano 441f390781cSLorenzo Albano break; 442*c00a44faSLorenzo Albano case Intrinsic::vp_scatter: { 443*c00a44faSLorenzo Albano auto *ElementType = 444*c00a44faSLorenzo Albano cast<VectorType>(DataParam->getType())->getElementType(); 445*c00a44faSLorenzo Albano NewMemoryInst = Builder.CreateMaskedScatter( 446*c00a44faSLorenzo Albano DataParam, PtrParam, 447*c00a44faSLorenzo Albano AlignOpt.getValueOr(DL.getPrefTypeAlign(ElementType)), MaskParam); 448*c00a44faSLorenzo Albano break; 449*c00a44faSLorenzo Albano } 450*c00a44faSLorenzo Albano case Intrinsic::vp_gather: { 451*c00a44faSLorenzo Albano auto *ElementType = cast<VectorType>(VPI.getType())->getElementType(); 452*c00a44faSLorenzo Albano NewMemoryInst = Builder.CreateMaskedGather( 453*c00a44faSLorenzo Albano VPI.getType(), PtrParam, 454*c00a44faSLorenzo Albano AlignOpt.getValueOr(DL.getPrefTypeAlign(ElementType)), MaskParam, 455*c00a44faSLorenzo Albano nullptr, VPI.getName()); 456*c00a44faSLorenzo Albano break; 457*c00a44faSLorenzo Albano } 458f390781cSLorenzo Albano } 459f390781cSLorenzo Albano 460f390781cSLorenzo Albano assert(NewMemoryInst); 461f390781cSLorenzo Albano replaceOperation(*NewMemoryInst, VPI); 462f390781cSLorenzo Albano return NewMemoryInst; 463f390781cSLorenzo Albano } 464f390781cSLorenzo Albano 4651db4dbbaSSimon Moll void CachingVPExpander::discardEVLParameter(VPIntrinsic &VPI) { 4661db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "Discard EVL parameter in " << VPI << "\n"); 4671db4dbbaSSimon Moll 4681db4dbbaSSimon Moll if (VPI.canIgnoreVectorLengthParam()) 4691db4dbbaSSimon Moll return; 4701db4dbbaSSimon Moll 4711db4dbbaSSimon Moll Value *EVLParam = VPI.getVectorLengthParam(); 4721db4dbbaSSimon Moll if (!EVLParam) 4731db4dbbaSSimon Moll return; 4741db4dbbaSSimon Moll 4751db4dbbaSSimon Moll ElementCount StaticElemCount = VPI.getStaticVectorLength(); 4761db4dbbaSSimon Moll Value *MaxEVL = nullptr; 4771db4dbbaSSimon Moll Type *Int32Ty = Type::getInt32Ty(VPI.getContext()); 4781db4dbbaSSimon Moll if (StaticElemCount.isScalable()) { 4791db4dbbaSSimon Moll // TODO add caching 4801db4dbbaSSimon Moll auto *M = VPI.getModule(); 4811db4dbbaSSimon Moll Function *VScaleFunc = 4821db4dbbaSSimon Moll Intrinsic::getDeclaration(M, Intrinsic::vscale, Int32Ty); 4831db4dbbaSSimon Moll IRBuilder<> Builder(VPI.getParent(), VPI.getIterator()); 4841db4dbbaSSimon Moll Value *FactorConst = Builder.getInt32(StaticElemCount.getKnownMinValue()); 4851db4dbbaSSimon Moll Value *VScale = Builder.CreateCall(VScaleFunc, {}, "vscale"); 4861db4dbbaSSimon Moll MaxEVL = Builder.CreateMul(VScale, FactorConst, "scalable_size", 4871db4dbbaSSimon Moll /*NUW*/ true, /*NSW*/ false); 4881db4dbbaSSimon Moll } else { 4891db4dbbaSSimon Moll MaxEVL = ConstantInt::get(Int32Ty, StaticElemCount.getFixedValue(), false); 4901db4dbbaSSimon Moll } 4911db4dbbaSSimon Moll VPI.setVectorLengthParam(MaxEVL); 4921db4dbbaSSimon Moll } 4931db4dbbaSSimon Moll 4941db4dbbaSSimon Moll Value *CachingVPExpander::foldEVLIntoMask(VPIntrinsic &VPI) { 4951db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "Folding vlen for " << VPI << '\n'); 4961db4dbbaSSimon Moll 4971db4dbbaSSimon Moll IRBuilder<> Builder(&VPI); 4981db4dbbaSSimon Moll 4991db4dbbaSSimon Moll // Ineffective %evl parameter and so nothing to do here. 5001db4dbbaSSimon Moll if (VPI.canIgnoreVectorLengthParam()) 5011db4dbbaSSimon Moll return &VPI; 5021db4dbbaSSimon Moll 5031db4dbbaSSimon Moll // Only VP intrinsics can have an %evl parameter. 5041db4dbbaSSimon Moll Value *OldMaskParam = VPI.getMaskParam(); 5051db4dbbaSSimon Moll Value *OldEVLParam = VPI.getVectorLengthParam(); 5061db4dbbaSSimon Moll assert(OldMaskParam && "no mask param to fold the vl param into"); 5071db4dbbaSSimon Moll assert(OldEVLParam && "no EVL param to fold away"); 5081db4dbbaSSimon Moll 5091db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "OLD evl: " << *OldEVLParam << '\n'); 5101db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "OLD mask: " << *OldMaskParam << '\n'); 5111db4dbbaSSimon Moll 5121db4dbbaSSimon Moll // Convert the %evl predication into vector mask predication. 5131db4dbbaSSimon Moll ElementCount ElemCount = VPI.getStaticVectorLength(); 5141db4dbbaSSimon Moll Value *VLMask = convertEVLToMask(Builder, OldEVLParam, ElemCount); 5151db4dbbaSSimon Moll Value *NewMaskParam = Builder.CreateAnd(VLMask, OldMaskParam); 5161db4dbbaSSimon Moll VPI.setMaskParam(NewMaskParam); 5171db4dbbaSSimon Moll 5181db4dbbaSSimon Moll // Drop the %evl parameter. 5191db4dbbaSSimon Moll discardEVLParameter(VPI); 5201db4dbbaSSimon Moll assert(VPI.canIgnoreVectorLengthParam() && 5211db4dbbaSSimon Moll "transformation did not render the evl param ineffective!"); 5221db4dbbaSSimon Moll 5231db4dbbaSSimon Moll // Reassess the modified instruction. 5241db4dbbaSSimon Moll return &VPI; 5251db4dbbaSSimon Moll } 5261db4dbbaSSimon Moll 5271db4dbbaSSimon Moll Value *CachingVPExpander::expandPredication(VPIntrinsic &VPI) { 5281db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "Lowering to unpredicated op: " << VPI << '\n'); 5291db4dbbaSSimon Moll 5301db4dbbaSSimon Moll IRBuilder<> Builder(&VPI); 5311db4dbbaSSimon Moll 5321db4dbbaSSimon Moll // Try lowering to a LLVM instruction first. 53366963bf3SSimon Moll auto OC = VPI.getFunctionalOpcode(); 5341db4dbbaSSimon Moll 53566963bf3SSimon Moll if (OC && Instruction::isBinaryOp(*OC)) 5361db4dbbaSSimon Moll return expandPredicationInBinaryOperator(Builder, VPI); 5371db4dbbaSSimon Moll 538f3e90472SFraser Cormack if (auto *VPRI = dyn_cast<VPReductionIntrinsic>(&VPI)) 539f3e90472SFraser Cormack return expandPredicationInReduction(Builder, *VPRI); 540f3e90472SFraser Cormack 541f390781cSLorenzo Albano switch (VPI.getIntrinsicID()) { 542f390781cSLorenzo Albano default: 543f390781cSLorenzo Albano break; 544f390781cSLorenzo Albano case Intrinsic::vp_load: 545f390781cSLorenzo Albano case Intrinsic::vp_store: 546*c00a44faSLorenzo Albano case Intrinsic::vp_gather: 547*c00a44faSLorenzo Albano case Intrinsic::vp_scatter: 548f390781cSLorenzo Albano return expandPredicationInMemoryIntrinsic(Builder, VPI); 549f390781cSLorenzo Albano } 550f390781cSLorenzo Albano 5511db4dbbaSSimon Moll return &VPI; 5521db4dbbaSSimon Moll } 5531db4dbbaSSimon Moll 5541db4dbbaSSimon Moll //// } CachingVPExpander 5551db4dbbaSSimon Moll 5561db4dbbaSSimon Moll struct TransformJob { 5571db4dbbaSSimon Moll VPIntrinsic *PI; 5581db4dbbaSSimon Moll TargetTransformInfo::VPLegalization Strategy; 5591db4dbbaSSimon Moll TransformJob(VPIntrinsic *PI, TargetTransformInfo::VPLegalization InitStrat) 5601db4dbbaSSimon Moll : PI(PI), Strategy(InitStrat) {} 5611db4dbbaSSimon Moll 5621db4dbbaSSimon Moll bool isDone() const { return Strategy.shouldDoNothing(); } 5631db4dbbaSSimon Moll }; 5641db4dbbaSSimon Moll 5656e127110SSimon Moll void sanitizeStrategy(VPIntrinsic &VPI, VPLegalization &LegalizeStrat) { 56618c1ee04SSimon Moll // Operations with speculatable lanes do not strictly need predication. 5676e127110SSimon Moll if (maySpeculateLanes(VPI)) { 5681db4dbbaSSimon Moll // Converting a speculatable VP intrinsic means dropping %mask and %evl. 5691db4dbbaSSimon Moll // No need to expand %evl into the %mask only to ignore that code. 5701db4dbbaSSimon Moll if (LegalizeStrat.OpStrategy == VPLegalization::Convert) 5711db4dbbaSSimon Moll LegalizeStrat.EVLParamStrategy = VPLegalization::Discard; 5721db4dbbaSSimon Moll return; 5731db4dbbaSSimon Moll } 5741db4dbbaSSimon Moll 5751db4dbbaSSimon Moll // We have to preserve the predicating effect of %evl for this 5761db4dbbaSSimon Moll // non-speculatable VP intrinsic. 5771db4dbbaSSimon Moll // 1) Never discard %evl. 5781db4dbbaSSimon Moll // 2) If this VP intrinsic will be expanded to non-VP code, make sure that 5791db4dbbaSSimon Moll // %evl gets folded into %mask. 5801db4dbbaSSimon Moll if ((LegalizeStrat.EVLParamStrategy == VPLegalization::Discard) || 5811db4dbbaSSimon Moll (LegalizeStrat.OpStrategy == VPLegalization::Convert)) { 5821db4dbbaSSimon Moll LegalizeStrat.EVLParamStrategy = VPLegalization::Convert; 5831db4dbbaSSimon Moll } 5841db4dbbaSSimon Moll } 5851db4dbbaSSimon Moll 5861db4dbbaSSimon Moll VPLegalization 5871db4dbbaSSimon Moll CachingVPExpander::getVPLegalizationStrategy(const VPIntrinsic &VPI) const { 5881db4dbbaSSimon Moll auto VPStrat = TTI.getVPLegalizationStrategy(VPI); 5891db4dbbaSSimon Moll if (LLVM_LIKELY(!UsingTTIOverrides)) { 5901db4dbbaSSimon Moll // No overrides - we are in production. 5911db4dbbaSSimon Moll return VPStrat; 5921db4dbbaSSimon Moll } 5931db4dbbaSSimon Moll 5941db4dbbaSSimon Moll // Overrides set - we are in testing, the following does not need to be 5951db4dbbaSSimon Moll // efficient. 5961db4dbbaSSimon Moll VPStrat.EVLParamStrategy = parseOverrideOption(EVLTransformOverride); 5971db4dbbaSSimon Moll VPStrat.OpStrategy = parseOverrideOption(MaskTransformOverride); 5981db4dbbaSSimon Moll return VPStrat; 5991db4dbbaSSimon Moll } 6001db4dbbaSSimon Moll 6011db4dbbaSSimon Moll /// \brief Expand llvm.vp.* intrinsics as requested by \p TTI. 6021db4dbbaSSimon Moll bool CachingVPExpander::expandVectorPredication() { 6031db4dbbaSSimon Moll SmallVector<TransformJob, 16> Worklist; 6041db4dbbaSSimon Moll 6051db4dbbaSSimon Moll // Collect all VPIntrinsics that need expansion and determine their expansion 6061db4dbbaSSimon Moll // strategy. 6071db4dbbaSSimon Moll for (auto &I : instructions(F)) { 6081db4dbbaSSimon Moll auto *VPI = dyn_cast<VPIntrinsic>(&I); 6091db4dbbaSSimon Moll if (!VPI) 6101db4dbbaSSimon Moll continue; 6111db4dbbaSSimon Moll auto VPStrat = getVPLegalizationStrategy(*VPI); 6126e127110SSimon Moll sanitizeStrategy(*VPI, VPStrat); 6131db4dbbaSSimon Moll if (!VPStrat.shouldDoNothing()) 6141db4dbbaSSimon Moll Worklist.emplace_back(VPI, VPStrat); 6151db4dbbaSSimon Moll } 6161db4dbbaSSimon Moll if (Worklist.empty()) 6171db4dbbaSSimon Moll return false; 6181db4dbbaSSimon Moll 6191db4dbbaSSimon Moll // Transform all VPIntrinsics on the worklist. 6201db4dbbaSSimon Moll LLVM_DEBUG(dbgs() << "\n:::: Transforming " << Worklist.size() 6211db4dbbaSSimon Moll << " instructions ::::\n"); 6221db4dbbaSSimon Moll for (TransformJob Job : Worklist) { 6231db4dbbaSSimon Moll // Transform the EVL parameter. 6241db4dbbaSSimon Moll switch (Job.Strategy.EVLParamStrategy) { 6251db4dbbaSSimon Moll case VPLegalization::Legal: 6261db4dbbaSSimon Moll break; 6271db4dbbaSSimon Moll case VPLegalization::Discard: 6281db4dbbaSSimon Moll discardEVLParameter(*Job.PI); 6291db4dbbaSSimon Moll break; 6301db4dbbaSSimon Moll case VPLegalization::Convert: 6311db4dbbaSSimon Moll if (foldEVLIntoMask(*Job.PI)) 6321db4dbbaSSimon Moll ++NumFoldedVL; 6331db4dbbaSSimon Moll break; 6341db4dbbaSSimon Moll } 6351db4dbbaSSimon Moll Job.Strategy.EVLParamStrategy = VPLegalization::Legal; 6361db4dbbaSSimon Moll 6371db4dbbaSSimon Moll // Replace with a non-predicated operation. 6381db4dbbaSSimon Moll switch (Job.Strategy.OpStrategy) { 6391db4dbbaSSimon Moll case VPLegalization::Legal: 6401db4dbbaSSimon Moll break; 6411db4dbbaSSimon Moll case VPLegalization::Discard: 6421db4dbbaSSimon Moll llvm_unreachable("Invalid strategy for operators."); 6431db4dbbaSSimon Moll case VPLegalization::Convert: 6441db4dbbaSSimon Moll expandPredication(*Job.PI); 6451db4dbbaSSimon Moll ++NumLoweredVPOps; 6461db4dbbaSSimon Moll break; 6471db4dbbaSSimon Moll } 6481db4dbbaSSimon Moll Job.Strategy.OpStrategy = VPLegalization::Legal; 6491db4dbbaSSimon Moll 6501db4dbbaSSimon Moll assert(Job.isDone() && "incomplete transformation"); 6511db4dbbaSSimon Moll } 6521db4dbbaSSimon Moll 6531db4dbbaSSimon Moll return true; 6541db4dbbaSSimon Moll } 6551db4dbbaSSimon Moll class ExpandVectorPredication : public FunctionPass { 6561db4dbbaSSimon Moll public: 6571db4dbbaSSimon Moll static char ID; 6581db4dbbaSSimon Moll ExpandVectorPredication() : FunctionPass(ID) { 6591db4dbbaSSimon Moll initializeExpandVectorPredicationPass(*PassRegistry::getPassRegistry()); 6601db4dbbaSSimon Moll } 6611db4dbbaSSimon Moll 6621db4dbbaSSimon Moll bool runOnFunction(Function &F) override { 6631db4dbbaSSimon Moll const auto *TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 6641db4dbbaSSimon Moll CachingVPExpander VPExpander(F, *TTI); 6651db4dbbaSSimon Moll return VPExpander.expandVectorPredication(); 6661db4dbbaSSimon Moll } 6671db4dbbaSSimon Moll 6681db4dbbaSSimon Moll void getAnalysisUsage(AnalysisUsage &AU) const override { 6691db4dbbaSSimon Moll AU.addRequired<TargetTransformInfoWrapperPass>(); 6701db4dbbaSSimon Moll AU.setPreservesCFG(); 6711db4dbbaSSimon Moll } 6721db4dbbaSSimon Moll }; 6731db4dbbaSSimon Moll } // namespace 6741db4dbbaSSimon Moll 6751db4dbbaSSimon Moll char ExpandVectorPredication::ID; 6761db4dbbaSSimon Moll INITIALIZE_PASS_BEGIN(ExpandVectorPredication, "expandvp", 6771db4dbbaSSimon Moll "Expand vector predication intrinsics", false, false) 6781db4dbbaSSimon Moll INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 6791db4dbbaSSimon Moll INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 6801db4dbbaSSimon Moll INITIALIZE_PASS_END(ExpandVectorPredication, "expandvp", 6811db4dbbaSSimon Moll "Expand vector predication intrinsics", false, false) 6821db4dbbaSSimon Moll 6831db4dbbaSSimon Moll FunctionPass *llvm::createExpandVectorPredicationPass() { 6841db4dbbaSSimon Moll return new ExpandVectorPredication(); 6851db4dbbaSSimon Moll } 6861db4dbbaSSimon Moll 6871db4dbbaSSimon Moll PreservedAnalyses 6881db4dbbaSSimon Moll ExpandVectorPredicationPass::run(Function &F, FunctionAnalysisManager &AM) { 6891db4dbbaSSimon Moll const auto &TTI = AM.getResult<TargetIRAnalysis>(F); 6901db4dbbaSSimon Moll CachingVPExpander VPExpander(F, TTI); 6911db4dbbaSSimon Moll if (!VPExpander.expandVectorPredication()) 6921db4dbbaSSimon Moll return PreservedAnalyses::all(); 6931db4dbbaSSimon Moll PreservedAnalyses PA; 6941db4dbbaSSimon Moll PA.preserveSet<CFGAnalyses>(); 6951db4dbbaSSimon Moll return PA; 6961db4dbbaSSimon Moll } 697