Index: include/llvm/Transforms/InstrProfiling.h =================================================================== --- include/llvm/Transforms/InstrProfiling.h +++ include/llvm/Transforms/InstrProfiling.h @@ -21,6 +21,8 @@ namespace llvm { +class TargetTransformInfo; + /// Instrumenation based profiling lowering pass. This pass lowers /// the profile instrumented code generated by FE or the IR based /// instrumentation pass. @@ -30,11 +32,13 @@ InstrProfiling(const InstrProfOptions &Options) : Options(Options) {} PreservedAnalyses run(Module &M, AnalysisManager &AM); - bool run(Module &M); + bool run(Module &M, + function_ref LookupTTI); private: InstrProfOptions Options; Module *M; + const TargetTransformInfo *TTI; struct PerFunctionProfileData { uint32_t NumValueSites[IPVK_Last + 1]; GlobalVariable *RegionCounters; Index: lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- lib/Transforms/Instrumentation/InstrProfiling.cpp +++ lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -15,6 +15,7 @@ #include "llvm/Transforms/InstrProfiling.h" #include "llvm/ADT/Triple.h" +#include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" @@ -57,26 +58,42 @@ return "Frontend instrumentation-based coverage lowering"; } - bool runOnModule(Module &M) override { return InstrProf.run(M); } + bool runOnModule(Module &M) override { + auto &TTIWP = getAnalysis(); + auto LookupTTI = [&TTIWP](Function &F) { + return &TTIWP.getTTI(F); + }; + return InstrProf.run(M, LookupTTI); + } void getAnalysisUsage(AnalysisUsage &AU) const override { AU.setPreservesCFG(); + AU.addRequired(); } }; } // anonymous namespace PreservedAnalyses InstrProfiling::run(Module &M, AnalysisManager &AM) { - if (!run(M)) + auto &FAM = AM.getResult(M).getManager(); + auto LookupTTI = [&FAM](Function &F) { + return &FAM.getResult(F); + }; + + if (!run(M, LookupTTI)) return PreservedAnalyses::all(); return PreservedAnalyses::none(); } char InstrProfilingLegacyPass::ID = 0; -INITIALIZE_PASS(InstrProfilingLegacyPass, "instrprof", - "Frontend instrumentation-based coverage lowering.", false, - false) +INITIALIZE_PASS_BEGIN( + InstrProfilingLegacyPass, "instrprof", + "Frontend instrumentation-based coverage lowering.", false, false) +INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) +INITIALIZE_PASS_END( + InstrProfilingLegacyPass, "instrprof", + "Frontend instrumentation-based coverage lowering.", false, false) ModulePass * llvm::createInstrProfilingLegacyPass(const InstrProfOptions &Options) { @@ -107,7 +124,8 @@ return getInstrProfCoverageSectionName(isMachO()); } -bool InstrProfiling::run(Module &M) { +bool InstrProfiling::run(Module &M, + function_ref LookupTTI) { bool MadeChange = false; this->M = &M; @@ -134,7 +152,8 @@ static_cast(getOrCreateRegionCounters(FirstProfIncInst)); } - for (Function &F : M) + for (Function &F : M) { + this->TTI = LookupTTI(F); for (BasicBlock &BB : F) for (auto I = BB.begin(), E = BB.end(); I != E;) { auto Instr = I++; @@ -146,6 +165,7 @@ MadeChange = true; } } + } if (GlobalVariable *CoverageNamesVar = M.getNamedGlobal(getCoverageUnusedNamesVarName())) { @@ -165,7 +185,8 @@ return true; } -static Constant *getOrInsertValueProfilingCall(Module &M) { +static Constant *getOrInsertValueProfilingCall(Module &M, + const TargetTransformInfo &TTI) { LLVMContext &Ctx = M.getContext(); auto *ReturnTy = Type::getVoidTy(M.getContext()); Type *ParamTypes[] = { @@ -174,8 +195,16 @@ }; auto *ValueProfilingCallTy = FunctionType::get(ReturnTy, makeArrayRef(ParamTypes), false); - return M.getOrInsertFunction(getInstrProfValueProfFuncName(), - ValueProfilingCallTy); + Constant *Res = M.getOrInsertFunction(getInstrProfValueProfFuncName(), + ValueProfilingCallTy); + Function *FunRes = dyn_cast(Res); + if (!TTI.knownTarget()) + llvm::report_fatal_error("instrprof pass cannot run on unknown target"); + if (TTI.shouldExtI32Param() && FunRes) + FunRes->addAttribute(3, Attribute::ZExt); + else if (TTI.shouldSignExtI32Param() && FunRes) + FunRes->addAttribute(3, Attribute::SExt); + return Res; } void InstrProfiling::computeNumValueSiteCounts(InstrProfValueProfileInst *Ind) { @@ -209,8 +238,13 @@ Value *Args[3] = {Ind->getTargetValue(), Builder.CreateBitCast(DataVar, Builder.getInt8PtrTy()), Builder.getInt32(Index)}; - Ind->replaceAllUsesWith( - Builder.CreateCall(getOrInsertValueProfilingCall(*M), Args)); + CallInst *Call = Builder.CreateCall(getOrInsertValueProfilingCall(*M, *TTI), + Args); + if (TTI->shouldExtI32Param()) + Call->addAttribute(3, Attribute::ZExt); + else if (TTI->shouldSignExtI32Param()) + Call->addAttribute(3, Attribute::SExt); + Ind->replaceAllUsesWith(Call); Ind->eraseFromParent(); } Index: test/Instrumentation/InstrProfiling/icall.ll =================================================================== --- test/Instrumentation/InstrProfiling/icall.ll +++ test/Instrumentation/InstrProfiling/icall.ll @@ -1,10 +1,13 @@ ;; Check that static counters are allocated for value profiler +; RUN: not opt < %s -mtriple=unk-unknown-linux -vp-static-alloc=true -instrprof -S 2>&1 | FileCheck %s --check-prefix=ERROR ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -vp-static-alloc=true -instrprof -S | FileCheck %s --check-prefix=STATIC ; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -vp-static-alloc=true -S | FileCheck %s --check-prefix=STATIC ; RUN: opt < %s -mtriple=x86_64-apple-macosx10.10.0 -vp-static-alloc=false -instrprof -S | FileCheck %s --check-prefix=DYN ; RUN: opt < %s -mtriple=x86_64-unknown-linux -instrprof -vp-static-alloc=false -S | FileCheck %s --check-prefix=DYN +; ERROR: instrprof pass cannot run on unknown target + @__profn_foo = private constant [3 x i8] c"foo"