Skip to content

Commit 979a987

Browse files
[WPD] Change Devirt Cutoff to use DebugCounter (#170009)
This removes the presence of global state from within the pass which is blocking some efforts around test daemonization and is not good design practice in general for LLVM. See https://discourse.llvm.org/t/rfc-reducing-process-creation-overhead-in-llvm-regression-tests/88612/11 for more discussion. This patch replaces the usage of global state with a DebugCounter, which helps fix the global state problem and also increases the flexibility of the option as now an explicit range can be passed. Co-authored-by: Mingming Liu <[email protected]>
1 parent b76cada commit 979a987

File tree

3 files changed

+86
-21
lines changed

3 files changed

+86
-21
lines changed

llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
#include "llvm/IR/ProfDataUtils.h"
100100
#include "llvm/Support/Casting.h"
101101
#include "llvm/Support/CommandLine.h"
102+
#include "llvm/Support/DebugCounter.h"
102103
#include "llvm/Support/Errc.h"
103104
#include "llvm/Support/Error.h"
104105
#include "llvm/Support/FileSystem.h"
@@ -130,6 +131,8 @@ STATISTIC(NumUniqueRetVal, "Number of unique return value optimizations");
130131
STATISTIC(NumVirtConstProp1Bit,
131132
"Number of 1 bit virtual constant propagations");
132133
STATISTIC(NumVirtConstProp, "Number of virtual constant propagations");
134+
DEBUG_COUNTER(CallsToDevirt, "calls-to-devirt",
135+
"Controls how many calls should be devirtualized.");
133136

134137
namespace llvm {
135138

@@ -219,14 +222,6 @@ static cl::opt<bool> WholeProgramDevirtKeepUnreachableFunction(
219222
cl::desc("Regard unreachable functions as possible devirtualize targets."),
220223
cl::Hidden, cl::init(true));
221224

222-
/// If explicitly specified, the devirt module pass will stop transformation
223-
/// once the total number of devirtualizations reach the cutoff value. Setting
224-
/// this option to 0 explicitly will do 0 devirtualization.
225-
static cl::opt<unsigned> WholeProgramDevirtCutoff(
226-
"wholeprogramdevirt-cutoff",
227-
cl::desc("Max number of devirtualizations for devirt module pass"),
228-
cl::init(0));
229-
230225
/// Mechanism to add runtime checking of devirtualization decisions, optionally
231226
/// trapping or falling back to indirect call on any that are not correct.
232227
/// Trapping mode is useful for debugging undefined behavior leading to failures
@@ -377,9 +372,6 @@ VirtualCallTarget::VirtualCallTarget(GlobalValue *Fn, const TypeMemberInfo *TM)
377372

378373
namespace {
379374

380-
// Tracks the number of devirted calls in the IR transformation.
381-
static unsigned NumDevirtCalls = 0;
382-
383375
// A slot in a set of virtual tables. The TypeID identifies the set of virtual
384376
// tables, and the ByteOffset is the offset in bytes from the address point to
385377
// the virtual function pointer.
@@ -1216,15 +1208,13 @@ void DevirtModule::applySingleImplDevirt(VTableSlotInfo &SlotInfo,
12161208
continue;
12171209

12181210
// Stop when the number of devirted calls reaches the cutoff.
1219-
if (WholeProgramDevirtCutoff.getNumOccurrences() > 0 &&
1220-
NumDevirtCalls >= WholeProgramDevirtCutoff)
1221-
return;
1211+
if (!DebugCounter::shouldExecute(CallsToDevirt))
1212+
continue;
12221213

12231214
if (RemarksEnabled)
12241215
VCallSite.emitRemark("single-impl",
12251216
TheFn->stripPointerCasts()->getName(), OREGetter);
12261217
NumSingleImpl++;
1227-
NumDevirtCalls++;
12281218
auto &CB = VCallSite.CB;
12291219
assert(!CB.getCalledFunction() && "devirtualizing direct call?");
12301220
IRBuilder<> Builder(&CB);
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
; REQUIRES: asserts
2+
3+
; Devirt calls debug counter is not explicitly set. Expect 3 remark messages.
4+
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import \
5+
; RUN: -pass-remarks=wholeprogramdevirt \
6+
; RUN: -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml \
7+
; RUN: -print-debug-counter-queries < %s 2>&1 \
8+
; RUN: | grep "remark" | count 3
9+
; Devirt calls debug counter is set to 1. Expect one remark messages.
10+
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import \
11+
; RUN: -pass-remarks=wholeprogramdevirt -debug-counter=calls-to-devirt=0 \
12+
; RUN: -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml \
13+
; RUN: -print-debug-counter-queries < %s 2>&1 \
14+
; RUN: | FileCheck --check-prefix=CHECK-SINGLE %s
15+
; Devirt calls debug counter is set outside the range of calls. Expect no remark message.
16+
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import \
17+
; RUN: -pass-remarks=wholeprogramdevirt -debug-counter=calls-to-devirt=9999 \
18+
; RUN: -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml \
19+
; RUN: -print-debug-counter-queries < %s 2>&1 \
20+
; RUN: | FileCheck -implicit-check-not="remark" --check-prefix=CHECK-NONE %s
21+
22+
; CHECK-SINGLE: DebugCounter calls-to-devirt=0 execute
23+
; CHECK-SINGLE: remark
24+
; CHECK-SINGLE-SAME: devirtualized a call
25+
; CHECK-SINGLE: DebugCounter calls-to-devirt=1 skip
26+
; CHECK-SINGLE: DebugCounter calls-to-devirt=2 skip
27+
28+
; CHECK-NONE: DebugCounter calls-to-devirt=0 skip
29+
; CHECK-NONE: DebugCounter calls-to-devirt=1 skip
30+
; CHECK-NONE: DebugCounter calls-to-devirt=2 skip
31+
32+
target datalayout = "e-p:64:64"
33+
target triple = "x86_64-unknown-linux-gnu"
34+
35+
define i32 @call1(ptr %obj) #0 {
36+
%vtable = load ptr, ptr %obj
37+
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid1")
38+
call void @llvm.assume(i1 %p)
39+
%fptr = load ptr, ptr %vtable
40+
%result = call i32 %fptr(ptr %obj, i32 1)
41+
ret i32 %result
42+
}
43+
44+
define i1 @call2(ptr %obj) #0 {
45+
%vtable = load ptr, ptr %obj
46+
%pair = call {ptr, i1} @llvm.type.checked.load(ptr %vtable, i32 8, metadata !"typeid2")
47+
%fptr = extractvalue {ptr, i1} %pair, 0
48+
%p = extractvalue {ptr, i1} %pair, 1
49+
br i1 %p, label %cont, label %trap
50+
51+
cont:
52+
%result = call i1 %fptr(ptr %obj, i32 undef)
53+
ret i1 %result
54+
55+
trap:
56+
call void @llvm.trap()
57+
unreachable
58+
}
59+
60+
define i1 @call3(ptr %obj) #0 {
61+
%vtable = load ptr, ptr %obj
62+
%pair = call {ptr, i1} @llvm.type.checked.load(ptr %vtable, i32 8, metadata !"typeid2")
63+
%fptr = extractvalue {ptr, i1} %pair, 0
64+
%p = extractvalue {ptr, i1} %pair, 1
65+
br i1 %p, label %cont, label %trap
66+
67+
cont:
68+
%result = call i1 %fptr(ptr %obj, i32 3)
69+
ret i1 %result
70+
71+
trap:
72+
call void @llvm.trap()
73+
unreachable
74+
}
75+
76+
declare void @llvm.assume(i1)
77+
declare void @llvm.trap()
78+
declare {ptr, i1} @llvm.type.checked.load(ptr, i32, metadata)
79+
declare i1 @llvm.type.test(ptr, metadata)
80+
81+
attributes #0 = { "target-features"="+retpoline" }

llvm/test/Transforms/WholeProgramDevirt/import.ll

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@
88
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp-branch-funnel.yaml < %s | FileCheck --check-prefixes=CHECK,VCP,VCP-X86,VCP64,BRANCH-FUNNEL %s
99
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-branch-funnel.yaml < %s | FileCheck --check-prefixes=CHECK,BRANCH-FUNNEL,BRANCH-FUNNEL-NOVCP %s
1010

11-
; Cutoff value is not explicitly set. Expect 3 remark messages.
12-
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml < %s 2>&1 | grep "single-impl" | count 3
13-
; Cutoff value is set to 1. Expect one remark messages.
14-
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-cutoff=1 -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml < %s 2>&1 | grep "single-impl" | count 1
15-
; Cutoff value is explicitly set to zero. Expect no remark message.
16-
; RUN: opt -S -passes=wholeprogramdevirt -wholeprogramdevirt-summary-action=import -pass-remarks=wholeprogramdevirt -wholeprogramdevirt-cutoff=0 -wholeprogramdevirt-read-summary=%S/Inputs/import-single-impl.yaml < %s 2>&1 | FileCheck -implicit-check-not="remark" %s
1711
target datalayout = "e-p:64:64"
1812
target triple = "x86_64-unknown-linux-gnu"
1913

0 commit comments

Comments
 (0)