r254876 - [PGO] Instrument only base constructors and destructors.

Serge Pavlov via cfe-commits cfe-commits at lists.llvm.org
Sun Dec 6 06:32:40 PST 2015


Author: sepavloff
Date: Sun Dec  6 08:32:39 2015
New Revision: 254876

URL: http://llvm.org/viewvc/llvm-project?rev=254876&view=rev
Log:
[PGO] Instrument only base constructors and destructors.

Constructors and destructors may be represented by several functions
in IR. Only base structors correspond to source code, others are
small pieces of code and eventually call the base variant. In this
case instrumentation of non-base structors has little sense, this
fix remove it. Now profile data of a declaration corresponds to
exactly one function in IR, it agrees with the current logic of the
profile data loading.

This change fixes PR24996.

Differential Revision: http://reviews.llvm.org/D15158

Added:
    cfe/trunk/test/Profile/cxx-structors.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CGStmt.cpp
    cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
    cfe/trunk/lib/CodeGen/CodeGenPGO.h
    cfe/trunk/test/Profile/cxx-virtual-destructor-calls.cpp

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Sun Dec  6 08:32:39 2015
@@ -1241,7 +1241,7 @@ CodeGenFunction::GenerateBlockFunction(G
   if (IsLambdaConversionToBlock)
     EmitLambdaBlockInvokeBody();
   else {
-    PGO.assignRegionCounters(blockDecl, fn);
+    PGO.assignRegionCounters(GlobalDecl(blockDecl), fn);
     incrementProfileCounter(blockDecl->getBody());
     EmitStmt(blockDecl->getBody());
   }

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Dec  6 08:32:39 2015
@@ -557,7 +557,7 @@ static llvm::Value *emitARCRetainLoadOfS
 /// its pointer, name, and types registered in the class struture.
 void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) {
   StartObjCMethod(OMD, OMD->getClassInterface());
-  PGO.assignRegionCounters(OMD, CurFn);
+  PGO.assignRegionCounters(GlobalDecl(OMD), CurFn);
   assert(isa<CompoundStmt>(OMD->getBody()));
   incrementProfileCounter(OMD->getBody());
   EmitCompoundStmtWithoutScope(*cast<CompoundStmt>(OMD->getBody()));

Modified: cfe/trunk/lib/CodeGen/CGStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmt.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmt.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmt.cpp Sun Dec  6 08:32:39 2015
@@ -2170,7 +2170,7 @@ CodeGenFunction::GenerateCapturedStmtFun
     CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
   }
 
-  PGO.assignRegionCounters(CD, F);
+  PGO.assignRegionCounters(GlobalDecl(CD), F);
   CapturedStmtInfo->EmitBody(*this, CD->getBody());
   FinishFunction(CD->getBodyRBrace());
 

Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Sun Dec  6 08:32:39 2015
@@ -185,7 +185,7 @@ CodeGenFunction::GenerateOpenMPCapturedS
     ++Cnt, ++I;
   }
 
-  PGO.assignRegionCounters(CD, F);
+  PGO.assignRegionCounters(GlobalDecl(CD), F);
   CapturedStmtInfo->EmitBody(*this, CD->getBody());
   FinishFunction(CD->getBodyRBrace());
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Dec  6 08:32:39 2015
@@ -957,8 +957,7 @@ void CodeGenFunction::GenerateCode(Globa
   StartFunction(GD, ResTy, Fn, FnInfo, Args, Loc, BodyRange.getBegin());
 
   // Generate the body of the function.
-  PGO.checkGlobalDecl(GD);
-  PGO.assignRegionCounters(GD.getDecl(), CurFn);
+  PGO.assignRegionCounters(GD, CurFn);
   if (isa<CXXDestructorDecl>(FD))
     EmitDestructorBody(Args);
   else if (isa<CXXConstructorDecl>(FD))

Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.cpp Sun Dec  6 08:32:39 2015
@@ -605,27 +605,24 @@ uint64_t PGOHash::finalize() {
   return endian::read<uint64_t, little, unaligned>(Result);
 }
 
-void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) {
-  // Make sure we only emit coverage mapping for one constructor/destructor.
-  // Clang emits several functions for the constructor and the destructor of
-  // a class. Every function is instrumented, but we only want to provide
-  // coverage for one of them. Because of that we only emit the coverage mapping
-  // for the base constructor/destructor.
-  if ((isa<CXXConstructorDecl>(GD.getDecl()) &&
-       GD.getCtorType() != Ctor_Base) ||
-      (isa<CXXDestructorDecl>(GD.getDecl()) &&
-       GD.getDtorType() != Dtor_Base)) {
-    SkipCoverageMapping = true;
-  }
-}
-
-void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
+void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
+  const Decl *D = GD.getDecl();
   bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
   if (!InstrumentRegions && !PGOReader)
     return;
   if (D->isImplicit())
     return;
+  // Constructors and destructors may be represented by several functions in IR.
+  // If so, instrument only base variant, others are implemented by delegation
+  // to the base one, it would be counted twice otherwise.
+  if (CGM.getTarget().getCXXABI().hasConstructorVariants() &&
+      ((isa<CXXConstructorDecl>(GD.getDecl()) &&
+        GD.getCtorType() != Ctor_Base) ||
+       (isa<CXXDestructorDecl>(GD.getDecl()) &&
+        GD.getDtorType() != Dtor_Base))) {
+      return;
+  }
   CGM.ClearUnusedCoverageMapping(D);
   setFuncName(Fn);
 

Modified: cfe/trunk/lib/CodeGen/CodeGenPGO.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenPGO.h?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenPGO.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenPGO.h Sun Dec  6 08:32:39 2015
@@ -78,13 +78,11 @@ public:
       setCurrentRegionCount(*Count);
   }
 
-  /// Check if we need to emit coverage mapping for a given declaration
-  void checkGlobalDecl(GlobalDecl GD);
   /// Assign counters to regions and configure them for PGO of a given
   /// function. Does nothing if instrumentation is not enabled and either
   /// generates global variables or associates PGO data with each of the
   /// counters depending on whether we are generating or using instrumentation.
-  void assignRegionCounters(const Decl *D, llvm::Function *Fn);
+  void assignRegionCounters(GlobalDecl GD, llvm::Function *Fn);
   /// Emit a coverage mapping range with a counter zero
   /// for an unused declaration.
   void emitEmptyCounterMapping(const Decl *D, StringRef FuncName,

Added: cfe/trunk/test/Profile/cxx-structors.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/cxx-structors.cpp?rev=254876&view=auto
==============================================================================
--- cfe/trunk/test/Profile/cxx-structors.cpp (added)
+++ cfe/trunk/test/Profile/cxx-structors.cpp Sun Dec  6 08:32:39 2015
@@ -0,0 +1,32 @@
+// Tests for instrumentation of C++ constructors and destructors.
+//
+// RUN: %clang_cc1 -triple x86_64-apple-macosx10.11.0 -x c++ %s -o - -emit-llvm -fprofile-instr-generate | FileCheck %s
+
+struct Foo {
+  Foo() {}
+  Foo(int) {}
+  ~Foo() {}
+};
+
+struct Bar : public Foo {
+  Bar() {}
+  Bar(int x) : Foo(x) {}
+  ~Bar();
+};
+
+Foo foo;
+Foo foo2(1);
+Bar bar;
+
+// Profile data for complete constructors and destructors must absent.
+
+// CHECK-NOT: @__llvm_profile_name__ZN3FooC1Ev
+// CHECK-NOT: @__llvm_profile_name__ZN3FooC1Ei
+// CHECK-NOT: @__llvm_profile_name__ZN3FooD1Ev
+// CHECK-NOT: @__llvm_profile_name__ZN3BarC1Ev
+// CHECK-NOT: @__llvm_profile_name__ZN3BarD1Ev
+// CHECK-NOT: @__llvm_profile_counters__ZN3FooD1Ev
+// CHECK-NOT: @__llvm_profile_data__ZN3FooD1Ev
+
+int main() {
+}

Modified: cfe/trunk/test/Profile/cxx-virtual-destructor-calls.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Profile/cxx-virtual-destructor-calls.cpp?rev=254876&r1=254875&r2=254876&view=diff
==============================================================================
--- cfe/trunk/test/Profile/cxx-virtual-destructor-calls.cpp (original)
+++ cfe/trunk/test/Profile/cxx-virtual-destructor-calls.cpp Sun Dec  6 08:32:39 2015
@@ -13,18 +13,25 @@ struct B : A {
   virtual ~B();
 };
 
-// Complete dtor
-// CHECK: @__llvm_profile_name__ZN1BD1Ev = private constant [9 x i8] c"_ZN1BD1Ev"
+// Base dtor
+// CHECK: @__llvm_profile_name__ZN1BD2Ev = private constant [9 x i8] c"_ZN1BD2Ev"
 
-// Deleting dtor
-// CHECK: @__llvm_profile_name__ZN1BD0Ev = private constant [9 x i8] c"_ZN1BD0Ev"
+// Complete dtor must not be instrumented
+// CHECK-NOT: @__llvm_profile_name__ZN1BD1Ev = private constant [9 x i8] c"_ZN1BD1Ev"
 
-// Complete dtor counters and profile data
-// CHECK: @__llvm_profile_counters__ZN1BD1Ev = private global [1 x i64] zeroinitializer
-// CHECK: @__llvm_profile_data__ZN1BD1Ev =
-
-// Deleting dtor counters and profile data
-// CHECK: @__llvm_profile_counters__ZN1BD0Ev = private global [1 x i64] zeroinitializer
-// CHECK: @__llvm_profile_data__ZN1BD0Ev =
+// Deleting dtor must not be instrumented
+// CHECK-NOT: @__llvm_profile_name__ZN1BD0Ev = private constant [9 x i8] c"_ZN1BD0Ev"
+
+// Base dtor counters and profile data
+// CHECK: @__llvm_profile_counters__ZN1BD2Ev = private global [1 x i64] zeroinitializer
+// CHECK: @__llvm_profile_data__ZN1BD2Ev =
+
+// Complete dtor counters and profile data must absent
+// CHECK-NOT: @__llvm_profile_counters__ZN1BD1Ev = private global [1 x i64] zeroinitializer
+// CHECK-NOT: @__llvm_profile_data__ZN1BD1Ev =
+
+// Deleting dtor counters and profile data must absent
+// CHECK-NOT: @__llvm_profile_counters__ZN1BD0Ev = private global [1 x i64] zeroinitializer
+// CHECK-NOT: @__llvm_profile_data__ZN1BD0Ev =
 
 B::~B() { }




More information about the cfe-commits mailing list