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