summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/CodeGen/CGBlocks.cpp2
-rw-r--r--clang/lib/CodeGen/CGObjC.cpp2
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp2
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp2
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.cpp27
-rw-r--r--clang/lib/CodeGen/CodeGenPGO.h4
-rw-r--r--clang/test/Profile/cxx-structors.cpp32
-rw-r--r--clang/test/Profile/cxx-virtual-destructor-calls.cpp27
9 files changed, 67 insertions, 34 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 87165fe13a4..ba2941e9df4 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1241,7 +1241,7 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
if (IsLambdaConversionToBlock)
EmitLambdaBlockInvokeBody();
else {
- PGO.assignRegionCounters(blockDecl, fn);
+ PGO.assignRegionCounters(GlobalDecl(blockDecl), fn);
incrementProfileCounter(blockDecl->getBody());
EmitStmt(blockDecl->getBody());
}
diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp
index 6865f974fc2..2d5991b71fc 100644
--- a/clang/lib/CodeGen/CGObjC.cpp
+++ b/clang/lib/CodeGen/CGObjC.cpp
@@ -557,7 +557,7 @@ static llvm::Value *emitARCRetainLoadOfScalar(CodeGenFunction &CGF,
/// 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()));
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 5ebcdf654ab..1cbdeffd7c4 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2170,7 +2170,7 @@ CodeGenFunction::GenerateCapturedStmtFunction(const CapturedStmt &S) {
CXXThisValue = EmitLoadOfLValue(ThisLValue, Loc).getScalarVal();
}
- PGO.assignRegionCounters(CD, F);
+ PGO.assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index a6099cabb59..d86cdc7110e 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -185,7 +185,7 @@ CodeGenFunction::GenerateOpenMPCapturedStmtFunction(const CapturedStmt &S) {
++Cnt, ++I;
}
- PGO.assignRegionCounters(CD, F);
+ PGO.assignRegionCounters(GlobalDecl(CD), F);
CapturedStmtInfo->EmitBody(*this, CD->getBody());
FinishFunction(CD->getBodyRBrace());
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 31a93e001f8..048a04328fc 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -957,8 +957,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,
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))
diff --git a/clang/lib/CodeGen/CodeGenPGO.cpp b/clang/lib/CodeGen/CodeGenPGO.cpp
index 403380efcb4..38774332f31 100644
--- a/clang/lib/CodeGen/CodeGenPGO.cpp
+++ b/clang/lib/CodeGen/CodeGenPGO.cpp
@@ -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);
diff --git a/clang/lib/CodeGen/CodeGenPGO.h b/clang/lib/CodeGen/CodeGenPGO.h
index 350cdcce3e8..6bf29ecaa7c 100644
--- a/clang/lib/CodeGen/CodeGenPGO.h
+++ b/clang/lib/CodeGen/CodeGenPGO.h
@@ -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,
diff --git a/clang/test/Profile/cxx-structors.cpp b/clang/test/Profile/cxx-structors.cpp
new file mode 100644
index 00000000000..24c595b863e
--- /dev/null
+++ b/clang/test/Profile/cxx-structors.cpp
@@ -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() {
+}
diff --git a/clang/test/Profile/cxx-virtual-destructor-calls.cpp b/clang/test/Profile/cxx-virtual-destructor-calls.cpp
index 35975c28533..d117c211437 100644
--- a/clang/test/Profile/cxx-virtual-destructor-calls.cpp
+++ b/clang/test/Profile/cxx-virtual-destructor-calls.cpp
@@ -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 must not be instrumented
+// CHECK-NOT: @__llvm_profile_name__ZN1BD0Ev = private constant [9 x i8] c"_ZN1BD0Ev"
-// Deleting dtor counters and profile data
-// CHECK: @__llvm_profile_counters__ZN1BD0Ev = private global [1 x i64] zeroinitializer
-// CHECK: @__llvm_profile_data__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() { }
OpenPOWER on IntegriCloud