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 if (!F.hasFnAttribute(Attribute::NoBuiltin)) 35 Changed |= inferLibFuncAttributes(F, GetTLI(F)); 36 Changed |= inferAttributesFromOthers(F); 37 } 38 39 return Changed; 40 } 41 42 PreservedAnalyses InferFunctionAttrsPass::run(Module &M, 43 ModuleAnalysisManager &AM) { 44 FunctionAnalysisManager &FAM = 45 AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager(); 46 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & { 47 return FAM.getResult<TargetLibraryAnalysis>(F); 48 }; 49 50 if (!inferAllPrototypeAttributes(M, GetTLI)) 51 // If we didn't infer anything, preserve all analyses. 52 return PreservedAnalyses::all(); 53 54 // Otherwise, we may have changed fundamental function attributes, so clear 55 // out all the passes. 56 return PreservedAnalyses::none(); 57 } 58 59 namespace { 60 struct InferFunctionAttrsLegacyPass : public ModulePass { 61 static char ID; // Pass identification, replacement for typeid 62 InferFunctionAttrsLegacyPass() : ModulePass(ID) { 63 initializeInferFunctionAttrsLegacyPassPass( 64 *PassRegistry::getPassRegistry()); 65 } 66 67 void getAnalysisUsage(AnalysisUsage &AU) const override { 68 AU.addRequired<TargetLibraryInfoWrapperPass>(); 69 } 70 71 bool runOnModule(Module &M) override { 72 if (skipModule(M)) 73 return false; 74 75 auto GetTLI = [this](Function &F) -> TargetLibraryInfo & { 76 return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F); 77 }; 78 return inferAllPrototypeAttributes(M, GetTLI); 79 } 80 }; 81 } 82 83 char InferFunctionAttrsLegacyPass::ID = 0; 84 INITIALIZE_PASS_BEGIN(InferFunctionAttrsLegacyPass, "inferattrs", 85 "Infer set function attributes", false, false) 86 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) 87 INITIALIZE_PASS_END(InferFunctionAttrsLegacyPass, "inferattrs", 88 "Infer set function attributes", false, false) 89 90 Pass *llvm::createInferFunctionAttrsLegacyPass() { 91 return new InferFunctionAttrsLegacyPass(); 92 } 93