1 //===- InferFunctionAttrs.cpp - Infer implicit function attributes --------===// 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 "llvm/Transforms/IPO/InferFunctionAttrs.h" 10 #include "llvm/Analysis/TargetLibraryInfo.h" 11 #include "llvm/IR/Function.h" 12 #include "llvm/IR/LLVMContext.h" 13 #include "llvm/IR/Module.h" 14 #include "llvm/InitializePasses.h" 15 #include "llvm/Support/Debug.h" 16 #include "llvm/Support/raw_ostream.h" 17 #include "llvm/Transforms/Utils/BuildLibCalls.h" 18 #include "llvm/Transforms/Utils/Local.h" 19 using namespace llvm; 20 21 #define DEBUG_TYPE "inferattrs" 22 23 static bool inferAllPrototypeAttributes( 24 Module &M, function_ref<TargetLibraryInfo &(Function &)> GetTLI) { 25 bool Changed = false; 26 27 for (Function &F : M.functions()) 28 // We only infer things using the prototype and the name; we don't need 29 // definitions. This ensures libfuncs are annotated and also allows our 30 // CGSCC inference to avoid needing to duplicate the inference from other 31 // attribute logic on all calls to declarations (as declarations aren't 32 // explicitly visited by CGSCC passes in the new pass manager.) 33 if (F.isDeclaration() && !F.hasOptNone()) { 34 Changed |= inferLibFuncAttributes(F, GetTLI(F)); 35 Changed |= inferAttributesFromOthers(F); 36 } 37 38 return Changed; 39 } 40 41 PreservedAnalyses InferFunctionAttrsPass::run(Module &M, 42 ModuleAnalysisManager &AM) { 43 FunctionAnalysisManager &FAM = 44 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 45 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 46 return FAM.getResult<TargetLibraryAnalysis>(F); 47 }; 48 49 if (!inferAllPrototypeAttributes(M, GetTLI)) 50 // If we didn't infer anything, preserve all analyses. 51 return PreservedAnalyses::all(); 52 53 // Otherwise, we may have changed fundamental function attributes, so clear 54 // out all the passes. 55 return PreservedAnalyses::none(); 56 } 57 58 namespace { 59 struct InferFunctionAttrsLegacyPass : public ModulePass { 60 static char ID; // Pass identification, replacement for typeid 61 InferFunctionAttrsLegacyPass() : ModulePass(ID) { 62 initializeInferFunctionAttrsLegacyPassPass( 63 *PassRegistry::getPassRegistry()); 64 } 65 66 void getAnalysisUsage(AnalysisUsage &AU) const override { 67 AU.addRequired<TargetLibraryInfoWrapperPass>(); 68 } 69 70 bool runOnModule(Module &M) override { 71 if (skipModule(M)) 72 return false; 73 74 auto GetTLI = [this](Function &F) -> TargetLibraryInfo & { 75 return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 76 }; 77 return inferAllPrototypeAttributes(M, GetTLI); 78 } 79 }; 80 } 81 82 char InferFunctionAttrsLegacyPass::ID = 0; 83 INITIALIZE_PASS_BEGIN(InferFunctionAttrsLegacyPass, "inferattrs", 84 "Infer set function attributes", false, false) 85 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 86 INITIALIZE_PASS_END(InferFunctionAttrsLegacyPass, "inferattrs", 87 "Infer set function attributes", false, false) 88 89 Pass *llvm::createInferFunctionAttrsLegacyPass() { 90 return new InferFunctionAttrsLegacyPass(); 91 } 92