Add a counter-function insertion pass
authorHal Finkel <hfinkel@anl.gov>
Thu, 1 Sep 2016 09:42:39 +0000 (09:42 +0000)
committerHal Finkel <hfinkel@anl.gov>
Thu, 1 Sep 2016 09:42:39 +0000 (09:42 +0000)
As discussed in https://reviews.llvm.org/D22666, our current mechanism to
support -pg profiling, where we insert calls to mcount(), or some similar
function, is fundamentally broken. We insert these calls in the frontend, which
means they get duplicated when inlining, and so the accumulated execution
counts for the inlined-into functions are wrong.

Because we don't want the presence of these functions to affect optimizaton,
they should be inserted in the backend. Here's a pass which would do just that.
The knowledge of the name of the counting function lives in the frontend, so
we're passing it here as a function attribute. Clang will be updated to use
this mechanism.

Differential Revision: https://reviews.llvm.org/D22825

llvm-svn: 280347

llvm/include/llvm/CodeGen/Passes.h
llvm/include/llvm/InitializePasses.h
llvm/include/llvm/LinkAllPasses.h
llvm/lib/CodeGen/CMakeLists.txt
llvm/lib/CodeGen/CodeGen.cpp
llvm/lib/CodeGen/CountingFunctionInserter.cpp [new file with mode: 0644]
llvm/lib/CodeGen/TargetPassConfig.cpp
llvm/test/CodeGen/PowerPC/mcount-insertion.ll [new file with mode: 0644]
llvm/test/Transforms/CountingFunctionInserter/mcount.ll [new file with mode: 0644]
llvm/tools/llc/llc.cpp
llvm/tools/opt/opt.cpp

index 09e660987482d48516b85d1d8ab30a7ce37fa4d5..94e3c32c92b405fdc05e501394cdd8cfa4843a38 100644 (file)
@@ -43,6 +43,9 @@ namespace llvm {
   /// 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 e3e131cf9ff2bb31029e6f9bfaab91fcb4afc2b8..3c7fc63605dfa7e64c8805977e39145952ad221d 100644 (file)
@@ -92,6 +92,7 @@ void initializeCallGraphPrinterLegacyPassPass(PassRegistry&);
 void initializeCallGraphViewerPass(PassRegistry&);
 void initializeCallGraphWrapperPassPass(PassRegistry &);
 void initializeCodeGenPreparePass(PassRegistry&);
+void initializeCountingFunctionInserterPass(PassRegistry&);
 void initializeConstantHoistingLegacyPassPass(PassRegistry&);
 void initializeConstantMergeLegacyPassPass(PassRegistry &);
 void initializeConstantPropagationPass(PassRegistry&);
index 16c5f5c5c7ce7a5da5a84b881eb52d1505760fbf..4c55f8cfaa7aa4cdda61e435a60c0f4defcdfa0a 100644 (file)
@@ -160,6 +160,7 @@ namespace {
       (void) llvm::createInstCountPass();
       (void) llvm::createConstantHoistingPass();
       (void) llvm::createCodeGenPreparePass();
+      (void) llvm::createCountingFunctionInserterPass();
       (void) llvm::createEarlyCSEPass();
       (void) llvm::createGVNHoistPass();
       (void) llvm::createMergedLoadStoreMotionPass();
index f68bac9856434d2fba1216111e1e244c426476c0..ed86e6e544a9179112cc4a677a318dce13bbfc6a 100644 (file)
@@ -10,6 +10,7 @@ add_llvm_library(LLVMCodeGen
   CallingConvLower.cpp
   CodeGen.cpp
   CodeGenPrepare.cpp
+  CountingFunctionInserter.cpp
   CriticalAntiDepBreaker.cpp
   DeadMachineInstructionElim.cpp
   DetectDeadLanes.cpp
index 5cd43df05d6900bd9a277a1f490b94e8e938797e..59f52ba7954e44acb391577f4cd43aeb74dcbac2 100644 (file)
@@ -23,6 +23,7 @@ void llvm::initializeCodeGen(PassRegistry &Registry) {
   initializeAtomicExpandPass(Registry);
   initializeBranchFolderPassPass(Registry);
   initializeCodeGenPreparePass(Registry);
+  initializeCountingFunctionInserterPass(Registry);
   initializeDeadMachineInstructionElimPass(Registry);
   initializeDetectDeadLanesPass(Registry);
   initializeDwarfEHPreparePass(Registry);
diff --git a/llvm/lib/CodeGen/CountingFunctionInserter.cpp b/llvm/lib/CodeGen/CountingFunctionInserter.cpp
new file mode 100644 (file)
index 0000000..1e46a7a
--- /dev/null
@@ -0,0 +1,62 @@
+//===- 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/Analysis/GlobalsModRef.h"
+#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 &AU) const override {
+      AU.addPreserved<GlobalsAAWrapperPass>();
+    }
+
+    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 1244681592b54bea5c2c8b13521b454d3f9bfad3..782a1d951b5ebde36ed98195c60f6e9bc13ef0f5 100644 (file)
@@ -477,6 +477,9 @@ void TargetPassConfig::addIRPasses() {
 
   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
diff --git a/llvm/test/CodeGen/PowerPC/mcount-insertion.ll b/llvm/test/CodeGen/PowerPC/mcount-insertion.ll
new file mode 100644 (file)
index 0000000..04e8571
--- /dev/null
@@ -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" }
+
diff --git a/llvm/test/Transforms/CountingFunctionInserter/mcount.ll b/llvm/test/Transforms/CountingFunctionInserter/mcount.ll
new file mode 100644 (file)
index 0000000..88297c7
--- /dev/null
@@ -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 d3ef4154c512b05eee071dc265007048bd6bd2ec..865da497bc54906f6741a1b4326d177485eb02c8 100644 (file)
@@ -254,6 +254,7 @@ int main(int argc, char **argv) {
   initializeCodeGen(*Registry);
   initializeLoopStrengthReducePass(*Registry);
   initializeLowerIntrinsicsPass(*Registry);
+  initializeCountingFunctionInserterPass(*Registry);
   initializeUnreachableBlockElimLegacyPassPass(*Registry);
 
   // Register the target printer for --version.
index 02976820c673adb450e9d88d6f7bc3c8e488a7b8..6564d0ae14424f319dbe5ac623b9c6a4760c1fe8 100644 (file)
@@ -384,6 +384,7 @@ int main(int argc, char **argv) {
   initializePreISelIntrinsicLoweringLegacyPassPass(Registry);
   initializeGlobalMergePass(Registry);
   initializeInterleavedAccessPass(Registry);
+  initializeCountingFunctionInserterPass(Registry);
   initializeUnreachableBlockElimLegacyPassPass(Registry);
 
 #ifdef LINK_POLLY_INTO_TOOLS