Index: include/llvm/CodeGen/Passes.h =================================================================== --- include/llvm/CodeGen/Passes.h +++ include/llvm/CodeGen/Passes.h @@ -43,6 +43,9 @@ /// the entry block. FunctionPass *createUnreachableBlockEliminationPass(); + /// Insert mcount-like function calls. + FunctionPass *createCountingFunctionInserterPass(); + /// MachineFunctionPrinter pass - This pass prints out the machine function to /// the given stream as a debugging tool. MachineFunctionPass * Index: include/llvm/InitializePasses.h =================================================================== --- include/llvm/InitializePasses.h +++ include/llvm/InitializePasses.h @@ -89,6 +89,7 @@ void initializeCallGraphViewerPass(PassRegistry&); void initializeCallGraphWrapperPassPass(PassRegistry &); void initializeCodeGenPreparePass(PassRegistry&); +void initializeCountingFunctionInserterPass(PassRegistry&); void initializeConstantHoistingLegacyPassPass(PassRegistry&); void initializeConstantMergeLegacyPassPass(PassRegistry &); void initializeConstantPropagationPass(PassRegistry&); Index: include/llvm/LinkAllPasses.h =================================================================== --- include/llvm/LinkAllPasses.h +++ include/llvm/LinkAllPasses.h @@ -159,6 +159,7 @@ (void) llvm::createInstCountPass(); (void) llvm::createConstantHoistingPass(); (void) llvm::createCodeGenPreparePass(); + (void) llvm::createCountingFunctionInserterPass(); (void) llvm::createEarlyCSEPass(); (void) llvm::createGVNHoistPass(); (void) llvm::createMergedLoadStoreMotionPass(); Index: lib/CodeGen/CMakeLists.txt =================================================================== --- lib/CodeGen/CMakeLists.txt +++ lib/CodeGen/CMakeLists.txt @@ -10,6 +10,7 @@ CallingConvLower.cpp CodeGen.cpp CodeGenPrepare.cpp + CountingFunctionInserter.cpp CriticalAntiDepBreaker.cpp DeadMachineInstructionElim.cpp DetectDeadLanes.cpp Index: lib/CodeGen/CodeGen.cpp =================================================================== --- lib/CodeGen/CodeGen.cpp +++ lib/CodeGen/CodeGen.cpp @@ -23,6 +23,7 @@ initializeAtomicExpandPass(Registry); initializeBranchFolderPassPass(Registry); initializeCodeGenPreparePass(Registry); + initializeCountingFunctionInserterPass(Registry); initializeDeadMachineInstructionElimPass(Registry); initializeDetectDeadLanesPass(Registry); initializeDwarfEHPreparePass(Registry); Index: lib/CodeGen/CountingFunctionInserter.cpp =================================================================== --- /dev/null +++ lib/CodeGen/CountingFunctionInserter.cpp @@ -0,0 +1,61 @@ +//===- CountingFunctionInserter.cpp - Insert mcount-like function calls ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Insert calls to counter functions, such as mcount, intended to be called +// once per function, at the beginning of each function. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Type.h" +#include "llvm/Pass.h" +using namespace llvm; + +namespace { + struct CountingFunctionInserter : public FunctionPass { + static char ID; // Pass identification, replacement for typeid + CountingFunctionInserter() : FunctionPass(ID) { + initializeCountingFunctionInserterPass(*PassRegistry::getPassRegistry()); + } + + void getAnalysisUsage(AnalysisUsage &Info) const override { + Info.setPreservesAll(); + } + + bool runOnFunction(Function &F) override { + std::string CountingFunctionName = + F.getFnAttribute("counting-function").getValueAsString(); + if (CountingFunctionName.empty()) + return false; + + Type *VoidTy = Type::getVoidTy(F.getContext()); + Constant *CountingFn = + F.getParent()->getOrInsertFunction(CountingFunctionName, + VoidTy, nullptr); + CallInst::Create(CountingFn, "", &*F.begin()->getFirstInsertionPt()); + return true; + } + }; + + char CountingFunctionInserter::ID = 0; +} + +INITIALIZE_PASS(CountingFunctionInserter, "cfinserter", + "Inserts calls to mcount-like functions", false, false) + +//===----------------------------------------------------------------------===// +// +// CountingFunctionInserter - Give any unnamed non-void instructions "tmp" names. +// +FunctionPass *llvm::createCountingFunctionInserterPass() { + return new CountingFunctionInserter(); +} Index: lib/CodeGen/TargetPassConfig.cpp =================================================================== --- lib/CodeGen/TargetPassConfig.cpp +++ lib/CodeGen/TargetPassConfig.cpp @@ -469,6 +469,9 @@ if (getOptLevel() != CodeGenOpt::None && !DisablePartialLibcallInlining) addPass(createPartiallyInlineLibCallsPass()); + + // Insert calls to mcount-like functions. + addPass(createCountingFunctionInserterPass()); } /// Turn exception handling constructs into something the code generators can Index: test/CodeGen/PowerPC/mcount-insertion.ll =================================================================== --- /dev/null +++ test/CodeGen/PowerPC/mcount-insertion.ll @@ -0,0 +1,16 @@ +; RUN: llc < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-bgq-linux" + +define void @test1() #0 { +entry: + ret void + +; CHECK-LABEL: @test1 +; CHECK: bl mcount +; CHECK-NOT: mcount +; CHECK: blr +} + +attributes #0 = { "counting-function"="mcount" } + Index: test/Transforms/CountingFunctionInserter/mcount.ll =================================================================== --- /dev/null +++ test/Transforms/CountingFunctionInserter/mcount.ll @@ -0,0 +1,27 @@ +; RUN: opt -S -cfinserter < %s | FileCheck %s +target datalayout = "E-m:e-i64:64-n32:64" +target triple = "powerpc64-bgq-linux" + +define void @test1() #0 { +entry: + ret void + +; CHECK-LABEL: define void @test1() +; CHECK: entry: +; CHECK-NEXT: call void @mcount() +; CHECK: ret void +} + +define void @test2() #1 { +entry: + ret void + +; CHECK-LABEL: define void @test2() +; CHECK: entry: +; CHECK-NEXT: call void @.mcount() +; CHECK: ret void +} + +attributes #0 = { "counting-function"="mcount" } +attributes #1 = { "counting-function"=".mcount" } + Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -246,6 +246,7 @@ initializeCodeGen(*Registry); initializeLoopStrengthReducePass(*Registry); initializeLowerIntrinsicsPass(*Registry); + initializeCountingFunctionInserterPass(*Registry); initializeUnreachableBlockElimLegacyPassPass(*Registry); // Register the target printer for --version. Index: tools/opt/opt.cpp =================================================================== --- tools/opt/opt.cpp +++ tools/opt/opt.cpp @@ -369,6 +369,7 @@ initializePreISelIntrinsicLoweringLegacyPassPass(Registry); initializeGlobalMergePass(Registry); initializeInterleavedAccessPass(Registry); + initializeCountingFunctionInserterPass(Registry); initializeUnreachableBlockElimLegacyPassPass(Registry); #ifdef LINK_POLLY_INTO_TOOLS