forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[InstrProfiling] Ensure data variables are always created for inlined…
… functions (llvm#72069) Fixes a bug introduced by commit f95b2f1 ("Reland [InstrProf][compiler-rt] Enable MC/DC Support in LLVM Source-based Code Coverage (1/3)") The InstrProfiling pass was refactored when introducing support for MC/DC such that the creation of the data variable was abstracted and called only once per function from ::run(). Because ::run() only iterated over functions there were not fully inlined, and because it only created the data variable for the first intrinsic that it saw, data variables corresponding to functions fully inlined into other instrumented callers would end up without a data variable, resulting in loss of coverage information. This patch does the following: 1.) Move the call of createDataVariable() to getOrCreateRegionCounters() so that the creation of the data variable will happen indirectly either from ::new() or during profile intrinsic lowering when it is needed. This effectively restores the behavior prior to the refactor and ensures that all data variables are created when needed (and not duplicated). 2.) Process all MC/DC bitmap parameter intrinsics in ::run() prior to calling getOrCreateRegionCounters(). This ensures bitmap regions are created for each function including functions that are fully inlined. It also ensures that the bitmap region is created for each function prior to the creation of the data variable because it is referenced by the data variable. Again, duplication is prevented if the same parameter intrinsic is inlined into multiple functions. 3.) No longer pass the MC/DC intrinsic to createDataVariable(). This decouples the creation of the data variable from a specific MC/DC intrinsic. Instead, with #2 above, store the number of bitmap bytes required in the PerFunctionProfileData in the ProfileDataMap along with the function's CounterRegion and BitmapRegion variables. This ties the bitmap information directly to the function to which it belongs, and the data variable created for that function can reference that.
- Loading branch information
Showing
3 changed files
with
58 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
llvm/test/Instrumentation/InstrProfiling/inline-data-var-create.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
;; Check that all data variables are created for instrumented functions even | ||
;; when those functions are fully inlined into their instrumented callers prior | ||
;; to the instrprof pass. | ||
; RUN: opt %s -passes='instrprof' -S | FileCheck %s -check-prefix=NOINLINE | ||
; RUN: opt %s -passes='cgscc(inline),instrprof' -S | FileCheck %s -check-prefix=INLINEFIRST | ||
; RUN: opt %s -passes='instrprof,cgscc(inline)' -S | FileCheck %s -check-prefix=INLINEAFTER | ||
|
||
target triple = "x86_64-unknown-linux-gnu" | ||
|
||
; INLINEFIRST: @__profd_foo = private global{{.*}}zeroinitializer, i32 21 | ||
; INLINEFIRST: @__profd_bar = private global{{.*}}zeroinitializer, i32 23 | ||
; INLINEFIRST: @__profd_foobar = private global{{.*}}zeroinitializer, i32 99 | ||
|
||
; INLINEAFTER: @__profd_foobar = private global{{.*}}zeroinitializer, i32 99 | ||
; INLINEAFTER: @__profd_foo = private global{{.*}}zeroinitializer, i32 21 | ||
; INLINEAFTER: @__profd_bar = private global{{.*}}zeroinitializer, i32 23 | ||
|
||
; NOINLINE: @__profd_foobar = private global{{.*}}zeroinitializer, i32 99 | ||
; NOINLINE: @__profd_foo = private global{{.*}}zeroinitializer, i32 21 | ||
; NOINLINE: @__profd_bar = private global{{.*}}zeroinitializer, i32 23 | ||
|
||
declare void @llvm.instrprof.increment(ptr %0, i64 %1, i32 %2, i32 %3) | ||
declare void @llvm.instrprof.mcdc.parameters(ptr %0, i64 %1, i32 %2) | ||
@__profn_foobar = private constant [6 x i8] c"foobar" | ||
@__profn_foo = private constant [3 x i8] c"foo" | ||
@__profn_bar = private constant [3 x i8] c"bar" | ||
|
||
define internal void @foobar() { | ||
call void @llvm.instrprof.increment(ptr @__profn_foobar, i64 123456, i32 32, i32 0) | ||
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foobar, i64 123456, i32 99) | ||
|
||
ret void | ||
} | ||
|
||
define void @foo() { | ||
call void @llvm.instrprof.increment(ptr @__profn_foo, i64 123456, i32 32, i32 0) | ||
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_foo, i64 123456, i32 21) | ||
call void @foobar() | ||
ret void | ||
} | ||
|
||
define void @bar() { | ||
call void @llvm.instrprof.increment(ptr @__profn_bar, i64 123456, i32 32, i32 0) | ||
call void @llvm.instrprof.mcdc.parameters(ptr @__profn_bar, i64 123456, i32 23) | ||
call void @foobar() | ||
ret void | ||
} |