Skip to content

Commit c0b77e0

Browse files
committed
Revert "Reapply "[llvm] Teach whole program devirtualization about relative vtables""
This reverts commit 09c3bfe.
1 parent 1c5d547 commit c0b77e0

File tree

11 files changed

+10
-458
lines changed

11 files changed

+10
-458
lines changed

llvm/include/llvm/Analysis/TypeMetadataUtils.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ void findDevirtualizableCallsForTypeCheckedLoad(
6666
/// Used for example from GlobalDCE to find an entry in a C++ vtable that
6767
/// matches a vcall offset.
6868
///
69-
/// To support relative vtables, getPointerAtOffset can see through "relative
69+
/// To support Swift vtables, getPointerAtOffset can see through "relative
7070
/// pointers", i.e. (sub-)expressions of the form of:
7171
///
7272
/// @symbol = ... {

llvm/lib/Analysis/ModuleSummaryAnalysis.cpp

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
#include "llvm/ADT/StringRef.h"
2323
#include "llvm/Analysis/BlockFrequencyInfo.h"
2424
#include "llvm/Analysis/BranchProbabilityInfo.h"
25-
#include "llvm/Analysis/ConstantFolding.h"
2625
#include "llvm/Analysis/IndirectCallPromotionAnalysis.h"
2726
#include "llvm/Analysis/LoopInfo.h"
2827
#include "llvm/Analysis/MemoryProfileInfo.h"
@@ -669,8 +668,7 @@ static void computeFunctionSummary(
669668
/// within the initializer.
670669
static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
671670
const Module &M, ModuleSummaryIndex &Index,
672-
VTableFuncList &VTableFuncs,
673-
const GlobalVariable &OrigGV) {
671+
VTableFuncList &VTableFuncs) {
674672
// First check if this is a function pointer.
675673
if (I->getType()->isPointerTy()) {
676674
auto C = I->stripPointerCasts();
@@ -698,42 +696,15 @@ static void findFuncPointers(const Constant *I, uint64_t StartingOffset,
698696
auto Offset = SL->getElementOffset(EI.index());
699697
unsigned Op = SL->getElementContainingOffset(Offset);
700698
findFuncPointers(cast<Constant>(I->getOperand(Op)),
701-
StartingOffset + Offset, M, Index, VTableFuncs, OrigGV);
699+
StartingOffset + Offset, M, Index, VTableFuncs);
702700
}
703701
} else if (auto *C = dyn_cast<ConstantArray>(I)) {
704702
ArrayType *ATy = C->getType();
705703
Type *EltTy = ATy->getElementType();
706704
uint64_t EltSize = DL.getTypeAllocSize(EltTy);
707705
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
708706
findFuncPointers(cast<Constant>(I->getOperand(i)),
709-
StartingOffset + i * EltSize, M, Index, VTableFuncs,
710-
OrigGV);
711-
}
712-
} else if (const auto *CE = dyn_cast<ConstantExpr>(I)) {
713-
// For relative vtables, the next sub-component should be a trunc.
714-
if (CE->getOpcode() != Instruction::Trunc ||
715-
!(CE = dyn_cast<ConstantExpr>(CE->getOperand(0))))
716-
return;
717-
718-
// If this constant can be reduced to the offset between a function and a
719-
// global, then we know this is a valid virtual function if the RHS is the
720-
// original vtable we're scanning through.
721-
if (CE->getOpcode() == Instruction::Sub) {
722-
GlobalValue *LHS, *RHS;
723-
APSInt LHSOffset, RHSOffset;
724-
if (IsConstantOffsetFromGlobal(CE->getOperand(0), LHS, LHSOffset, DL) &&
725-
IsConstantOffsetFromGlobal(CE->getOperand(1), RHS, RHSOffset, DL) &&
726-
RHS == &OrigGV &&
727-
728-
// For relative vtables, this component should point to the callable
729-
// function without any offsets.
730-
LHSOffset == 0 &&
731-
732-
// Also, the RHS should always point to somewhere within the vtable.
733-
RHSOffset <=
734-
static_cast<uint64_t>(DL.getTypeAllocSize(OrigGV.getInitializer()->getType()))) {
735-
findFuncPointers(LHS, StartingOffset, M, Index, VTableFuncs, OrigGV);
736-
}
707+
StartingOffset + i * EltSize, M, Index, VTableFuncs);
737708
}
738709
}
739710
}
@@ -746,7 +717,7 @@ static void computeVTableFuncs(ModuleSummaryIndex &Index,
746717
return;
747718

748719
findFuncPointers(V.getInitializer(), /*StartingOffset=*/0, M, Index,
749-
VTableFuncs, V);
720+
VTableFuncs);
750721

751722
#ifndef NDEBUG
752723
// Validate that the VTableFuncs list is ordered by offset.

llvm/lib/Analysis/TypeMetadataUtils.cpp

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,6 @@ static void findLoadCallsAtConstantOffset(
6767
findLoadCallsAtConstantOffset(M, DevirtCalls, User, Offset + GEPOffset,
6868
CI, DT);
6969
}
70-
} else if (auto *Call = dyn_cast<CallInst>(User)) {
71-
if (Call->getIntrinsicID() == llvm::Intrinsic::load_relative) {
72-
if (auto *LoadOffset = dyn_cast<ConstantInt>(Call->getOperand(1))) {
73-
findCallsAtConstantOffset(DevirtCalls, nullptr, User,
74-
Offset + LoadOffset->getSExtValue(), CI,
75-
DT);
76-
}
77-
}
7870
}
7971
}
8072
}
@@ -139,12 +131,6 @@ void llvm::findDevirtualizableCallsForTypeCheckedLoad(
139131

140132
Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
141133
Constant *TopLevelGlobal) {
142-
// TODO: Ideally it would be the caller who knows if it's appropriate to strip
143-
// the DSOLocalEquicalent. More generally, it would feel more appropriate to
144-
// have two functions that handle absolute and relative pointers separately.
145-
if (auto *Equiv = dyn_cast<DSOLocalEquivalent>(I))
146-
I = Equiv->getGlobalValue();
147-
148134
if (I->getType()->isPointerTy()) {
149135
if (Offset == 0)
150136
return I;
@@ -175,7 +161,7 @@ Constant *llvm::getPointerAtOffset(Constant *I, uint64_t Offset, Module &M,
175161
Offset % ElemSize, M, TopLevelGlobal);
176162
}
177163

178-
// Relative-pointer support starts here.
164+
// (Swift-specific) relative-pointer support starts here.
179165
if (auto *CI = dyn_cast<ConstantInt>(I)) {
180166
if (Offset == 0 && CI->isZero()) {
181167
return I;

llvm/test/ThinLTO/X86/devirt.ll

Lines changed: 3 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -27,36 +27,24 @@
2727
; NOENABLESPLITFLAG-DAG: [[B:\^[0-9]+]] = gv: (name: "_ZTV1B", {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[Bf]], [[An]])
2828
; NOENABLESPLITFLAG-DAG: [[C:\^[0-9]+]] = gv: (name: "_ZTV1C", {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 16), (virtFunc: [[An]], offset: 24)), refs: ([[An]], [[Cf]])
2929
; NOENABLESPLITFLAG-DAG: [[D:\^[0-9]+]] = gv: (name: "_ZTV1D", {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 16)), refs: ([[Dm]])
30-
; NOENABLESPLITFLAG-DAG: [[B_RV:\^[0-9]+]] = gv: (name: "_ZTV1B_RV", {{.*}} vTableFuncs: ((virtFunc: [[Bf]], offset: 8), (virtFunc: [[An]], offset: 12)), refs: ([[B_RV]], [[Bf]], [[An]])
31-
; NOENABLESPLITFLAG-DAG: [[C_RV:\^[0-9]+]] = gv: (name: "_ZTV1C_RV", {{.*}} vTableFuncs: ((virtFunc: [[Cf]], offset: 8), (virtFunc: [[An]], offset: 12)), refs: ([[C_RV]], [[An]], [[Cf]])
32-
; NOENABLESPLITFLAG-DAG: [[D_RV:\^[0-9]+]] = gv: (name: "_ZTV1D_RV", {{.*}} vTableFuncs: ((virtFunc: [[Dm]], offset: 8)), refs: ([[D_RV]], [[Dm]])
3330
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1A", summary: ((offset: 16, [[B]]), (offset: 16, [[C]])))
3431
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1B", summary: ((offset: 16, [[B]])))
3532
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1C", summary: ((offset: 16, [[C]])))
36-
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1A_RV", summary: ((offset: 8, [[B_RV]]), (offset: 8, [[C_RV]])))
37-
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1B_RV", summary: ((offset: 8, [[B_RV]])))
38-
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "_ZTS1C_RV", summary: ((offset: 8, [[C_RV]])))
3933
; Type Id on _ZTV1D should have been promoted
4034
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "1.{{.*}}", summary: ((offset: 16, [[D]])))
41-
; NOENABLESPLITFLAG-DAG: typeidCompatibleVTable: (name: "2.{{.*}}", summary: ((offset: 8, [[D_RV]])))
4235

4336
; Index based WPD
4437
; RUN: llvm-lto2 run %t2.o -save-temps -pass-remarks=. \
4538
; RUN: -whole-program-visibility \
4639
; RUN: -o %t3 \
4740
; RUN: -r=%t2.o,test,px \
48-
; RUN: -r=%t2.o,test_rv,px \
4941
; RUN: -r=%t2.o,_ZN1A1nEi,p \
5042
; RUN: -r=%t2.o,_ZN1B1fEi,p \
5143
; RUN: -r=%t2.o,_ZN1C1fEi,p \
5244
; RUN: -r=%t2.o,_ZN1D1mEi,p \
5345
; RUN: -r=%t2.o,_ZTV1B,px \
5446
; RUN: -r=%t2.o,_ZTV1C,px \
55-
; RUN: -r=%t2.o,_ZTV1D,px \
56-
; RUN: -r=%t2.o,_ZTV1B_RV,px \
57-
; RUN: -r=%t2.o,_ZTV1C_RV,px \
58-
; RUN: -r=%t2.o,_ZTV1D_RV,px \
59-
; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK
47+
; RUN: -r=%t2.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK
6048
; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
6149

6250
; Check that we're able to prevent specific function from being
@@ -66,49 +54,34 @@
6654
; RUN: -wholeprogramdevirt-skip=_ZN1A1nEi \
6755
; RUN: -o %t3 \
6856
; RUN: -r=%t2.o,test,px \
69-
; RUN: -r=%t2.o,test_rv,px \
7057
; RUN: -r=%t2.o,_ZN1A1nEi,p \
7158
; RUN: -r=%t2.o,_ZN1B1fEi,p \
7259
; RUN: -r=%t2.o,_ZN1C1fEi,p \
7360
; RUN: -r=%t2.o,_ZN1D1mEi,p \
7461
; RUN: -r=%t2.o,_ZTV1B,px \
7562
; RUN: -r=%t2.o,_ZTV1C,px \
76-
; RUN: -r=%t2.o,_ZTV1D,px \
77-
; RUN: -r=%t2.o,_ZTV1B_RV,px \
78-
; RUN: -r=%t2.o,_ZTV1C_RV,px \
79-
; RUN: -r=%t2.o,_ZTV1D_RV,px \
80-
; RUN: 2>&1 | FileCheck %s --check-prefix=SKIP
63+
; RUN: -r=%t2.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=SKIP
8164

8265
; RUN: llvm-lto2 run %t.o -save-temps -pass-remarks=. \
8366
; RUN: -whole-program-visibility \
8467
; RUN: -o %t3 \
8568
; RUN: -r=%t.o,test,px \
86-
; RUN: -r=%t.o,test_rv,px \
8769
; RUN: -r=%t.o,_ZN1A1nEi,p \
8870
; RUN: -r=%t.o,_ZN1B1fEi,p \
8971
; RUN: -r=%t.o,_ZN1C1fEi,p \
9072
; RUN: -r=%t.o,_ZN1D1mEi,p \
9173
; RUN: -r=%t.o,_ZTV1B, \
9274
; RUN: -r=%t.o,_ZTV1C, \
9375
; RUN: -r=%t.o,_ZTV1D, \
94-
; RUN: -r=%t.o,_ZTV1B_RV, \
95-
; RUN: -r=%t.o,_ZTV1C_RV, \
96-
; RUN: -r=%t.o,_ZTV1D_RV, \
9776
; RUN: -r=%t.o,_ZN1A1nEi, \
9877
; RUN: -r=%t.o,_ZN1B1fEi, \
9978
; RUN: -r=%t.o,_ZN1C1fEi, \
10079
; RUN: -r=%t.o,_ZN1D1mEi, \
10180
; RUN: -r=%t.o,_ZTV1B,px \
10281
; RUN: -r=%t.o,_ZTV1C,px \
103-
; RUN: -r=%t.o,_ZTV1D,px \
104-
; RUN: -r=%t.o,_ZTV1B_RV,px \
105-
; RUN: -r=%t.o,_ZTV1C_RV,px \
106-
; RUN: -r=%t.o,_ZTV1D_RV,px \
107-
; RUN: 2>&1 | FileCheck %s --check-prefix=REMARK --dump-input=fail
82+
; RUN: -r=%t.o,_ZTV1D,px 2>&1 | FileCheck %s --check-prefix=REMARK --dump-input=fail
10883
; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR
10984

110-
; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
111-
; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
11285
; REMARK-DAG: single-impl: devirtualized a call to _ZN1A1nEi
11386
; REMARK-DAG: single-impl: devirtualized a call to _ZN1D1mEi
11487

@@ -126,25 +99,6 @@ target triple = "x86_64-grtev4-linux-gnu"
12699
@_ZTV1C = constant { [4 x ptr] } { [4 x ptr] [ptr null, ptr undef, ptr @_ZN1C1fEi, ptr @_ZN1A1nEi] }, !type !0, !type !2
127100
@_ZTV1D = constant { [3 x ptr] } { [3 x ptr] [ptr null, ptr undef, ptr @_ZN1D1mEi] }, !type !3
128101

129-
@_ZTV1B_RV = constant { [4 x i32] } { [4 x i32] [
130-
i32 0,
131-
i32 undef,
132-
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1B1fEi to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B_RV, i32 0, i32 0, i32 2) to i64)) to i32),
133-
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A1nEi to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1B_RV, i32 0, i32 0, i32 3) to i64)) to i32)
134-
] }, !type !7, !type !8
135-
136-
@_ZTV1C_RV = constant { [4 x i32] } { [4 x i32] [
137-
i32 0,
138-
i32 undef,
139-
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1C1fEi to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1C_RV, i32 0, i32 0, i32 2) to i64)) to i32),
140-
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1A1nEi to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [4 x i32] }, ptr @_ZTV1C_RV, i32 0, i32 0, i32 3) to i64)) to i32)
141-
] }, !type !7, !type !9
142-
143-
@_ZTV1D_RV = constant { [3 x i32] } { [3 x i32] [
144-
i32 0,
145-
i32 undef,
146-
i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @_ZN1D1mEi to i64), i64 ptrtoint (ptr getelementptr inbounds ({ [3 x i32] }, ptr @_ZTV1D_RV, i32 0, i32 0, i32 2) to i64)) to i32)
147-
] }, !type !10
148102

149103
; CHECK-IR-LABEL: define {{(noundef )?}}i32 @test
150104
define i32 @test(ptr %obj, ptr %obj2, i32 %a) {
@@ -182,43 +136,6 @@ entry:
182136
; CHECK-IR-LABEL: ret i32
183137
; CHECK-IR-LABEL: }
184138

185-
declare ptr @llvm.load.relative.i32(ptr, i32)
186-
187-
; CHECK-IR-LABEL: define i32 @test_rv
188-
define i32 @test_rv(ptr %obj, ptr %obj2, i32 %a) {
189-
entry:
190-
%vtable = load ptr, ptr %obj
191-
%p = call i1 @llvm.type.test(ptr %vtable, metadata !"_ZTS1A_RV")
192-
call void @llvm.assume(i1 %p)
193-
%fptr1_rv = call ptr @llvm.load.relative.i32(ptr %vtable, i32 4)
194-
195-
; Check that the call was devirtualized.
196-
; CHECK-IR: %call = tail call i32 @_ZN1A1nEi
197-
; Ensure !prof and !callees metadata for indirect call promotion removed.
198-
; CHECK-IR-NOT: prof
199-
; CHECK-IR-NOT: callees
200-
%call = tail call i32 %fptr1_rv(ptr nonnull %obj, i32 %a), !prof !5, !callees !6
201-
202-
%fptr22_rv = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0)
203-
204-
; We still have to call it as virtual.
205-
; CHECK-IR: %call3 = tail call i32 %fptr22
206-
%call3 = tail call i32 %fptr22_rv(ptr nonnull %obj, i32 %call)
207-
208-
%vtable2 = load ptr, ptr %obj2
209-
%p2 = call i1 @llvm.type.test(ptr %vtable2, metadata !11)
210-
call void @llvm.assume(i1 %p2)
211-
212-
%fptr33_rv = call ptr @llvm.load.relative.i32(ptr %vtable2, i32 0)
213-
214-
; Check that the call was devirtualized.
215-
; CHECK-IR: %call4 = tail call i32 @_ZN1D1mEi
216-
%call4 = tail call i32 %fptr33_rv(ptr nonnull %obj2, i32 %call3)
217-
ret i32 %call4
218-
}
219-
; CHECK-IR-LABEL: ret i32
220-
; CHECK-IR-LABEL: }
221-
222139
declare i1 @llvm.type.test(ptr, metadata)
223140
declare void @llvm.assume(i1)
224141

@@ -248,9 +165,3 @@ attributes #0 = { noinline optnone }
248165
!4 = distinct !{}
249166
!5 = !{!"VP", i32 0, i64 1, i64 1621563287929432257, i64 1}
250167
!6 = !{ptr @_ZN1A1nEi}
251-
252-
!7 = !{i64 8, !"_ZTS1A_RV"}
253-
!8 = !{i64 8, !"_ZTS1B_RV"}
254-
!9 = !{i64 8, !"_ZTS1C_RV"}
255-
!10 = !{i64 8, !11}
256-
!11 = distinct !{}

llvm/test/Transforms/WholeProgramDevirt/Inputs/export.yaml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,14 @@ GlobalValueMap:
55
TypeTestAssumeVCalls:
66
- GUID: 14276520915468743435 # typeid1
77
Offset: 0
8-
- GUID: 271751036925422857 # typeid1_rv
9-
Offset: 0
108
TypeCheckedLoadVCalls:
119
- GUID: 15427464259790519041 # typeid2
1210
Offset: 0
13-
- GUID: 1146149264729288256 # typeid2_rv
14-
Offset: 0
1511
TypeTestAssumeConstVCalls:
1612
- VFunc:
1713
GUID: 3515965990081467659 # typeid3
1814
Offset: 0
1915
Args: [12, 24]
20-
- VFunc:
21-
GUID: 2777626534618191571 # typeid3_rv
22-
Offset: 0
23-
Args: [12, 24]
2416
TypeCheckedLoadConstVCalls:
2517
- VFunc:
2618
GUID: 17525413373118030901 # typeid4

0 commit comments

Comments
 (0)