1a17f03bdSSanjay Patel //===------- VectorCombine.cpp - Optimize partial vector operations -------===// 2a17f03bdSSanjay Patel // 3a17f03bdSSanjay Patel // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a17f03bdSSanjay Patel // See https://llvm.org/LICENSE.txt for license information. 5a17f03bdSSanjay Patel // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a17f03bdSSanjay Patel // 7a17f03bdSSanjay Patel //===----------------------------------------------------------------------===// 8a17f03bdSSanjay Patel // 9a17f03bdSSanjay Patel // This pass optimizes scalar/vector interactions using target cost models. The 10a17f03bdSSanjay Patel // transforms implemented here may not fit in traditional loop-based or SLP 11a17f03bdSSanjay Patel // vectorization passes. 12a17f03bdSSanjay Patel // 13a17f03bdSSanjay Patel //===----------------------------------------------------------------------===// 14a17f03bdSSanjay Patel 15a17f03bdSSanjay Patel #include "llvm/Transforms/Vectorize/VectorCombine.h" 16a17f03bdSSanjay Patel #include "llvm/ADT/Statistic.h" 17a17f03bdSSanjay Patel #include "llvm/Analysis/GlobalsModRef.h" 18a17f03bdSSanjay Patel #include "llvm/Analysis/TargetTransformInfo.h" 1919b62b79SSanjay Patel #include "llvm/Analysis/ValueTracking.h" 20a17f03bdSSanjay Patel #include "llvm/IR/Dominators.h" 21a17f03bdSSanjay Patel #include "llvm/IR/Function.h" 22a17f03bdSSanjay Patel #include "llvm/IR/IRBuilder.h" 23a17f03bdSSanjay Patel #include "llvm/IR/PatternMatch.h" 24a17f03bdSSanjay Patel #include "llvm/InitializePasses.h" 25a17f03bdSSanjay Patel #include "llvm/Pass.h" 2625c6544fSSanjay Patel #include "llvm/Support/CommandLine.h" 27a17f03bdSSanjay Patel #include "llvm/Transforms/Vectorize.h" 28a17f03bdSSanjay Patel #include "llvm/Transforms/Utils/Local.h" 29a17f03bdSSanjay Patel 30a17f03bdSSanjay Patel using namespace llvm; 31a17f03bdSSanjay Patel using namespace llvm::PatternMatch; 32a17f03bdSSanjay Patel 33a17f03bdSSanjay Patel #define DEBUG_TYPE "vector-combine" 34a17f03bdSSanjay Patel STATISTIC(NumVecCmp, "Number of vector compares formed"); 3519b62b79SSanjay Patel STATISTIC(NumVecBO, "Number of vector binops formed"); 36a17f03bdSSanjay Patel 3725c6544fSSanjay Patel static cl::opt<bool> DisableVectorCombine( 3825c6544fSSanjay Patel "disable-vector-combine", cl::init(false), cl::Hidden, 3925c6544fSSanjay Patel cl::desc("Disable all vector combine transforms")); 4025c6544fSSanjay Patel 41a69158c1SSanjay Patel static cl::opt<bool> DisableBinopExtractShuffle( 42a69158c1SSanjay Patel "disable-binop-extract-shuffle", cl::init(false), cl::Hidden, 43a69158c1SSanjay Patel cl::desc("Disable binop extract to shuffle transforms")); 44a69158c1SSanjay Patel 45a69158c1SSanjay Patel 46a69158c1SSanjay Patel /// Compare the relative costs of 2 extracts followed by scalar operation vs. 47a69158c1SSanjay Patel /// vector operation(s) followed by extract. Return true if the existing 48a69158c1SSanjay Patel /// instructions are cheaper than a vector alternative. Otherwise, return false 49a69158c1SSanjay Patel /// and if one of the extracts should be transformed to a shufflevector, set 50a69158c1SSanjay Patel /// \p ConvertToShuffle to that extract instruction. 5134e34855SSanjay Patel static bool isExtractExtractCheap(Instruction *Ext0, Instruction *Ext1, 5234e34855SSanjay Patel unsigned Opcode, 53a69158c1SSanjay Patel const TargetTransformInfo &TTI, 54a69158c1SSanjay Patel Instruction *&ConvertToShuffle) { 554fa63fd4SAustin Kerbow assert(isa<ConstantInt>(Ext0->getOperand(1)) && 56a69158c1SSanjay Patel isa<ConstantInt>(Ext1->getOperand(1)) && 57a69158c1SSanjay Patel "Expected constant extract indexes"); 5834e34855SSanjay Patel Type *ScalarTy = Ext0->getType(); 5934e34855SSanjay Patel Type *VecTy = Ext0->getOperand(0)->getType(); 6034e34855SSanjay Patel int ScalarOpCost, VectorOpCost; 6134e34855SSanjay Patel 6234e34855SSanjay Patel // Get cost estimates for scalar and vector versions of the operation. 6334e34855SSanjay Patel bool IsBinOp = Instruction::isBinaryOp(Opcode); 6434e34855SSanjay Patel if (IsBinOp) { 6534e34855SSanjay Patel ScalarOpCost = TTI.getArithmeticInstrCost(Opcode, ScalarTy); 6634e34855SSanjay Patel VectorOpCost = TTI.getArithmeticInstrCost(Opcode, VecTy); 6734e34855SSanjay Patel } else { 6834e34855SSanjay Patel assert((Opcode == Instruction::ICmp || Opcode == Instruction::FCmp) && 6934e34855SSanjay Patel "Expected a compare"); 7034e34855SSanjay Patel ScalarOpCost = TTI.getCmpSelInstrCost(Opcode, ScalarTy, 7134e34855SSanjay Patel CmpInst::makeCmpResultType(ScalarTy)); 7234e34855SSanjay Patel VectorOpCost = TTI.getCmpSelInstrCost(Opcode, VecTy, 7334e34855SSanjay Patel CmpInst::makeCmpResultType(VecTy)); 7434e34855SSanjay Patel } 7534e34855SSanjay Patel 76a69158c1SSanjay Patel // Get cost estimates for the extract elements. These costs will factor into 7734e34855SSanjay Patel // both sequences. 78a69158c1SSanjay Patel unsigned Ext0Index = cast<ConstantInt>(Ext0->getOperand(1))->getZExtValue(); 79a69158c1SSanjay Patel unsigned Ext1Index = cast<ConstantInt>(Ext1->getOperand(1))->getZExtValue(); 80a69158c1SSanjay Patel 81a69158c1SSanjay Patel int Extract0Cost = TTI.getVectorInstrCost(Instruction::ExtractElement, 82a69158c1SSanjay Patel VecTy, Ext0Index); 83a69158c1SSanjay Patel int Extract1Cost = TTI.getVectorInstrCost(Instruction::ExtractElement, 84a69158c1SSanjay Patel VecTy, Ext1Index); 85a69158c1SSanjay Patel 86a69158c1SSanjay Patel // A more expensive extract will always be replaced by a splat shuffle. 87a69158c1SSanjay Patel // For example, if Ext0 is more expensive: 88a69158c1SSanjay Patel // opcode (extelt V0, Ext0), (ext V1, Ext1) --> 89a69158c1SSanjay Patel // extelt (opcode (splat V0, Ext0), V1), Ext1 90a69158c1SSanjay Patel // TODO: Evaluate whether that always results in lowest cost. Alternatively, 91a69158c1SSanjay Patel // check the cost of creating a broadcast shuffle and shuffling both 92a69158c1SSanjay Patel // operands to element 0. 93a69158c1SSanjay Patel int CheapExtractCost = std::min(Extract0Cost, Extract1Cost); 9434e34855SSanjay Patel 9534e34855SSanjay Patel // Extra uses of the extracts mean that we include those costs in the 9634e34855SSanjay Patel // vector total because those instructions will not be eliminated. 97e9c79a7aSSanjay Patel int OldCost, NewCost; 98a69158c1SSanjay Patel if (Ext0->getOperand(0) == Ext1->getOperand(0) && Ext0Index == Ext1Index) { 99a69158c1SSanjay Patel // Handle a special case. If the 2 extracts are identical, adjust the 10034e34855SSanjay Patel // formulas to account for that. The extra use charge allows for either the 10134e34855SSanjay Patel // CSE'd pattern or an unoptimized form with identical values: 10234e34855SSanjay Patel // opcode (extelt V, C), (extelt V, C) --> extelt (opcode V, V), C 10334e34855SSanjay Patel bool HasUseTax = Ext0 == Ext1 ? !Ext0->hasNUses(2) 10434e34855SSanjay Patel : !Ext0->hasOneUse() || !Ext1->hasOneUse(); 105a69158c1SSanjay Patel OldCost = CheapExtractCost + ScalarOpCost; 106a69158c1SSanjay Patel NewCost = VectorOpCost + CheapExtractCost + HasUseTax * CheapExtractCost; 10734e34855SSanjay Patel } else { 10834e34855SSanjay Patel // Handle the general case. Each extract is actually a different value: 109a69158c1SSanjay Patel // opcode (extelt V0, C0), (extelt V1, C1) --> extelt (opcode V0, V1), C 110a69158c1SSanjay Patel OldCost = Extract0Cost + Extract1Cost + ScalarOpCost; 111a69158c1SSanjay Patel NewCost = VectorOpCost + CheapExtractCost + 112a69158c1SSanjay Patel !Ext0->hasOneUse() * Extract0Cost + 113a69158c1SSanjay Patel !Ext1->hasOneUse() * Extract1Cost; 11434e34855SSanjay Patel } 115a69158c1SSanjay Patel 116a69158c1SSanjay Patel if (Ext0Index == Ext1Index) { 117a69158c1SSanjay Patel // If the extract indexes are identical, no shuffle is needed. 118a69158c1SSanjay Patel ConvertToShuffle = nullptr; 119a69158c1SSanjay Patel } else { 120a69158c1SSanjay Patel if (IsBinOp && DisableBinopExtractShuffle) 121a69158c1SSanjay Patel return true; 122a69158c1SSanjay Patel 123a69158c1SSanjay Patel // If we are extracting from 2 different indexes, then one operand must be 124a69158c1SSanjay Patel // shuffled before performing the vector operation. The shuffle mask is 125a69158c1SSanjay Patel // undefined except for 1 lane that is being translated to the remaining 126a69158c1SSanjay Patel // extraction lane. Therefore, it is a splat shuffle. Ex: 127a69158c1SSanjay Patel // ShufMask = { undef, undef, 0, undef } 128a69158c1SSanjay Patel // TODO: The cost model has an option for a "broadcast" shuffle 129a69158c1SSanjay Patel // (splat-from-element-0), but no option for a more general splat. 130a69158c1SSanjay Patel NewCost += 131a69158c1SSanjay Patel TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, VecTy); 132a69158c1SSanjay Patel 133a69158c1SSanjay Patel // The more expensive extract will be replaced by a shuffle. If the extracts 134a69158c1SSanjay Patel // have the same cost, replace the extract with the higher index. 135a69158c1SSanjay Patel if (Extract0Cost > Extract1Cost) 136a69158c1SSanjay Patel ConvertToShuffle = Ext0; 137a69158c1SSanjay Patel else if (Extract1Cost > Extract0Cost) 138a69158c1SSanjay Patel ConvertToShuffle = Ext1; 139a69158c1SSanjay Patel else 140a69158c1SSanjay Patel ConvertToShuffle = Ext0Index > Ext1Index ? Ext0 : Ext1; 141a69158c1SSanjay Patel } 142a69158c1SSanjay Patel 14310ea01d8SSanjay Patel // Aggressively form a vector op if the cost is equal because the transform 14410ea01d8SSanjay Patel // may enable further optimization. 14510ea01d8SSanjay Patel // Codegen can reverse this transform (scalarize) if it was not profitable. 14610ea01d8SSanjay Patel return OldCost < NewCost; 14734e34855SSanjay Patel } 14834e34855SSanjay Patel 149fc445589SSanjay Patel /// Try to reduce extract element costs by converting scalar compares to vector 150fc445589SSanjay Patel /// compares followed by extract. 151e9c79a7aSSanjay Patel /// cmp (ext0 V0, C), (ext1 V1, C) 152e9c79a7aSSanjay Patel static void foldExtExtCmp(Instruction *Ext0, Instruction *Ext1, 153fc445589SSanjay Patel Instruction &I, const TargetTransformInfo &TTI) { 154fc445589SSanjay Patel assert(isa<CmpInst>(&I) && "Expected a compare"); 155a17f03bdSSanjay Patel 156a17f03bdSSanjay Patel // cmp Pred (extelt V0, C), (extelt V1, C) --> extelt (cmp Pred V0, V1), C 157a17f03bdSSanjay Patel ++NumVecCmp; 158a17f03bdSSanjay Patel IRBuilder<> Builder(&I); 159fc445589SSanjay Patel CmpInst::Predicate Pred = cast<CmpInst>(&I)->getPredicate(); 160e9c79a7aSSanjay Patel Value *V0 = Ext0->getOperand(0), *V1 = Ext1->getOperand(0); 16134e34855SSanjay Patel Value *VecCmp = 16234e34855SSanjay Patel Ext0->getType()->isFloatingPointTy() ? Builder.CreateFCmp(Pred, V0, V1) 163a17f03bdSSanjay Patel : Builder.CreateICmp(Pred, V0, V1); 164fc445589SSanjay Patel Value *Extract = Builder.CreateExtractElement(VecCmp, Ext0->getOperand(1)); 165fc445589SSanjay Patel I.replaceAllUsesWith(Extract); 166a17f03bdSSanjay Patel } 167a17f03bdSSanjay Patel 16819b62b79SSanjay Patel /// Try to reduce extract element costs by converting scalar binops to vector 16919b62b79SSanjay Patel /// binops followed by extract. 170e9c79a7aSSanjay Patel /// bo (ext0 V0, C), (ext1 V1, C) 171e9c79a7aSSanjay Patel static void foldExtExtBinop(Instruction *Ext0, Instruction *Ext1, 172fc445589SSanjay Patel Instruction &I, const TargetTransformInfo &TTI) { 173fc445589SSanjay Patel assert(isa<BinaryOperator>(&I) && "Expected a binary operator"); 17419b62b79SSanjay Patel 17534e34855SSanjay Patel // bo (extelt V0, C), (extelt V1, C) --> extelt (bo V0, V1), C 17619b62b79SSanjay Patel ++NumVecBO; 17719b62b79SSanjay Patel IRBuilder<> Builder(&I); 178e9c79a7aSSanjay Patel Value *V0 = Ext0->getOperand(0), *V1 = Ext1->getOperand(0); 179e9c79a7aSSanjay Patel Value *VecBO = 18034e34855SSanjay Patel Builder.CreateBinOp(cast<BinaryOperator>(&I)->getOpcode(), V0, V1); 181e9c79a7aSSanjay Patel 18219b62b79SSanjay Patel // All IR flags are safe to back-propagate because any potential poison 18319b62b79SSanjay Patel // created in unused vector elements is discarded by the extract. 184e9c79a7aSSanjay Patel if (auto *VecBOInst = dyn_cast<Instruction>(VecBO)) 18519b62b79SSanjay Patel VecBOInst->copyIRFlags(&I); 186e9c79a7aSSanjay Patel 187e9c79a7aSSanjay Patel Value *Extract = Builder.CreateExtractElement(VecBO, Ext0->getOperand(1)); 18819b62b79SSanjay Patel I.replaceAllUsesWith(Extract); 18919b62b79SSanjay Patel } 19019b62b79SSanjay Patel 191fc445589SSanjay Patel /// Match an instruction with extracted vector operands. 192fc445589SSanjay Patel static bool foldExtractExtract(Instruction &I, const TargetTransformInfo &TTI) { 193e9c79a7aSSanjay Patel // It is not safe to transform things like div, urem, etc. because we may 194e9c79a7aSSanjay Patel // create undefined behavior when executing those on unknown vector elements. 195e9c79a7aSSanjay Patel if (!isSafeToSpeculativelyExecute(&I)) 196e9c79a7aSSanjay Patel return false; 197e9c79a7aSSanjay Patel 198fc445589SSanjay Patel Instruction *Ext0, *Ext1; 199fc445589SSanjay Patel CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE; 200fc445589SSanjay Patel if (!match(&I, m_Cmp(Pred, m_Instruction(Ext0), m_Instruction(Ext1))) && 201fc445589SSanjay Patel !match(&I, m_BinOp(m_Instruction(Ext0), m_Instruction(Ext1)))) 202fc445589SSanjay Patel return false; 203fc445589SSanjay Patel 204fc445589SSanjay Patel Value *V0, *V1; 205fc445589SSanjay Patel uint64_t C0, C1; 206fc445589SSanjay Patel if (!match(Ext0, m_ExtractElement(m_Value(V0), m_ConstantInt(C0))) || 207fc445589SSanjay Patel !match(Ext1, m_ExtractElement(m_Value(V1), m_ConstantInt(C1))) || 208fc445589SSanjay Patel V0->getType() != V1->getType()) 209fc445589SSanjay Patel return false; 210fc445589SSanjay Patel 211a69158c1SSanjay Patel Instruction *ConvertToShuffle; 212a69158c1SSanjay Patel if (isExtractExtractCheap(Ext0, Ext1, I.getOpcode(), TTI, ConvertToShuffle)) 213fc445589SSanjay Patel return false; 214e9c79a7aSSanjay Patel 215a69158c1SSanjay Patel if (ConvertToShuffle) { 216a69158c1SSanjay Patel // The shuffle mask is undefined except for 1 lane that is being translated 217a69158c1SSanjay Patel // to the cheap extraction lane. Example: 218a69158c1SSanjay Patel // ShufMask = { 2, undef, undef, undef } 219a69158c1SSanjay Patel uint64_t SplatIndex = ConvertToShuffle == Ext0 ? C0 : C1; 220a69158c1SSanjay Patel uint64_t CheapExtIndex = ConvertToShuffle == Ext0 ? C1 : C0; 221a69158c1SSanjay Patel Type *VecTy = V0->getType(); 222a69158c1SSanjay Patel Type *I32Ty = IntegerType::getInt32Ty(I.getContext()); 223a69158c1SSanjay Patel UndefValue *Undef = UndefValue::get(I32Ty); 224a69158c1SSanjay Patel SmallVector<Constant *, 32> ShufMask(VecTy->getVectorNumElements(), Undef); 225a69158c1SSanjay Patel ShufMask[CheapExtIndex] = ConstantInt::get(I32Ty, SplatIndex); 226a69158c1SSanjay Patel IRBuilder<> Builder(ConvertToShuffle); 227a69158c1SSanjay Patel 228a69158c1SSanjay Patel // extelt X, C --> extelt (splat X), C' 229a69158c1SSanjay Patel Value *Shuf = Builder.CreateShuffleVector(ConvertToShuffle->getOperand(0), 230a69158c1SSanjay Patel UndefValue::get(VecTy), 231a69158c1SSanjay Patel ConstantVector::get(ShufMask)); 232a69158c1SSanjay Patel Value *NewExt = Builder.CreateExtractElement(Shuf, CheapExtIndex); 233a69158c1SSanjay Patel if (ConvertToShuffle == Ext0) 234a69158c1SSanjay Patel Ext0 = cast<Instruction>(NewExt); 235a69158c1SSanjay Patel else 236a69158c1SSanjay Patel Ext1 = cast<Instruction>(NewExt); 237a69158c1SSanjay Patel } 238e9c79a7aSSanjay Patel 239e9c79a7aSSanjay Patel if (Pred != CmpInst::BAD_ICMP_PREDICATE) 240e9c79a7aSSanjay Patel foldExtExtCmp(Ext0, Ext1, I, TTI); 241e9c79a7aSSanjay Patel else 242e9c79a7aSSanjay Patel foldExtExtBinop(Ext0, Ext1, I, TTI); 243e9c79a7aSSanjay Patel 244e9c79a7aSSanjay Patel return true; 245fc445589SSanjay Patel } 246fc445589SSanjay Patel 247a17f03bdSSanjay Patel /// This is the entry point for all transforms. Pass manager differences are 248a17f03bdSSanjay Patel /// handled in the callers of this function. 249a17f03bdSSanjay Patel static bool runImpl(Function &F, const TargetTransformInfo &TTI, 250a17f03bdSSanjay Patel const DominatorTree &DT) { 25125c6544fSSanjay Patel if (DisableVectorCombine) 25225c6544fSSanjay Patel return false; 25325c6544fSSanjay Patel 254a17f03bdSSanjay Patel bool MadeChange = false; 255a17f03bdSSanjay Patel for (BasicBlock &BB : F) { 256a17f03bdSSanjay Patel // Ignore unreachable basic blocks. 257a17f03bdSSanjay Patel if (!DT.isReachableFromEntry(&BB)) 258a17f03bdSSanjay Patel continue; 259a17f03bdSSanjay Patel // Do not delete instructions under here and invalidate the iterator. 260a17f03bdSSanjay Patel // Walk the block backwards for efficiency. We're matching a chain of 261a17f03bdSSanjay Patel // use->defs, so we're more likely to succeed by starting from the bottom. 262a17f03bdSSanjay Patel // TODO: It could be more efficient to remove dead instructions 263a17f03bdSSanjay Patel // iteratively in this loop rather than waiting until the end. 264*fc3cc8a4SSanjay Patel for (Instruction &I : make_range(BB.rbegin(), BB.rend())) { 265*fc3cc8a4SSanjay Patel if (isa<DbgInfoIntrinsic>(I)) 266*fc3cc8a4SSanjay Patel continue; 267fc445589SSanjay Patel MadeChange |= foldExtractExtract(I, TTI); 268a17f03bdSSanjay Patel } 269*fc3cc8a4SSanjay Patel } 270a17f03bdSSanjay Patel 271a17f03bdSSanjay Patel // We're done with transforms, so remove dead instructions. 272a17f03bdSSanjay Patel if (MadeChange) 273a17f03bdSSanjay Patel for (BasicBlock &BB : F) 274a17f03bdSSanjay Patel SimplifyInstructionsInBlock(&BB); 275a17f03bdSSanjay Patel 276a17f03bdSSanjay Patel return MadeChange; 277a17f03bdSSanjay Patel } 278a17f03bdSSanjay Patel 279a17f03bdSSanjay Patel // Pass manager boilerplate below here. 280a17f03bdSSanjay Patel 281a17f03bdSSanjay Patel namespace { 282a17f03bdSSanjay Patel class VectorCombineLegacyPass : public FunctionPass { 283a17f03bdSSanjay Patel public: 284a17f03bdSSanjay Patel static char ID; 285a17f03bdSSanjay Patel VectorCombineLegacyPass() : FunctionPass(ID) { 286a17f03bdSSanjay Patel initializeVectorCombineLegacyPassPass(*PassRegistry::getPassRegistry()); 287a17f03bdSSanjay Patel } 288a17f03bdSSanjay Patel 289a17f03bdSSanjay Patel void getAnalysisUsage(AnalysisUsage &AU) const override { 290a17f03bdSSanjay Patel AU.addRequired<DominatorTreeWrapperPass>(); 291a17f03bdSSanjay Patel AU.addRequired<TargetTransformInfoWrapperPass>(); 292a17f03bdSSanjay Patel AU.setPreservesCFG(); 293a17f03bdSSanjay Patel AU.addPreserved<DominatorTreeWrapperPass>(); 294a17f03bdSSanjay Patel AU.addPreserved<GlobalsAAWrapperPass>(); 295a17f03bdSSanjay Patel FunctionPass::getAnalysisUsage(AU); 296a17f03bdSSanjay Patel } 297a17f03bdSSanjay Patel 298a17f03bdSSanjay Patel bool runOnFunction(Function &F) override { 299a17f03bdSSanjay Patel if (skipFunction(F)) 300a17f03bdSSanjay Patel return false; 301a17f03bdSSanjay Patel auto &TTI = getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); 302a17f03bdSSanjay Patel auto &DT = getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 303a17f03bdSSanjay Patel return runImpl(F, TTI, DT); 304a17f03bdSSanjay Patel } 305a17f03bdSSanjay Patel }; 306a17f03bdSSanjay Patel } // namespace 307a17f03bdSSanjay Patel 308a17f03bdSSanjay Patel char VectorCombineLegacyPass::ID = 0; 309a17f03bdSSanjay Patel INITIALIZE_PASS_BEGIN(VectorCombineLegacyPass, "vector-combine", 310a17f03bdSSanjay Patel "Optimize scalar/vector ops", false, 311a17f03bdSSanjay Patel false) 312a17f03bdSSanjay Patel INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 313a17f03bdSSanjay Patel INITIALIZE_PASS_END(VectorCombineLegacyPass, "vector-combine", 314a17f03bdSSanjay Patel "Optimize scalar/vector ops", false, false) 315a17f03bdSSanjay Patel Pass *llvm::createVectorCombinePass() { 316a17f03bdSSanjay Patel return new VectorCombineLegacyPass(); 317a17f03bdSSanjay Patel } 318a17f03bdSSanjay Patel 319a17f03bdSSanjay Patel PreservedAnalyses VectorCombinePass::run(Function &F, 320a17f03bdSSanjay Patel FunctionAnalysisManager &FAM) { 321a17f03bdSSanjay Patel TargetTransformInfo &TTI = FAM.getResult<TargetIRAnalysis>(F); 322a17f03bdSSanjay Patel DominatorTree &DT = FAM.getResult<DominatorTreeAnalysis>(F); 323a17f03bdSSanjay Patel if (!runImpl(F, TTI, DT)) 324a17f03bdSSanjay Patel return PreservedAnalyses::all(); 325a17f03bdSSanjay Patel PreservedAnalyses PA; 326a17f03bdSSanjay Patel PA.preserveSet<CFGAnalyses>(); 327a17f03bdSSanjay Patel PA.preserve<GlobalsAA>(); 328a17f03bdSSanjay Patel return PA; 329a17f03bdSSanjay Patel } 330