[llvm] [BPF] Fix CORE optimization bug in BPFMISimplifyPatchable (PR #183446)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 6 11:50:06 PST 2026
https://github.com/yonghong-song updated https://github.com/llvm/llvm-project/pull/183446
>From aa6829c6953469228d7fe851173adb94bb3c7138 Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Wed, 25 Feb 2026 13:29:44 -0800
Subject: [PATCH] [BPF] Fix CORE optimization bug in BPFMISimplifyPatchable
Commit ffd57408efd4 ("[BPF] Enable relocation location for load/store/shifts")
enabled CORE relocation for load/store/shirts. In particular, the commit
did optimization to have load/store/shift insn itself having the relocation.
For the load and store, the optimization has the following:
rX = *(rY + <relocation>) and *(rX + <relocation>) = rY
There is no value-range check for the above '<relocation>'.
For example, if the original '<relocation>' is 0x10006 due to a large
struct, the insn encoding of '<relocaiton>' will be truncated into '6'
and incorrect result will happen.
This patch fixed the issue by checking the value range of '<relocation>'.
If the '<relocation>' is more than INT16_MAX, optimization will be
skipped.
Even llvm side is fixed, libbpf side may still have issues with the
current approach since libbpf may change the value of <relocation>.
If the <relocation> value is more than INT16_MAX, libbpf will either
fail or need to patch insns.
Let us say we have
rX = *(rY + <relocation>) and *(rX + <relocation>) = rY
libbpf will modify '<relocation>' value depending on the actual
offset in kernel data structure. If '<relocation>' is more
than INT16_MAX, more than one insn will be necessary.
llvm could add nop instructions for patch purpose (see [1]).
The following are major patching cases:
case 1: rX = *(rY + <relocation>) // rX and rY are different
rX = <relocation>
rX += rY
rX = *(rX + 0)
case 2: rX = *(rX + <relocation>)
rX += <relocation>
rX = *(rX + 0)
case 3: *(rX + <relocation>) = imm
rX += <relocation>
*(rX + 0) = imm
rX -= <relocation>
case 4: *(rX + <relocation>) = rY // rX and rY are different
rX += <relocation>
*(rX + 0) = rY
rX -= <relocation>
case 5: *(rX + <relocation>) = rX
// We are not able to resolve this issue.
A llvm option (-disable-bpf-core-optimization) is implemented to
disable bpf core optimizaiton, which means the relocation will not
be in load/store insns. This can workaround the above case 5.
[1] https://github.com/llvm/llvm-project/compare/main...yonghong-song:llvm-project:fix-core-overflow-debug
---
.../lib/Target/BPF/BPFMISimplifyPatchable.cpp | 25 +++-
.../CORE/offset-reloc-simplify-patchable-4.ll | 123 ++++++++++++++++++
.../CORE/offset-reloc-simplify-patchable-5.ll | 123 ++++++++++++++++++
3 files changed, 268 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-4.ll
create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-5.ll
diff --git a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
index 9d6de2044b2b6..991998105afec 100644
--- a/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
+++ b/llvm/lib/Target/BPF/BPFMISimplifyPatchable.cpp
@@ -42,6 +42,10 @@ using namespace llvm;
#define DEBUG_TYPE "bpf-mi-simplify-patchable"
+static cl::opt<bool>
+ DisableCOREOptimization("disable-bpf-core-optimization", cl::Hidden,
+ cl::desc("Disable CORE relocation optimization"));
+
namespace {
struct BPFMISimplifyPatchable : public MachineFunctionPass {
@@ -293,9 +297,24 @@ void BPFMISimplifyPatchable::processInst(MachineRegisterInfo *MRI,
return;
}
- if (Opcode == BPF::ADD_rr)
- checkADDrr(MRI, RelocOp, GVal);
- else if (Opcode == BPF::SLL_rr)
+ if (DisableCOREOptimization)
+ return;
+
+ if (Opcode == BPF::ADD_rr) {
+ // If the struct offset is greater than INT16_MAX, skip optimization.
+ StringRef AccessPattern = GVal->getName();
+ size_t FirstDollar = AccessPattern.find_first_of('$');
+ size_t FirstColon = AccessPattern.find_first_of(':');
+ size_t SecondColon = AccessPattern.find_first_of(':', FirstColon + 1);
+ StringRef PatchImmStr =
+ AccessPattern.substr(SecondColon + 1, FirstDollar - SecondColon);
+ int PatchImm = std::stoll(std::string(PatchImmStr));
+ if (PatchImm <= INT16_MAX)
+ checkADDrr(MRI, RelocOp, GVal);
+ return;
+ }
+
+ if (Opcode == BPF::SLL_rr)
checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SLL_ri);
else if (Opcode == BPF::SRA_rr)
checkShift(MRI, *Inst->getParent(), RelocOp, GVal, BPF::SRA_ri);
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-4.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-4.ll
new file mode 100644
index 0000000000000..62e0c2cae0f46
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-4.ll
@@ -0,0 +1,123 @@
+; RUN: llc -mtriple=bpf -filetype=obj -mcpu=v3 %s -o %t
+; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t
+; RUN: %python %p/../BTF/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s
+; RUN: llvm-objdump --no-print-imm-hex -dr --no-show-raw-insn %t | FileCheck --check-prefix=CHECK-DUMP %s
+
+; Source:
+; struct t {
+; char c[40000];
+; int ub;
+; } __attribute__((preserve_access_index));
+; void foo(volatile struct t *t) {
+; t->ub = 1;
+; }
+; int bar(volatile struct t *t) {
+; return t->ub;
+; }
+; Using the following command:
+; clang -g -O2 -mcpu=v3 -S -emit-llvm --target=bpf t.c -o t.ll
+
+@"llvm.t:0:40000$0:1" = external global i64, !llvm.preserve.access.index !0 #0
+
+; Function Attrs: nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none)
+define dso_local void @foo(ptr noundef %0) local_unnamed_addr #1 !dbg !20 {
+ #dbg_value(ptr %0, !26, !DIExpression(), !27)
+ %2 = load i64, ptr @"llvm.t:0:40000$0:1", align 8
+ %3 = getelementptr i8, ptr %0, i64 %2
+ %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 0, ptr %3)
+ store volatile i32 1, ptr %4, align 4, !dbg !28, !tbaa !29
+ ret void, !dbg !31
+}
+
+; Function Attrs: nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none)
+define dso_local i32 @bar(ptr noundef %0) local_unnamed_addr #1 !dbg !32 {
+ #dbg_value(ptr %0, !36, !DIExpression(), !37)
+ %2 = load i64, ptr @"llvm.t:0:40000$0:1", align 8
+ %3 = getelementptr i8, ptr %0, i64 %2
+ %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 1, ptr %3)
+ %5 = load volatile i32, ptr %4, align 4, !dbg !38, !tbaa !29
+ ret i32 %5, !dbg !39
+}
+
+; CHECK-BTF: [1] PTR '(anon)' type_id=2
+; CHECK-BTF-NEXT: [2] VOLATILE '(anon)' type_id=3
+; CHECK-BTF-NEXT: [3] STRUCT 't' size=40004 vlen=2
+; CHECK-BTF-NEXT: 'c' type_id=5 bits_offset=0
+; CHECK-BTF-NEXT: 'ub' type_id=7 bits_offset=320000
+; CHECK-BTF-NEXT: [4] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
+; CHECK-BTF-NEXT: [5] ARRAY '(anon)' type_id=4 index_type_id=6 nr_elems=40000
+; CHECK-BTF-NEXT: [6] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
+; CHECK-BTF-NEXT: [7] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
+; CHECK-BTF-NEXT: [8] FUNC_PROTO '(anon)' ret_type_id=0 vlen=1
+; CHECK-BTF-NEXT: 't' type_id=1
+; CHECK-BTF-NEXT: [9] FUNC 'foo' type_id=8 linkage=global
+; CHECK-BTF-NEXT: [10] FUNC_PROTO '(anon)' ret_type_id=7 vlen=1
+; CHECK-BTF-NEXT: 't' type_id=1
+; CHECK-BTF-NEXT: [11] FUNC 'bar' type_id=10 linkage=global
+
+; CHECK-DUMP: <foo>:
+; CHECK-DUMP-NEXT: 0: r2 = 40000
+; CHECK-DUMP-NEXT: 0000000000000000: CO-RE <byte_off> [3] struct t::ub (0:1)
+; CHECK-DUMP-NEXT: 1: r1 += r2
+; CHECK-DUMP-NEXT: 2: w2 = 1
+; CHECK-DUMP-NEXT: 3: *(u32 *)(r1 + 0) = w2
+; CHECK-DUMP-NEXT: 4: exit
+; CHECK-DUMP: <bar>:
+; CHECK-DUMP-NEXT: 5: r2 = 40000
+; CHECK-DUMP-NEXT: 0000000000000028: CO-RE <byte_off> [3] struct t::ub (0:1)
+; CHECK-DUMP-NEXT: 6: r1 += r2
+; CHECK-DUMP-NEXT: 7: w0 = *(u32 *)(r1 + 0)
+; CHECK-DUMP-NEXT: 8: exit
+
+; Function Attrs: nofree nosync nounwind memory(none)
+declare ptr @llvm.bpf.passthrough.p0.p0(i32, ptr) #2
+
+attributes #0 = { "btf_ama" }
+attributes #1 = { nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="v3" }
+attributes #2 = { nofree nosync nounwind memory(none) }
+
+!llvm.dbg.cu = !{!10}
+!llvm.module.flags = !{!11, !12, !13, !14}
+!llvm.ident = !{!15}
+!llvm.errno.tbaa = !{!16}
+
+!0 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !1, line: 1, size: 320032, elements: !2)
+!1 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/tmp", checksumkind: CSK_MD5, checksum: "80fd4c64ef78a956ea2b9ea665675989")
+!2 = !{!3, !8}
+!3 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !0, file: !1, line: 2, baseType: !4, size: 320000)
+!4 = !DICompositeType(tag: DW_TAG_array_type, baseType: !5, size: 320000, elements: !6)
+!5 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!6 = !{!7}
+!7 = !DISubrange(count: 40000)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "ub", scope: !0, file: !1, line: 3, baseType: !9, size: 32, offset: 320000)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 23.0.0git (https://github.com/llvm/llvm-project.git 11727c11f833873af97d3969483f488e5251f35d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!11 = !{i32 7, !"Dwarf Version", i32 5}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 7, !"frame-pointer", i32 2}
+!14 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!15 = !{!"clang version 23.0.0git (https://github.com/llvm/llvm-project.git 11727c11f833873af97d3969483f488e5251f35d)"}
+!16 = !{!17, !17, i64 0}
+!17 = !{!"int", !18, i64 0}
+!18 = !{!"omnipotent char", !19, i64 0}
+!19 = !{!"Simple C/C++ TBAA"}
+!20 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, type: !21, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !10, retainedNodes: !25, keyInstructions: true)
+!21 = !DISubroutineType(types: !22)
+!22 = !{null, !23}
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64)
+!24 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !0)
+!25 = !{!26}
+!26 = !DILocalVariable(name: "t", arg: 1, scope: !20, file: !1, line: 5, type: !23)
+!27 = !DILocation(line: 0, scope: !20)
+!28 = !DILocation(line: 6, column: 9, scope: !20, atomGroup: 1, atomRank: 1)
+!29 = !{!30, !17, i64 40000}
+!30 = !{!"t", !18, i64 0, !17, i64 40000}
+!31 = !DILocation(line: 7, column: 1, scope: !20, atomGroup: 2, atomRank: 1)
+!32 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 8, type: !33, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !10, retainedNodes: !35, keyInstructions: true)
+!33 = !DISubroutineType(types: !34)
+!34 = !{!9, !23}
+!35 = !{!36}
+!36 = !DILocalVariable(name: "t", arg: 1, scope: !32, file: !1, line: 8, type: !23)
+!37 = !DILocation(line: 0, scope: !32)
+!38 = !DILocation(line: 9, column: 13, scope: !32, atomGroup: 1, atomRank: 2)
+!39 = !DILocation(line: 9, column: 3, scope: !32, atomGroup: 1, atomRank: 1)
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-5.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-5.ll
new file mode 100644
index 0000000000000..ecd0c929524c1
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-simplify-patchable-5.ll
@@ -0,0 +1,123 @@
+; RUN: llc -mtriple=bpf -filetype=obj -mcpu=v3 -disable-bpf-core-optimization %s -o %t
+; RUN: llvm-objcopy --dump-section='.BTF'=%t2 %t
+; RUN: %python %p/../BTF/print_btf.py %t2 | FileCheck -check-prefixes=CHECK-BTF %s
+; RUN: llvm-objdump --no-print-imm-hex -dr --no-show-raw-insn %t | FileCheck --check-prefix=CHECK-DUMP %s
+
+; Source:
+; struct t {
+; char c[40];
+; int ub;
+; } __attribute__((preserve_access_index));
+; void foo(volatile struct t *t) {
+; t->ub = 1;
+; }
+; int bar(volatile struct t *t) {
+; return t->ub;
+; }
+; Using the following command:
+; clang -g -O2 -mcpu=v3 -S -emit-llvm --target=bpf t.c -o t.ll
+
+@"llvm.t:0:40$0:1" = external global i64, !llvm.preserve.access.index !0 #0
+
+; Function Attrs: nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none)
+define dso_local void @foo(ptr noundef %0) local_unnamed_addr #1 !dbg !20 {
+ #dbg_value(ptr %0, !26, !DIExpression(), !27)
+ %2 = load i64, ptr @"llvm.t:0:40$0:1", align 8
+ %3 = getelementptr i8, ptr %0, i64 %2
+ %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 0, ptr %3)
+ store volatile i32 1, ptr %4, align 4, !dbg !28, !tbaa !29
+ ret void, !dbg !31
+}
+
+; Function Attrs: nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none)
+define dso_local i32 @bar(ptr noundef %0) local_unnamed_addr #1 !dbg !32 {
+ #dbg_value(ptr %0, !36, !DIExpression(), !37)
+ %2 = load i64, ptr @"llvm.t:0:40$0:1", align 8
+ %3 = getelementptr i8, ptr %0, i64 %2
+ %4 = tail call ptr @llvm.bpf.passthrough.p0.p0(i32 1, ptr %3)
+ %5 = load volatile i32, ptr %4, align 4, !dbg !38, !tbaa !29
+ ret i32 %5, !dbg !39
+}
+
+; CHECK-BTF: [1] PTR '(anon)' type_id=2
+; CHECK-BTF-NEXT: [2] VOLATILE '(anon)' type_id=3
+; CHECK-BTF-NEXT: [3] STRUCT 't' size=44 vlen=2
+; CHECK-BTF-NEXT: 'c' type_id=5 bits_offset=0
+; CHECK-BTF-NEXT: 'ub' type_id=7 bits_offset=320
+; CHECK-BTF-NEXT: [4] INT 'char' size=1 bits_offset=0 nr_bits=8 encoding=SIGNED
+; CHECK-BTF-NEXT: [5] ARRAY '(anon)' type_id=4 index_type_id=6 nr_elems=40
+; CHECK-BTF-NEXT: [6] INT '__ARRAY_SIZE_TYPE__' size=4 bits_offset=0 nr_bits=32 encoding=(none)
+; CHECK-BTF-NEXT: [7] INT 'int' size=4 bits_offset=0 nr_bits=32 encoding=SIGNED
+; CHECK-BTF-NEXT: [8] FUNC_PROTO '(anon)' ret_type_id=0 vlen=1
+; CHECK-BTF-NEXT: 't' type_id=1
+; CHECK-BTF-NEXT: [9] FUNC 'foo' type_id=8 linkage=global
+; CHECK-BTF-NEXT: [10] FUNC_PROTO '(anon)' ret_type_id=7 vlen=1
+; CHECK-BTF-NEXT: 't' type_id=1
+; CHECK-BTF-NEXT: [11] FUNC 'bar' type_id=10 linkage=global
+
+; CHECK-DUMP: <foo>:
+; CHECK-DUMP-NEXT: 0: r2 = 40
+; CHECK-DUMP-NEXT: 0000000000000000: CO-RE <byte_off> [3] struct t::ub (0:1)
+; CHECK-DUMP-NEXT: 1: r1 += r2
+; CHECK-DUMP-NEXT: 2: w2 = 1
+; CHECK-DUMP-NEXT: 3: *(u32 *)(r1 + 0) = w2
+; CHECK-DUMP-NEXT: 4: exit
+; CHECK-DUMP: <bar>:
+; CHECK-DUMP-NEXT: 5: r2 = 40
+; CHECK-DUMP-NEXT: 0000000000000028: CO-RE <byte_off> [3] struct t::ub (0:1)
+; CHECK-DUMP-NEXT: 6: r1 += r2
+; CHECK-DUMP-NEXT: 7: w0 = *(u32 *)(r1 + 0)
+; CHECK-DUMP-NEXT: 8: exit
+
+; Function Attrs: nofree nosync nounwind memory(none)
+declare ptr @llvm.bpf.passthrough.p0.p0(i32, ptr) #2
+
+attributes #0 = { "btf_ama" }
+attributes #1 = { nofree nounwind memory(readwrite, target_mem0: none, target_mem1: none) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="v3" }
+attributes #2 = { nofree nosync nounwind memory(none) }
+
+!llvm.dbg.cu = !{!10}
+!llvm.module.flags = !{!11, !12, !13, !14}
+!llvm.ident = !{!15}
+!llvm.errno.tbaa = !{!16}
+
+!0 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !1, line: 1, size: 352, elements: !2)
+!1 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/tmp", checksumkind: CSK_MD5, checksum: "c0b1e83c4a0097ba80a1a5b0da78cb75")
+!2 = !{!3, !8}
+!3 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !0, file: !1, line: 2, baseType: !4, size: 320)
+!4 = !DICompositeType(tag: DW_TAG_array_type, baseType: !5, size: 320, elements: !6)
+!5 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!6 = !{!7}
+!7 = !DISubrange(count: 40)
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "ub", scope: !0, file: !1, line: 3, baseType: !9, size: 32, offset: 320)
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 23.0.0git (https://github.com/llvm/llvm-project.git 11727c11f833873af97d3969483f488e5251f35d)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!11 = !{i32 7, !"Dwarf Version", i32 5}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 7, !"frame-pointer", i32 2}
+!14 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
+!15 = !{!"clang version 23.0.0git (https://github.com/llvm/llvm-project.git 11727c11f833873af97d3969483f488e5251f35d)"}
+!16 = !{!17, !17, i64 0}
+!17 = !{!"int", !18, i64 0}
+!18 = !{!"omnipotent char", !19, i64 0}
+!19 = !{!"Simple C/C++ TBAA"}
+!20 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, type: !21, scopeLine: 5, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !10, retainedNodes: !25, keyInstructions: true)
+!21 = !DISubroutineType(types: !22)
+!22 = !{null, !23}
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64)
+!24 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !0)
+!25 = !{!26}
+!26 = !DILocalVariable(name: "t", arg: 1, scope: !20, file: !1, line: 5, type: !23)
+!27 = !DILocation(line: 0, scope: !20)
+!28 = !DILocation(line: 6, column: 9, scope: !20, atomGroup: 1, atomRank: 1)
+!29 = !{!30, !17, i64 40}
+!30 = !{!"t", !18, i64 0, !17, i64 40}
+!31 = !DILocation(line: 7, column: 1, scope: !20, atomGroup: 2, atomRank: 1)
+!32 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 8, type: !33, scopeLine: 8, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !10, retainedNodes: !35, keyInstructions: true)
+!33 = !DISubroutineType(types: !34)
+!34 = !{!9, !23}
+!35 = !{!36}
+!36 = !DILocalVariable(name: "t", arg: 1, scope: !32, file: !1, line: 8, type: !23)
+!37 = !DILocation(line: 0, scope: !32)
+!38 = !DILocation(line: 9, column: 13, scope: !32, atomGroup: 1, atomRank: 2)
+!39 = !DILocation(line: 9, column: 3, scope: !32, atomGroup: 1, atomRank: 1)
More information about the llvm-commits
mailing list