[llvm] edd71db - BPF: avoid duplicated globals for CORE relocations

Yonghong Song via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 6 22:42:11 PDT 2020


Author: Yonghong Song
Date: 2020-10-06T22:37:49-07:00
New Revision: edd71db38b0c2292e6a36fb789a3ec3cbde6a023

URL: https://github.com/llvm/llvm-project/commit/edd71db38b0c2292e6a36fb789a3ec3cbde6a023
DIFF: https://github.com/llvm/llvm-project/commit/edd71db38b0c2292e6a36fb789a3ec3cbde6a023.diff

LOG: 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 54d9f743c8b0
("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 40251fee0084
("[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 54d9f743c8b0, the pass
is a ModulePass, so we have a local variable, incremented for
each instance, and works fine. But after Commit 54d9f743c8b0,
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

Added: 
    llvm/test/CodeGen/BPF/CORE/btf-id-duplicate.ll
    llvm/test/CodeGen/BPF/CORE/field-reloc-duplicate.ll

Modified: 
    llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
    llvm/lib/Target/BPF/BPFPreserveDIType.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
index d04b0644ac49..cd994a9c8365 100644
--- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
+++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp
@@ -141,7 +141,7 @@ class BPFAbstractMemberAccess final {
   const DataLayout *DL = nullptr;
   Module *M = nullptr;
 
-  std::map<std::string, GlobalVariable *> GEPGlobals;
+  static std::map<std::string, GlobalVariable *> GEPGlobals;
   // A map to link preserve_*_access_index instrinsic calls.
   std::map<CallInst *, std::pair<CallInst *, CallInfo>> AIChain;
   // A map to hold all the base preserve_*_access_index instrinsic calls.
@@ -179,6 +179,8 @@ class BPFAbstractMemberAccess final {
   bool transformGEPChain(CallInst *Call, CallInfo &CInfo);
 };
 
+std::map<std::string, GlobalVariable *> BPFAbstractMemberAccess::GEPGlobals;
+
 class BPFAbstractMemberAccessLegacyPass final : public FunctionPass {
   BPFTargetMachine *TM;
 

diff  --git a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp
index d2e969780786..75febbe4b138 100644
--- a/llvm/lib/Target/BPF/BPFPreserveDIType.cpp
+++ b/llvm/lib/Target/BPF/BPFPreserveDIType.cpp
@@ -68,7 +68,7 @@ static bool BPFPreserveDITypeImpl(Function &F) {
     return false;
 
   std::string BaseName = "llvm.btf_type_id.";
-  int Count = 0;
+  static int Count = 0;
   for (auto Call : PreserveDITypeCalls) {
     const ConstantInt *Flag = dyn_cast<ConstantInt>(Call->getArgOperand(1));
     assert(Flag);

diff  --git a/llvm/test/CodeGen/BPF/CORE/btf-id-duplicate.ll b/llvm/test/CodeGen/BPF/CORE/btf-id-duplicate.ll
new file mode 100644
index 000000000000..070ac3f51763
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/btf-id-duplicate.ll
@@ -0,0 +1,97 @@
+; RUN: opt -O2 -mtriple=bpf-pc-linux %s | llvm-dis > %t1
+; RUN: llc -o - %t1 | FileCheck %s
+; RUN: opt -passes='default<O2>' -mtriple=bpf-pc-linux %s | llvm-dis > %t1
+; RUN: llc -o - %t1 | FileCheck %s
+;
+; Source:
+;   struct s1 { int a; int b; };
+;   int foo(struct s1 *arg) { return __builtin_btf_type_id(*arg, 0); }
+;   int bar(struct s1 *arg) { return __builtin_btf_type_id(*arg, 0); }
+; Compilation flag:
+;   clang -target bpf -O2 -S -emit-llvm -g -Xclang -disable-llvm-passes test.c
+
+%struct.s1 = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @foo(%struct.s1* %arg) #0 !dbg !7 {
+entry:
+  %arg.addr = alloca %struct.s1*, align 8
+  store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
+  call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !17, metadata !DIExpression()), !dbg !22
+  %0 = call i32 @llvm.bpf.btf.type.id(i32 0, i64 0), !dbg !23, !llvm.preserve.access.index !12
+  ret i32 %0, !dbg !24
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind readnone
+declare i32 @llvm.bpf.btf.type.id(i32, i64) #2
+
+; Function Attrs: nounwind
+define dso_local i32 @bar(%struct.s1* %arg) #0 !dbg !25 {
+entry:
+  %arg.addr = alloca %struct.s1*, align 8
+  store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
+  call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !27, metadata !DIExpression()), !dbg !28
+  %0 = call i32 @llvm.bpf.btf.type.id(i32 1, i64 0), !dbg !29, !llvm.preserve.access.index !12
+  ret i32 %0, !dbg !30
+}
+
+; CHECK:             .long   1                               # BTF_KIND_STRUCT(id = 2)
+
+; CHECK:             .ascii  "s1"                            # string offset=1
+; CHECK:             .ascii  ".text"                         # string offset=20
+; CHECK:             .byte   48                              # string offset=26
+
+; CHECK:             .long   16                              # FieldReloc
+; CHECK-NEXT:        .long   20                              # Field reloc section string offset=20
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   6
+
+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" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+attributes #2 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!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)
+!1 = !DIFile(filename: "test.c", directory: "/home/yhs/work/tests/dup")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 80a3f7beebd8caab358ff063526ae2d26467c029)"}
+!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)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !11}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 1, size: 64, elements: !13)
+!13 = !{!14, !15}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 1, baseType: !10, size: 32)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 1, baseType: !10, size: 32, offset: 32)
+!16 = !{!17}
+!17 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 2, type: !11)
+!18 = !{!19, !19, i64 0}
+!19 = !{!"any pointer", !20, i64 0}
+!20 = !{!"omnipotent char", !21, i64 0}
+!21 = !{!"Simple C/C++ TBAA"}
+!22 = !DILocation(line: 2, column: 20, scope: !7)
+!23 = !DILocation(line: 2, column: 34, scope: !7)
+!24 = !DILocation(line: 2, column: 27, scope: !7)
+!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)
+!26 = !{!27}
+!27 = !DILocalVariable(name: "arg", arg: 1, scope: !25, file: !1, line: 3, type: !11)
+!28 = !DILocation(line: 3, column: 20, scope: !25)
+!29 = !DILocation(line: 3, column: 34, scope: !25)
+!30 = !DILocation(line: 3, column: 27, scope: !25)

diff  --git a/llvm/test/CodeGen/BPF/CORE/field-reloc-duplicate.ll b/llvm/test/CodeGen/BPF/CORE/field-reloc-duplicate.ll
new file mode 100644
index 000000000000..b83f45a6b91a
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/field-reloc-duplicate.ll
@@ -0,0 +1,106 @@
+; RUN: opt -O2 -mtriple=bpf-pc-linux %s | llvm-dis > %t1
+; RUN: llc -o - %t1 | FileCheck %s
+; RUN: opt -passes='default<O2>' -mtriple=bpf-pc-linux %s | llvm-dis > %t1
+; RUN: llc -o - %t1 | FileCheck %s
+;
+; Source:
+;   struct s1 { int a; int b; } __attribute__((preserve_access_index));
+;   int foo(struct s1 *arg) { return arg->a; }
+;   int bar(struct s1 *arg) { return arg->a; }
+; Compilation flag:
+;   clang -target bpf -O2 -S -emit-llvm -g -Xclang -disable-llvm-passes test.c
+
+%struct.s1 = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @foo(%struct.s1* %arg) #0 !dbg !7 {
+entry:
+  %arg.addr = alloca %struct.s1*, align 8
+  store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
+  call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !17, metadata !DIExpression()), !dbg !22
+  %0 = load %struct.s1*, %struct.s1** %arg.addr, align 8, !dbg !23, !tbaa !18
+  %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
+  %2 = load i32, i32* %1, align 4, !dbg !24, !tbaa !25
+  ret i32 %2, !dbg !28
+}
+
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.s1s(%struct.s1*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind
+define dso_local i32 @bar(%struct.s1* %arg) #0 !dbg !29 {
+entry:
+  %arg.addr = alloca %struct.s1*, align 8
+  store %struct.s1* %arg, %struct.s1** %arg.addr, align 8, !tbaa !18
+  call void @llvm.dbg.declare(metadata %struct.s1** %arg.addr, metadata !31, metadata !DIExpression()), !dbg !32
+  %0 = load %struct.s1*, %struct.s1** %arg.addr, align 8, !dbg !33, !tbaa !18
+  %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
+  %2 = load i32, i32* %1, align 4, !dbg !34, !tbaa !25
+  ret i32 %2, !dbg !35
+}
+
+; CHECK:             .long   1                               # BTF_KIND_STRUCT(id = 2)
+
+; CHECK:             .ascii  "s1"                            # string offset=1
+; CHECK:             .ascii  ".text"                         # string offset=20
+; CHECK:             .ascii  "0:0"                           # string offset=26
+
+; CHECK:             .long   16                              # FieldReloc
+; CHECK-NEXT:        .long   20                              # Field reloc section string offset=20
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   0
+
+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" }
+attributes #1 = { nounwind readnone speculatable willreturn }
+attributes #2 = { nounwind readnone }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4, !5}
+!llvm.ident = !{!6}
+
+!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)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/core")
+!2 = !{}
+!3 = !{i32 7, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git 2f40e20613758b3e11a15494c09f4b6973673d6b)"}
+!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)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !11}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64)
+!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1", file: !1, line: 1, size: 64, elements: !13)
+!13 = !{!14, !15}
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 1, baseType: !10, size: 32)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 1, baseType: !10, size: 32, offset: 32)
+!16 = !{!17}
+!17 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 2, type: !11)
+!18 = !{!19, !19, i64 0}
+!19 = !{!"any pointer", !20, i64 0}
+!20 = !{!"omnipotent char", !21, i64 0}
+!21 = !{!"Simple C/C++ TBAA"}
+!22 = !DILocation(line: 2, column: 20, scope: !7)
+!23 = !DILocation(line: 2, column: 34, scope: !7)
+!24 = !DILocation(line: 2, column: 39, scope: !7)
+!25 = !{!26, !27, i64 0}
+!26 = !{!"s1", !27, i64 0, !27, i64 4}
+!27 = !{!"int", !20, i64 0}
+!28 = !DILocation(line: 2, column: 27, scope: !7)
+!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)
+!30 = !{!31}
+!31 = !DILocalVariable(name: "arg", arg: 1, scope: !29, file: !1, line: 3, type: !11)
+!32 = !DILocation(line: 3, column: 20, scope: !29)
+!33 = !DILocation(line: 3, column: 34, scope: !29)
+!34 = !DILocation(line: 3, column: 39, scope: !29)
+!35 = !DILocation(line: 3, column: 27, scope: !29)


        


More information about the llvm-commits mailing list