Skip to content

Commit edd71db

Browse files
committed
BPF: avoid duplicated globals for CORE relocations
This patch fixed two issues related with relocation globals. In LLVM, if a global, e.g. with name "g", is created and conflict with another global with the same name, LLVM will rename the global, e.g., with a new name "g.2". Since relocation global name has special meaning, we do not want llvm to change it, so internally we have logic to check whether duplication happens or not. If happens, just reuse the previous global. The first bug is related to non-btf-id relocation (BPFAbstractMemberAccess.cpp). Commit 54d9f74 ("BPF: move AbstractMemberAccess and PreserveDIType passes to EP_EarlyAsPossible") changed ModulePass to FunctionPass, i.e., handling each function at a time. But still just one BPFAbstractMemberAccess object is created so module level de-duplication still possible. Commit 40251fe ("[BPF][NewPM] Make BPFTargetMachine properly adjust NPM optimizer pipeline") made a change to create a BPFAbstractMemberAccess object per function so module level de-duplication is not possible any more without going through all module globals. This patch simply changed the map which holds reloc globals as class static, so it will be available to all BPFAbstractMemberAccess objects for different functions. The second bug is related to btf-id relocation (BPFPreserveDIType.cpp). Before Commit 54d9f74, the pass is a ModulePass, so we have a local variable, incremented for each instance, and works fine. But after Commit 54d9f74, the pass becomes a FunctionPass. Local variable won't work properly since different functions will start with the same initial value. Fix the issue by change the local count variable as static, so it will be truely unique across the whole module compilation. Differential Revision: https://reviews.llvm.org/D88942
1 parent 0c009e0 commit edd71db

File tree

4 files changed

+207
-2
lines changed

4 files changed

+207
-2
lines changed

llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class BPFAbstractMemberAccess final {
141141
const DataLayout *DL = nullptr;
142142
Module *M = nullptr;
143143

144-
std::map<std::string, GlobalVariable *> GEPGlobals;
144+
static std::map<std::string, GlobalVariable *> GEPGlobals;
145145
// A map to link preserve_*_access_index instrinsic calls.
146146
std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
147147
// A map to hold all the base preserve_*_access_index instrinsic calls.
@@ -179,6 +179,8 @@ class BPFAbstractMemberAccess final {
179179
bool transformGEPChain(CallInst *Call, CallInfo &CInfo);
180180
};
181181

182+
std::map<std::string, GlobalVariable *> BPFAbstractMemberAccess::GEPGlobals;
183+
182184
class BPFAbstractMemberAccessLegacyPass final : public FunctionPass {
183185
BPFTargetMachine *TM;
184186

llvm/lib/Target/BPF/BPFPreserveDIType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static bool BPFPreserveDITypeImpl(Function &F) {
6868
return false;
6969

7070
std::string BaseName = "llvm.btf_type_id.";
71-
int Count = 0;
71+
static int Count = 0;
7272
for (auto Call : PreserveDITypeCalls) {
7373
const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(1));
7474
assert(Flag);
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
; RUN: opt -O2 -mtriple=bpf-pc-linux %s | llvm-dis > %t1
2+
; RUN: llc -o - %t1 | FileCheck %s
3+
; RUN: opt -passes='default<O2>' -mtriple=bpf-pc-linux %s | llvm-dis > %t1
4+
; RUN: llc -o - %t1 | FileCheck %s
5+
;
6+
; Source:
7+
; struct s1 { int a; int b; };
8+
; int foo(struct s1 *arg) { return __builtin_btf_type_id(*arg, 0); }
9+
; int bar(struct s1 *arg) { return __builtin_btf_type_id(*arg, 0); }
10+
; Compilation flag:
11+
; clang -target bpf -O2 -S -emit-llvm -g -Xclang -disable-llvm-passes test.c
12+
13+
%struct.s1 = type { i32, i32 }
14+
15+
; Function Attrs: nounwind
16+
define dso_local i32 @foo(%struct.s1* %arg) #0 !dbg !7 {
17+
entry:
18+
%arg.addr = alloca %struct.s1*, align 8
19+
store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
20+
call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !17, metadata !DIExpression()), !dbg !22
21+
%0 = call i32 @llvm.bpf.btf.type.id(i32 0, i64 0), !dbg !23, !llvm.preserve.access.index !12
22+
ret i32 %0, !dbg !24
23+
}
24+
25+
; Function Attrs: nounwind readnone speculatable willreturn
26+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
27+
28+
; Function Attrs: nounwind readnone
29+
declare i32 @llvm.bpf.btf.type.id(i32, i64) #2
30+
31+
; Function Attrs: nounwind
32+
define dso_local i32 @bar(%struct.s1* %arg) #0 !dbg !25 {
33+
entry:
34+
%arg.addr = alloca %struct.s1*, align 8
35+
store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
36+
call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !27, metadata !DIExpression()), !dbg !28
37+
%0 = call i32 @llvm.bpf.btf.type.id(i32 1, i64 0), !dbg !29, !llvm.preserve.access.index !12
38+
ret i32 %0, !dbg !30
39+
}
40+
41+
; CHECK: .long 1 # BTF_KIND_STRUCT(id = 2)
42+
43+
; CHECK: .ascii "s1" # string offset=1
44+
; CHECK: .ascii ".text" # string offset=20
45+
; CHECK: .byte 48 # string offset=26
46+
47+
; CHECK: .long 16 # FieldReloc
48+
; CHECK-NEXT: .long 20 # Field reloc section string offset=20
49+
; CHECK-NEXT: .long 2
50+
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
51+
; CHECK-NEXT: .long 2
52+
; CHECK-NEXT: .long 26
53+
; CHECK-NEXT: .long 6
54+
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
55+
; CHECK-NEXT: .long 2
56+
; CHECK-NEXT: .long 26
57+
; CHECK-NEXT: .long 6
58+
59+
attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
60+
attributes #1 = { nounwind readnone speculatable willreturn }
61+
attributes #2 = { nounwind readnone }
62+
63+
!llvm.dbg.cu = !{!0}
64+
!llvm.module.flags = !{!3, !4, !5}
65+
!llvm.ident = !{!6}
66+
67+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git 80a3f7beebd8caab358ff063526ae2d26467c029)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
68+
!1 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/dup")
69+
!2 = !{}
70+
!3 = !{i32 7, !"Dwarf Version", i32 4}
71+
!4 = !{i32 2, !"Debug Info Version", i32 3}
72+
!5 = !{i32 1, !"wchar_size", i32 4}
73+
!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 80a3f7beebd8caab358ff063526ae2d26467c029)"}
74+
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
75+
!8 = !DISubroutineType(types: !9)
76+
!9 = !{!10, !11}
77+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
78+
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
79+
!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 1, size: 64, elements: !13)
80+
!13 = !{!14, !15}
81+
!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 1, baseType: !10, size: 32)
82+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 1, baseType: !10, size: 32, offset: 32)
83+
!16 = !{!17}
84+
!17 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 2, type: !11)
85+
!18 = !{!19, !19, i64 0}
86+
!19 = !{!"any pointer", !20, i64 0}
87+
!20 = !{!"omnipotent char", !21, i64 0}
88+
!21 = !{!"Simple C/C++ TBAA"}
89+
!22 = !DILocation(line: 2, column: 20, scope: !7)
90+
!23 = !DILocation(line: 2, column: 34, scope: !7)
91+
!24 = !DILocation(line: 2, column: 27, scope: !7)
92+
!25 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !26)
93+
!26 = !{!27}
94+
!27 = !DILocalVariable(name: "arg", arg: 1, scope: !25, file: !1, line: 3, type: !11)
95+
!28 = !DILocation(line: 3, column: 20, scope: !25)
96+
!29 = !DILocation(line: 3, column: 34, scope: !25)
97+
!30 = !DILocation(line: 3, column: 27, scope: !25)
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
; RUN: opt -O2 -mtriple=bpf-pc-linux %s | llvm-dis > %t1
2+
; RUN: llc -o - %t1 | FileCheck %s
3+
; RUN: opt -passes='default<O2>' -mtriple=bpf-pc-linux %s | llvm-dis > %t1
4+
; RUN: llc -o - %t1 | FileCheck %s
5+
;
6+
; Source:
7+
; struct s1 { int a; int b; } __attribute__((preserve_access_index));
8+
; int foo(struct s1 *arg) { return arg->a; }
9+
; int bar(struct s1 *arg) { return arg->a; }
10+
; Compilation flag:
11+
; clang -target bpf -O2 -S -emit-llvm -g -Xclang -disable-llvm-passes test.c
12+
13+
%struct.s1 = type { i32, i32 }
14+
15+
; Function Attrs: nounwind
16+
define dso_local i32 @foo(%struct.s1* %arg) #0 !dbg !7 {
17+
entry:
18+
%arg.addr = alloca %struct.s1*, align 8
19+
store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
20+
call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !17, metadata !DIExpression()), !dbg !22
21+
%0 = load %struct.s1*, %struct.s1** %arg.addr, align 8, !dbg !23, !tbaa !18
22+
%1 = call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %0, i32 0, i32 0), !dbg !24, !llvm.preserve.access.index !12
23+
%2 = load i32, i32* %1, align 4, !dbg !24, !tbaa !25
24+
ret i32 %2, !dbg !28
25+
}
26+
27+
; Function Attrs: nounwind readnone speculatable willreturn
28+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
29+
30+
; Function Attrs: nounwind readnone
31+
declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1*, i32 immarg, i32 immarg) #2
32+
33+
; Function Attrs: nounwind
34+
define dso_local i32 @bar(%struct.s1* %arg) #0 !dbg !29 {
35+
entry:
36+
%arg.addr = alloca %struct.s1*, align 8
37+
store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
38+
call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !31, metadata !DIExpression()), !dbg !32
39+
%0 = load %struct.s1*, %struct.s1** %arg.addr, align 8, !dbg !33, !tbaa !18
40+
%1 = call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1* %0, i32 0, i32 0), !dbg !34, !llvm.preserve.access.index !12
41+
%2 = load i32, i32* %1, align 4, !dbg !34, !tbaa !25
42+
ret i32 %2, !dbg !35
43+
}
44+
45+
; CHECK: .long 1 # BTF_KIND_STRUCT(id = 2)
46+
47+
; CHECK: .ascii "s1" # string offset=1
48+
; CHECK: .ascii ".text" # string offset=20
49+
; CHECK: .ascii "0:0" # string offset=26
50+
51+
; CHECK: .long 16 # FieldReloc
52+
; CHECK-NEXT: .long 20 # Field reloc section string offset=20
53+
; CHECK-NEXT: .long 2
54+
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
55+
; CHECK-NEXT: .long 2
56+
; CHECK-NEXT: .long 26
57+
; CHECK-NEXT: .long 0
58+
; CHECK-NEXT: .long .Ltmp{{[0-9]+}}
59+
; CHECK-NEXT: .long 2
60+
; CHECK-NEXT: .long 26
61+
; CHECK-NEXT: .long 0
62+
63+
attributes #0 = { nounwind "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
64+
attributes #1 = { nounwind readnone speculatable willreturn }
65+
attributes #2 = { nounwind readnone }
66+
67+
!llvm.dbg.cu = !{!0}
68+
!llvm.module.flags = !{!3, !4, !5}
69+
!llvm.ident = !{!6}
70+
71+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git 2f40e20613758b3e11a15494c09f4b6973673d6b)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
72+
!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
73+
!2 = !{}
74+
!3 = !{i32 7, !"Dwarf Version", i32 4}
75+
!4 = !{i32 2, !"Debug Info Version", i32 3}
76+
!5 = !{i32 1, !"wchar_size", i32 4}
77+
!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 2f40e20613758b3e11a15494c09f4b6973673d6b)"}
78+
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !16)
79+
!8 = !DISubroutineType(types: !9)
80+
!9 = !{!10, !11}
81+
!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
82+
!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
83+
!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 1, size: 64, elements: !13)
84+
!13 = !{!14, !15}
85+
!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 1, baseType: !10, size: 32)
86+
!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 1, baseType: !10, size: 32, offset: 32)
87+
!16 = !{!17}
88+
!17 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 2, type: !11)
89+
!18 = !{!19, !19, i64 0}
90+
!19 = !{!"any pointer", !20, i64 0}
91+
!20 = !{!"omnipotent char", !21, i64 0}
92+
!21 = !{!"Simple C/C++ TBAA"}
93+
!22 = !DILocation(line: 2, column: 20, scope: !7)
94+
!23 = !DILocation(line: 2, column: 34, scope: !7)
95+
!24 = !DILocation(line: 2, column: 39, scope: !7)
96+
!25 = !{!26, !27, i64 0}
97+
!26 = !{!"s1", !27, i64 0, !27, i64 4}
98+
!27 = !{!"int", !20, i64 0}
99+
!28 = !DILocation(line: 2, column: 27, scope: !7)
100+
!29 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !30)
101+
!30 = !{!31}
102+
!31 = !DILocalVariable(name: "arg", arg: 1, scope: !29, file: !1, line: 3, type: !11)
103+
!32 = !DILocation(line: 3, column: 20, scope: !29)
104+
!33 = !DILocation(line: 3, column: 34, scope: !29)
105+
!34 = !DILocation(line: 3, column: 39, scope: !29)
106+
!35 = !DILocation(line: 3, column: 27, scope: !29)

0 commit comments

Comments
 (0)