aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Stellard <thomas.stellard@amd.com>2015-05-01 02:43:13 +0000
committerTom Stellard <thomas.stellard@amd.com>2015-05-01 02:43:13 +0000
commita0a6defa18f648ff296acef7f46d53308c041099 (patch)
tree37f109dd7640b2879b10bba6851c4d49e7cadd48
parentd0505d6ed6a0b587630d26c17bd1704657ece915 (diff)
Merging r232438:
------------------------------------------------------------------------ r232438 | mail | 2015-03-16 19:52:03 -0400 (Mon, 16 Mar 2015) | 6 lines GCOV: Make the exit block placement from r223193 optional By default we want our gcov emission to stay 4.2 compatible, which means we need to continue emit the exit block last by default. We add an option to emit it before the body for users that need it. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_36@236303 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/Transforms/Instrumentation.h4
-rw-r--r--lib/Transforms/Instrumentation/GCOVProfiling.cpp20
-rw-r--r--test/Transforms/GCOVProfiling/return-block.ll23
3 files changed, 33 insertions, 14 deletions
diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h
index 24e3ef783ee..0de2d75c091 100644
--- a/include/llvm/Transforms/Instrumentation.h
+++ b/include/llvm/Transforms/Instrumentation.h
@@ -59,6 +59,10 @@ struct GCOVOptions {
// Emit the name of the function in the .gcda files. This is redundant, as
// the function identifier can be used to find the name from the .gcno file.
bool FunctionNamesInData;
+
+ // Emit the exit block immediately after the start block, rather than after
+ // all of the function body's blocks.
+ bool ExitBlockBeforeBody;
};
ModulePass *createGCOVProfilerPass(const GCOVOptions &Options =
GCOVOptions::getDefault());
diff --git a/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
index cb965fb9a22..ec8e86b777c 100644
--- a/lib/Transforms/Instrumentation/GCOVProfiling.cpp
+++ b/lib/Transforms/Instrumentation/GCOVProfiling.cpp
@@ -47,6 +47,8 @@ using namespace llvm;
static cl::opt<std::string>
DefaultGCOVVersion("default-gcov-version", cl::init("402*"), cl::Hidden,
cl::ValueRequired);
+static cl::opt<bool> DefaultExitBlockBeforeBody("gcov-exit-block-before-body",
+ cl::init(false), cl::Hidden);
GCOVOptions GCOVOptions::getDefault() {
GCOVOptions Options;
@@ -55,6 +57,7 @@ GCOVOptions GCOVOptions::getDefault() {
Options.UseCfgChecksum = false;
Options.NoRedZone = false;
Options.FunctionNamesInData = true;
+ Options.ExitBlockBeforeBody = DefaultExitBlockBeforeBody;
if (DefaultGCOVVersion.size() != 4) {
llvm::report_fatal_error(std::string("Invalid -default-gcov-version: ") +
@@ -312,7 +315,7 @@ namespace {
class GCOVFunction : public GCOVRecord {
public:
GCOVFunction(DISubprogram SP, raw_ostream *os, uint32_t Ident,
- bool UseCfgChecksum)
+ bool UseCfgChecksum, bool ExitBlockBeforeBody)
: SP(SP), Ident(Ident), UseCfgChecksum(UseCfgChecksum), CfgChecksum(0),
ReturnBlock(1, os) {
this->os = os;
@@ -322,11 +325,13 @@ namespace {
uint32_t i = 0;
for (auto &BB : *F) {
- // Skip index 1 (0, 2, 3, 4, ...) because that's assigned to the
- // ReturnBlock.
- bool first = i == 0;
- Blocks.insert(std::make_pair(&BB, GCOVBlock(i++ + !first, os)));
+ // Skip index 1 if it's assigned to the ReturnBlock.
+ if (i == 1 && ExitBlockBeforeBody)
+ ++i;
+ Blocks.insert(std::make_pair(&BB, GCOVBlock(i++, os)));
}
+ if (!ExitBlockBeforeBody)
+ ReturnBlock.Number = i;
std::string FunctionNameAndLine;
raw_string_ostream FNLOS(FunctionNameAndLine);
@@ -469,7 +474,7 @@ static bool functionHasLines(Function *F) {
if (Loc.isUnknown()) continue;
// Artificial lines such as calls to the global constructors.
- if (Loc.getLine() == 0) continue;
+ if (Loc.getLine() == 0) continue;
return true;
}
@@ -513,7 +518,8 @@ void GCOVProfiler::emitProfileNotes() {
EntryBlock.splitBasicBlock(It);
Funcs.push_back(make_unique<GCOVFunction>(SP, &out, FunctionIdent++,
- Options.UseCfgChecksum));
+ Options.UseCfgChecksum,
+ Options.ExitBlockBeforeBody));
GCOVFunction &Func = *Funcs.back();
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
diff --git a/test/Transforms/GCOVProfiling/return-block.ll b/test/Transforms/GCOVProfiling/return-block.ll
index f0be3d21aeb..fce374a0a18 100644
--- a/test/Transforms/GCOVProfiling/return-block.ll
+++ b/test/Transforms/GCOVProfiling/return-block.ll
@@ -1,8 +1,14 @@
; Inject metadata to set the .gcno file location
; RUN: echo '!19 = !{!"%/T/return-block.ll", !0}' > %t1
; RUN: cat %s %t1 > %t2
+
+; By default, the return block is last.
; RUN: opt -insert-gcov-profiling -disable-output %t2
-; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck %s
+; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-LAST %s
+
+; But we can optionally emit it second, to match newer gcc versions.
+; RUN: opt -insert-gcov-profiling -gcov-exit-block-before-body -disable-output %t2
+; RUN: llvm-cov gcov -n -dump %T/return-block.gcno 2>&1 | FileCheck -check-prefix=CHECK -check-prefix=RETURN-SECOND %s
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@@ -58,9 +64,12 @@ attributes #2 = { nounwind }
!17 = !{!"0xb\007\007\000", !1, !4} ; [ DW_TAG_lexical_block ] [return-block.c]
!18 = !MDLocation(line: 9, column: 1, scope: !4)
-; There should be no destination edges for block 1.
-; CHECK: Block : 0 Counter : 0
-; CHECK-NEXT: Destination Edges : 2 (0),
-; CHECK-NEXT: Block : 1 Counter : 0
-; CHECK-NEXT: Source Edges : 4 (0),
-; CHECK-NEXT: Block : 2 Counter : 0
+; There should be no destination edges for the exit block.
+; CHECK: Block : 1 Counter : 0
+; RETURN-LAST: Destination Edges
+; RETURN-SECOND-NOT: Destination Edges
+; CHECK: Block : 2 Counter : 0
+; CHECK: Block : 4 Counter : 0
+; RETURN-LAST-NOT: Destination Edges
+; RETURN-SECOND: Destination Edges
+; CHECK-NOT: Block :