[BPF] Support for compile once and run everywhere

Introduction
============

This patch added intial support for bpf program compile once
and run everywhere (CO-RE).

The main motivation is for bpf program which depends on
kernel headers which may vary between different kernel versions.
The initial discussion can be found at https://lwn.net/Articles/773198/.

Currently, bpf program accesses kernel internal data structure
through bpf_probe_read() helper. The idea is to capture the
kernel data structure to be accessed through bpf_probe_read()
and relocate them on different kernel versions.

On each host, right before bpf program load, the bpfloader
will look at the types of the native linux through vmlinux BTF,
calculates proper access offset and patch the instruction.

To accommodate this, three intrinsic functions
   preserve_{array,union,struct}_access_index
are introduced which in clang will preserve the base pointer,
struct/union/array access_index and struct/union debuginfo type
information. Later, bpf IR pass can reconstruct the whole gep
access chains without looking at gep itself.

This patch did the following:
  . An IR pass is added to convert preserve_*_access_index to
    global variable who name encodes the getelementptr
    access pattern. The global variable has metadata
    attached to describe the corresponding struct/union
    debuginfo type.
  . An SimplifyPatchable MachineInstruction pass is added
    to remove unnecessary loads.
  . The BTF output pass is enhanced to generate relocation
    records located in .BTF.ext section.

Typical CO-RE also needs support of global variables which can
be assigned to different values to different hosts. For example,
kernel version can be used to guard different versions of codes.
This patch added the support for patchable externals as well.

Example
=======

The following is an example.

  struct pt_regs {
    long arg1;
    long arg2;
  };
  struct sk_buff {
    int i;
    struct net_device *dev;
  };

  #define _(x) (__builtin_preserve_access_index(x))
  static int (*bpf_probe_read)(void *dst, int size, const void *unsafe_ptr) =
          (void *) 4;
  extern __attribute__((section(".BPF.patchable_externs"))) unsigned __kernel_version;
  int bpf_prog(struct pt_regs *ctx) {
    struct net_device *dev = 0;

    // ctx->arg* does not need bpf_probe_read
    if (__kernel_version >= 41608)
      bpf_probe_read(&dev, sizeof(dev), _(&((struct sk_buff *)ctx->arg1)->dev));
    else
      bpf_probe_read(&dev, sizeof(dev), _(&((struct sk_buff *)ctx->arg2)->dev));
    return dev != 0;
  }

In the above, we want to translate the third argument of
bpf_probe_read() as relocations.

  -bash-4.4$ clang -target bpf -O2 -g -S trace.c

The compiler will generate two new subsections in .BTF.ext,
OffsetReloc and ExternReloc.
OffsetReloc is to record the structure member offset operations,
and ExternalReloc is to record the external globals where
only u8, u16, u32 and u64 are supported.

   BPFOffsetReloc Size
   struct SecLOffsetReloc for ELF section #1
   A number of struct BPFOffsetReloc for ELF section #1
   struct SecOffsetReloc for ELF section #2
   A number of struct BPFOffsetReloc for ELF section #2
   ...
   BPFExternReloc Size
   struct SecExternReloc for ELF section #1
   A number of struct BPFExternReloc for ELF section #1
   struct SecExternReloc for ELF section #2
   A number of struct BPFExternReloc for ELF section #2

  struct BPFOffsetReloc {
    uint32_t InsnOffset;    ///< Byte offset in this section
    uint32_t TypeID;        ///< TypeID for the relocation
    uint32_t OffsetNameOff; ///< The string to traverse types
  };

  struct BPFExternReloc {
    uint32_t InsnOffset;    ///< Byte offset in this section
    uint32_t ExternNameOff; ///< The string for external variable
  };

Note that only externs with attribute section ".BPF.patchable_externs"
are considered for Extern Reloc which will be patched by bpf loader
right before the load.

For the above test case, two offset records and one extern record
will be generated:
  OffsetReloc records:
        .long   .Ltmp12                 # Insn Offset
        .long   7                       # TypeId
        .long   242                     # Type Decode String
        .long   .Ltmp18                 # Insn Offset
        .long   7                       # TypeId
        .long   242                     # Type Decode String

  ExternReloc record:
        .long   .Ltmp5                  # Insn Offset
        .long   165                     # External Variable

  In string table:
        .ascii  "0:1"                   # string offset=242
        .ascii  "__kernel_version"      # string offset=165

The default member offset can be calculated as
    the 2nd member offset (0 representing the 1st member) of struct "sk_buff".

The asm code:
    .Ltmp5:
    .Ltmp6:
            r2 = 0
            r3 = 41608
    .Ltmp7:
    .Ltmp8:
            .loc    1 18 9 is_stmt 0        # t.c:18:9
    .Ltmp9:
            if r3 > r2 goto LBB0_2
    .Ltmp10:
    .Ltmp11:
            .loc    1 0 9                   # t.c:0:9
    .Ltmp12:
            r2 = 8
    .Ltmp13:
            .loc    1 19 66 is_stmt 1       # t.c:19:66
    .Ltmp14:
    .Ltmp15:
            r3 = *(u64 *)(r1 + 0)
            goto LBB0_3
    .Ltmp16:
    .Ltmp17:
    LBB0_2:
            .loc    1 0 66 is_stmt 0        # t.c:0:66
    .Ltmp18:
            r2 = 8
            .loc    1 21 66 is_stmt 1       # t.c:21:66
    .Ltmp19:
            r3 = *(u64 *)(r1 + 8)
    .Ltmp20:
    .Ltmp21:
    LBB0_3:
            .loc    1 0 66 is_stmt 0        # t.c:0:66
            r3 += r2
            r1 = r10
    .Ltmp22:
    .Ltmp23:
    .Ltmp24:
            r1 += -8
            r2 = 8
            call 4

For instruction .Ltmp12 and .Ltmp18, "r2 = 8", the number
8 is the structure offset based on the current BTF.
Loader needs to adjust it if it changes on the host.

For instruction .Ltmp5, "r2 = 0", the external variable
got a default value 0, loader needs to supply an appropriate
value for the particular host.

Compiling to generate object code and disassemble:
   0000000000000000 bpf_prog:
           0:       b7 02 00 00 00 00 00 00         r2 = 0
           1:       7b 2a f8 ff 00 00 00 00         *(u64 *)(r10 - 8) = r2
           2:       b7 02 00 00 00 00 00 00         r2 = 0
           3:       b7 03 00 00 88 a2 00 00         r3 = 41608
           4:       2d 23 03 00 00 00 00 00         if r3 > r2 goto +3 <LBB0_2>
           5:       b7 02 00 00 08 00 00 00         r2 = 8
           6:       79 13 00 00 00 00 00 00         r3 = *(u64 *)(r1 + 0)
           7:       05 00 02 00 00 00 00 00         goto +2 <LBB0_3>

    0000000000000040 LBB0_2:
           8:       b7 02 00 00 08 00 00 00         r2 = 8
           9:       79 13 08 00 00 00 00 00         r3 = *(u64 *)(r1 + 8)

    0000000000000050 LBB0_3:
          10:       0f 23 00 00 00 00 00 00         r3 += r2
          11:       bf a1 00 00 00 00 00 00         r1 = r10
          12:       07 01 00 00 f8 ff ff ff         r1 += -8
          13:       b7 02 00 00 08 00 00 00         r2 = 8
          14:       85 00 00 00 04 00 00 00         call 4

Instructions #2, #5 and #8 need relocation resoutions from the loader.

Signed-off-by: Yonghong Song <yhs@fb.com>

Differential Revision: https://reviews.llvm.org/D61524

llvm-svn: 365503
diff --git a/llvm/test/CodeGen/BPF/BTF/binary-format.ll b/llvm/test/CodeGen/BPF/BTF/binary-format.ll
index 39d699b..bc56156 100644
--- a/llvm/test/CodeGen/BPF/BTF/binary-format.ll
+++ b/llvm/test/CodeGen/BPF/BTF/binary-format.ll
@@ -15,31 +15,33 @@
 
 ; CHECK:    '.BTF'
 ; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 30000000
-; CHECK-EL: 0x00000010 30000000 33000000 2b000000 00000001
+; CHECK-EL: 0x00000010 30000000 33000000 01000000 00000001
 ; CHECK-EL: 0x00000020 04000000 20000001 00000000 0100000d
-; CHECK-EL: 0x00000030 01000000 2f000000 01000000 31000000
-; CHECK-EL: 0x00000040 0000000c 02000000 002e7465 7874002f
+; CHECK-EL: 0x00000030 01000000 05000000 01000000 07000000
+; CHECK-EL: 0x00000040 0000000c 02000000 00696e74 00610066
 ; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000030
-; CHECK-EB: 0x00000010 00000030 00000033 0000002b 01000000
+; CHECK-EB: 0x00000010 00000030 00000033 00000001 01000000
 ; CHECK-EB: 0x00000020 00000004 01000020 00000000 0d000001
-; CHECK-EB: 0x00000030 00000001 0000002f 00000001 00000031
-; CHECK-EB: 0x00000040 0c000000 00000002 002e7465 7874002f
-; CHECK:    0x00000050 746d702f 742e6300 696e7420 6628696e
-; CHECK:    0x00000060 74206129 207b2072 65747572 6e20613b
-; CHECK:    0x00000070 207d0069 6e740061 006600
+; CHECK-EB: 0x00000030 00000001 00000005 00000001 00000007
+; CHECK-EB: 0x00000040 0c000000 00000002 00696e74 00610066
+; CHECK:    0x00000050 002e7465 7874002f 746d702f 742e6300
+; CHECK:    0x00000060 696e7420 6628696e 74206129 207b2072
+; CHECK:    0x00000070 65747572 6e20613b 207d00
 ; CHECK:    '.BTF.ext'
-; CHECK-EL: 0x00000000 9feb0100 18000000 00000000 14000000
-; CHECK-EL: 0x00000010 14000000 2c000000 08000000 01000000
-; CHECK-EL: 0x00000020 01000000 00000000 03000000 10000000
-; CHECK-EL: 0x00000030 01000000 02000000 00000000 07000000
-; CHECK-EL: 0x00000040 10000000 00040000 08000000 07000000
-; CHECK-EL: 0x00000050 10000000 10040000
-; CHECK-EB: 0x00000000 eb9f0100 00000018 00000000 00000014
-; CHECK-EB: 0x00000010 00000014 0000002c 00000008 00000001
-; CHECK-EB: 0x00000020 00000001 00000000 00000003 00000010
-; CHECK-EB: 0x00000030 00000001 00000002 00000000 00000007
-; CHECK-EB: 0x00000040 00000010 00000400 00000008 00000007
-; CHECK-EB: 0x00000050 00000010 00000410
+; CHECK-EL: 0x00000000 9feb0100 28000000 00000000 14000000
+; CHECK-EL: 0x00000010 14000000 2c000000 40000000 00000000
+; CHECK-EL: 0x00000020 40000000 00000000 08000000 09000000
+; CHECK-EL: 0x00000030 01000000 00000000 03000000 10000000
+; CHECK-EL: 0x00000040 09000000 02000000 00000000 0f000000
+; CHECK-EL: 0x00000050 18000000 00040000 08000000 0f000000
+; CHECK-EL: 0x00000060 18000000 10040000
+; CHECK-EB: 0x00000000 eb9f0100 00000028 00000000 00000014
+; CHECK-EB: 0x00000010 00000014 0000002c 00000040 00000000
+; CHECK-EB: 0x00000020 00000040 00000000 00000008 00000009
+; CHECK-EB: 0x00000030 00000001 00000000 00000003 00000010
+; CHECK-EB: 0x00000040 00000009 00000002 00000000 0000000f
+; CHECK-EB: 0x00000050 00000018 00000400 00000008 0000000f
+; CHECK-EB: 0x00000060 00000018 00000410
 
 ; Function Attrs: nounwind readnone speculatable
 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
diff --git a/llvm/test/CodeGen/BPF/BTF/extern-global-var.ll b/llvm/test/CodeGen/BPF/BTF/extern-global-var.ll
index ad81d28..235a0ed 100644
--- a/llvm/test/CodeGen/BPF/BTF/extern-global-var.ll
+++ b/llvm/test/CodeGen/BPF/BTF/extern-global-var.ll
@@ -28,21 +28,21 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 
 attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/llvm/test/CodeGen/BPF/BTF/filename.ll b/llvm/test/CodeGen/BPF/BTF/filename.ll
index d0ada61..fd96720 100644
--- a/llvm/test/CodeGen/BPF/BTF/filename.ll
+++ b/llvm/test/CodeGen/BPF/BTF/filename.ll
@@ -23,41 +23,45 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   26                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   30                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/ttmp/t.c"    # string offset=7
+; CHECK-NEXT:        .ascii  "test"                  # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=26
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "test"                  # string offset=30
+; CHECK-NEXT:        .ascii  "/home/yhs/ttmp/t.c"    # string offset=16
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   10                      # FuncInfo section string offset=10
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin{{[0-9]+}}
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   10                      # LineInfo section string offset=10
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   16
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1038                    # Line 1 Col 14
 
diff --git a/llvm/test/CodeGen/BPF/BTF/func-func-ptr.ll b/llvm/test/CodeGen/BPF/BTF/func-func-ptr.ll
index df564f5..e614591 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-func-ptr.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-func-ptr.ll
@@ -29,16 +29,16 @@
 ; CHECK-NEXT:        .long   104
 ; CHECK-NEXT:        .long   104
 ; CHECK-NEXT:        .long   32
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 4)
@@ -54,17 +54,17 @@
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .long   29
 ; CHECK-NEXT:        .long   4
-; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   0                       # 0x0
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "p2"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "p2"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "t1"                    # string offset=26
 ; CHECK-NEXT:        .byte   0
@@ -74,21 +74,25 @@
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3091                    # Line 3 Col 19
 
diff --git a/llvm/test/CodeGen/BPF/BTF/func-non-void.ll b/llvm/test/CodeGen/BPF/BTF/func-non-void.ll
index e5361b9..5593ea88 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-non-void.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-non-void.ll
@@ -21,52 +21,56 @@
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   26
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "a1"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "a1"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   .Lfunc_begin0
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1024                    # Line 1 Col 0
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1042                    # Line 1 Col 18
 
diff --git a/llvm/test/CodeGen/BPF/BTF/func-source.ll b/llvm/test/CodeGen/BPF/BTF/func-source.ll
index 6e1bed3..0d6e098 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-source.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-source.ll
@@ -27,38 +27,42 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   33                      # BTF_KIND_FUNC(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_FUNC(id = 2)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .byte   102                     # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=3
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "void f(void) { }"      # string offset=16
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   102                     # string offset=33
+; CHECK-NEXT:        .ascii  "void f(void) { }"      # string offset=18
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   3                       # FuncInfo section string offset=3
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   3                       # LineInfo section string offset=3
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
-; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   18
 ; CHECK-NEXT:        .long   1040                    # Line 1 Col 16
 
 attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
diff --git a/llvm/test/CodeGen/BPF/BTF/func-typedef.ll b/llvm/test/CodeGen/BPF/BTF/func-typedef.ll
index 8deac0f..48fcb33 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-typedef.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-typedef.ll
@@ -24,65 +24,70 @@
 ; CHECK-NEXT:        .long   72
 ; CHECK-NEXT:        .long   72
 ; CHECK-NEXT:        .long   35
-; CHECK-NEXT:        .long   16                      # BTF_KIND_TYPEDEF(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_TYPEDEF(id = 1)
 ; CHECK-NEXT:        .long   134217728               # 0x8000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   22                      # BTF_KIND_TYPEDEF(id = 2)
+; CHECK-NEXT:        .long   7                       # BTF_KIND_TYPEDEF(id = 2)
 ; CHECK-NEXT:        .long   134217728               # 0x8000000
 ; CHECK-NEXT:        .long   3
-; CHECK-NEXT:        .long   27                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   12                      # BTF_KIND_INT(id = 3)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 4)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   31
+; CHECK-NEXT:        .long   16
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   33                      # BTF_KIND_FUNC(id = 5)
+; CHECK-NEXT:        .long   18                      # BTF_KIND_FUNC(id = 5)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "__int"                 # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "_int"                  # string offset=7
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "__int"                 # string offset=16
+; CHECK-NEXT:        .ascii  "int"                   # string offset=12
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "_int"                  # string offset=22
+; CHECK-NEXT:        .byte   97                      # string offset=16
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=27
+; CHECK-NEXT:        .byte   102                     # string offset=18
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   97                      # string offset=31
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=20
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   102                     # string offset=33
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=26
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   20                      # FuncInfo section string offset=20
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   20                      # LineInfo section string offset=20
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   .Lfunc_begin0
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   26
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3072                    # Line 3 Col 0
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   26
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   3092                    # Line 3 Col 20
 
+
 ; Function Attrs: nounwind readnone speculatable
 declare void @llvm.dbg.value(metadata, metadata, metadata) #1
 
diff --git a/llvm/test/CodeGen/BPF/BTF/func-unused-arg.ll b/llvm/test/CodeGen/BPF/BTF/func-unused-arg.ll
index 62e9d40..ea94fb7 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-unused-arg.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-unused-arg.ll
@@ -21,48 +21,52 @@
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   48
 ; CHECK-NEXT:        .long   26
-; CHECK-NEXT:        .long   16                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   5
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   23                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  "a1"                    # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=16
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "a1"                    # string offset=20
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=11
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=23
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=17
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # FuncInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   3
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   11                      # LineInfo section string offset=11
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   17
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1042                    # Line 1 Col 18
 
diff --git a/llvm/test/CodeGen/BPF/BTF/func-void.ll b/llvm/test/CodeGen/BPF/BTF/func-void.ll
index f86643b..42a24d1 100644
--- a/llvm/test/CodeGen/BPF/BTF/func-void.ll
+++ b/llvm/test/CodeGen/BPF/BTF/func-void.ll
@@ -23,35 +23,39 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   0
-; CHECK-NEXT:        .long   16                      # BTF_KIND_FUNC(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_FUNC(id = 2)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=7
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=4
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "f1"                    # string offset=16
+; CHECK-NEXT:        .ascii  "/tmp/t.c"              # string offset=10
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
 ; CHECK-NEXT:        .short  60319                   # 0xeb9f
 ; CHECK-NEXT:        .byte   1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   40
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   8                       # FuncInfo
-; CHECK-NEXT:        .long   1                       # FuncInfo section string offset=1
+; CHECK-NEXT:        .long   4                       # FuncInfo section string offset=4
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Lfunc_begin0
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .long   16                      # LineInfo
-; CHECK-NEXT:        .long   1                       # LineInfo section string offset=1
+; CHECK-NEXT:        .long   4                       # LineInfo section string offset=4
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
-; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   10
 ; CHECK-NEXT:        .long   0
 ; CHECK-NEXT:        .long   1040                    # Line 1 Col 16
 
diff --git a/llvm/test/CodeGen/BPF/BTF/local-var.ll b/llvm/test/CodeGen/BPF/BTF/local-var.ll
index 4eb498a..fa7f09f 100644
--- a/llvm/test/CodeGen/BPF/BTF/local-var.ll
+++ b/llvm/test/CodeGen/BPF/BTF/local-var.ll
@@ -29,34 +29,34 @@
 ; CHECK-NEXT:        .long   64
 ; CHECK-NEXT:        .long   64
 ; CHECK-NEXT:        .long   59
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 1)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 1)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   16777224                # 0x1000008
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 2)
 ; CHECK-NEXT:        .long   218103809               # 0xd000001
 ; CHECK-NEXT:        .long   3
-; CHECK-NEXT:        .long   49
+; CHECK-NEXT:        .long   6
 ; CHECK-NEXT:        .long   1
-; CHECK-NEXT:        .long   51                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   8                       # BTF_KIND_INT(id = 3)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   55                      # BTF_KIND_FUNC(id = 4)
+; CHECK-NEXT:        .long   12                      # BTF_KIND_FUNC(id = 4)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   2
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "char"                  # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .byte   97                      # string offset=6
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "char"                  # string offset=44
+; CHECK-NEXT:        .ascii  "int"                   # string offset=8
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .byte   97                      # string offset=49
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=12
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=51
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=16
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=55
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=22
 ; CHECK-NEXT:        .byte   0
 
 ; Function Attrs: nounwind readnone speculatable
diff --git a/llvm/test/CodeGen/BPF/BTF/map-def.ll b/llvm/test/CodeGen/BPF/BTF/map-def.ll
new file mode 100644
index 0000000..cf77788
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/BTF/map-def.ll
@@ -0,0 +1,120 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+
+; Source code:
+;   struct key_type {
+;     int a;
+;     int b;
+;   };
+;   struct map_type {
+;     struct key_type *key;
+;     unsigned *value;
+;   };
+;   struct map_type __attribute__((section(".maps"))) hash_map;
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+%struct.map_type = type { %struct.key_type*, i32* }
+%struct.key_type = type { i32, i32 }
+
+@hash_map = dso_local local_unnamed_addr global %struct.map_type zeroinitializer, section ".maps", align 8, !dbg !0
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   65
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 1)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   14
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   64                      # 0x40
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 2)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   20                      # BTF_KIND_STRUCT(id = 3)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   29
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   31
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   33                      # BTF_KIND_INT(id = 4)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 5)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   37                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   50                      # BTF_KIND_VAR(id = 7)
+; CHECK-NEXT:        .long   234881024               # 0xe000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   59                      # BTF_KIND_DATASEC(id = 8)
+; CHECK-NEXT:        .long   251658241               # 0xf000001
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .long   hash_map
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "map_type"              # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "key"                   # string offset=10
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "value"                 # string offset=14
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "key_type"              # string offset=20
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   97                      # string offset=29
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   98                      # string offset=31
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=33
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "unsigned int"          # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "hash_map"              # string offset=50
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".maps"                 # string offset=59
+; CHECK-NEXT:        .byte   0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!18, !19, !20}
+!llvm.ident = !{!21}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "hash_map", scope: !2, file: !3, line: 9, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "map_type", file: !3, line: 5, size: 128, elements: !7)
+!7 = !{!8, !15}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "key", scope: !6, file: !3, line: 6, baseType: !9, size: 64)
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "key_type", file: !3, line: 1, size: 64, elements: !11)
+!11 = !{!12, !14}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !3, line: 2, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !10, file: !3, line: 3, baseType: !13, size: 32, offset: 32)
+!15 = !DIDerivedType(tag: DW_TAG_member, name: "value", scope: !6, file: !3, line: 7, baseType: !16, size: 64, offset: 64)
+!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64)
+!17 = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
+!18 = !{i32 2, !"Dwarf Version", i32 4}
+!19 = !{i32 2, !"Debug Info Version", i32 3}
+!20 = !{i32 1, !"wchar_size", i32 4}
+!21 = !{!"clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)"}
diff --git a/llvm/test/CodeGen/BPF/BTF/ptr-prune-type.ll b/llvm/test/CodeGen/BPF/BTF/ptr-prune-type.ll
new file mode 100644
index 0000000..597e413
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/BTF/ptr-prune-type.ll
@@ -0,0 +1,84 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+
+; Source code:
+;   struct t {
+;     int a;
+;   };
+;   struct t2 {
+;     struct t *f1;
+;   };
+;   struct t2 __attribute__((section("prune_types"))) g;
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm t.c
+
+%struct.t2 = type { %struct.t* }
+%struct.t = type { i32 }
+
+@g = dso_local local_unnamed_addr global %struct.t2 zeroinitializer, section "prune_types", align 8, !dbg !0
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   88
+; CHECK-NEXT:        .long   88
+; CHECK-NEXT:        .long   23
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 1)
+; CHECK-NEXT:        .long   67108865                # 0x4000001
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 2)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   7                       # BTF_KIND_VAR(id = 3)
+; CHECK-NEXT:        .long   234881024               # 0xe000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   9                       # BTF_KIND_DATASEC(id = 4)
+; CHECK-NEXT:        .long   251658241               # 0xf000001
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   g
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   21                      # BTF_KIND_FWD(id = 5)
+; CHECK-NEXT:        .long   117440512               # 0x7000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "t2"                    # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "f1"                    # string offset=4
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   103                     # string offset=7
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "prune_types"           # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   116                     # string offset=21
+; CHECK-NEXT:        .byte   0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!14, !15, !16}
+!llvm.ident = !{!17}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "g", scope: !2, file: !3, line: 7, type: !6, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5, nameTableKind: None)
+!3 = !DIFile(filename: "t.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!4 = !{}
+!5 = !{!0}
+!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t2", file: !3, line: 4, size: 64, elements: !7)
+!7 = !{!8}
+!8 = !DIDerivedType(tag: DW_TAG_member, name: "f1", scope: !6, file: !3, line: 5, baseType: !9, size: 64)
+!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64)
+!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !3, line: 1, size: 32, elements: !11)
+!11 = !{!12}
+!12 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !10, file: !3, line: 2, baseType: !13, size: 32)
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{i32 2, !"Dwarf Version", i32 4}
+!15 = !{i32 2, !"Debug Info Version", i32 3}
+!16 = !{i32 1, !"wchar_size", i32 4}
+!17 = !{!"clang version 9.0.0 (trunk 364157) (llvm/trunk 364156)"}
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-derived-type.ll b/llvm/test/CodeGen/BPF/BTF/static-var-derived-type.ll
index 1e87b5a..680bcd6 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-derived-type.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-derived-type.ll
@@ -46,11 +46,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   45                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .long   16777280                # 0x1000040
-; CHECK-NEXT:        .long   54                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   10                      # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -116,13 +116,13 @@
 ; CHECK-NEXT:        .long   v4
 ; CHECK-NEXT:        .long   8
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "long int"              # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bugs/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "long int"              # string offset=45
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=14
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=54
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bugs/test.c" # string offset=20
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "int"                   # string offset=58
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
index beeffa0..4533742 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited-sec.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
index b3b3576..ed6e9ea 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-inited.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
index 546f2bc..5901bbb 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly-sec.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_CONST(id = 4)
@@ -80,13 +80,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
index e39e737..04a3fbc 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-readonly.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_CONST(id = 4)
@@ -80,13 +80,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
index 36ce07d..6dcd4fe 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-sec.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll b/llvm/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll
index 51ff020..93f5da3 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var-zerolen-array.ll
@@ -32,11 +32,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -79,13 +79,13 @@
 ; CHECK-NEXT:        .long   sv
 ; CHECK-NEXT:        .long   20
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "test"                  # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=10
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "test"                  # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=16
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .byte   116                     # string offset=53
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/BTF/static-var.ll b/llvm/test/CodeGen/BPF/BTF/static-var.ll
index 5d09b19..0eb0565 100644
--- a/llvm/test/CodeGen/BPF/BTF/static-var.ll
+++ b/llvm/test/CodeGen/BPF/BTF/static-var.ll
@@ -35,11 +35,11 @@
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
 ; CHECK-NEXT:        .long   218103808               # 0xd000000
 ; CHECK-NEXT:        .long   2
-; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
 ; CHECK-NEXT:        .long   16777216                # 0x1000000
 ; CHECK-NEXT:        .long   4
 ; CHECK-NEXT:        .long   16777248                # 0x1000020
-; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
 ; CHECK-NEXT:        .long   201326592               # 0xc000000
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .long   0                       # BTF_KIND_VOLATILE(id = 4)
@@ -74,13 +74,13 @@
 ; CHECK-NEXT:        .long   a
 ; CHECK-NEXT:        .long   1
 ; CHECK-NEXT:        .byte   0                       # string offset=0
-; CHECK-NEXT:        .ascii  ".text"                 # string offset=1
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=7
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "int"                   # string offset=44
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
 ; CHECK-NEXT:        .byte   0
-; CHECK-NEXT:        .ascii  "foo"                   # string offset=48
+; CHECK-NEXT:        .ascii  "/home/yhs/work/tests/llvm/bug/test.c" # string offset=15
 ; CHECK-NEXT:        .byte   0
 ; CHECK-NEXT:        .ascii  "short"                 # string offset=52
 ; CHECK-NEXT:        .byte   0
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-basic.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-basic.ll
new file mode 100644
index 0000000..a6fb3a3
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-basic.ll
@@ -0,0 +1,186 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;    struct sk_buff {
+;      int i;
+;      struct net_device *dev;
+;    };
+;    #define _(x) (__builtin_preserve_access_index(x))
+;    static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;        = (void *) 4;
+;
+;    int bpf_prog(struct sk_buff *ctx) {
+;      struct net_device *dev = 0;
+;      bpf_probe_read(&dev, sizeof(dev), _(&ctx->dev));
+;      return dev != 0;
+;    }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, %struct.net_device* }
+%struct.net_device = type opaque
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca %struct.net_device*, align 8
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !26, metadata !DIExpression()), !dbg !28
+  %3 = bitcast %struct.net_device** %2 to i8*, !dbg !29
+  call void @llvm.lifetime.start.p0i8(i64 8, i8* nonnull %3) #4, !dbg !29
+  call void @llvm.dbg.value(metadata %struct.net_device* null, metadata !27, metadata !DIExpression()), !dbg !28
+  store %struct.net_device* null, %struct.net_device** %2, align 8, !dbg !30, !tbaa !31
+  %4 = tail call %struct.net_device** @llvm.preserve.struct.access.index.p0p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
+  %5 = bitcast %struct.net_device** %4 to i8*, !dbg !35
+  %6 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 8, i8* %5) #4, !dbg !36
+  %7 = load %struct.net_device*, %struct.net_device** %2, align 8, !dbg !37, !tbaa !31
+  call void @llvm.dbg.value(metadata %struct.net_device* %7, metadata !27, metadata !DIExpression()), !dbg !28
+  %8 = icmp ne %struct.net_device* %7, null, !dbg !38
+  %9 = zext i1 %8 to i32, !dbg !38
+  call void @llvm.lifetime.end.p0i8(i64 8, i8* nonnull %3) #4, !dbg !39
+  ret i32 %9, !dbg !40
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   90
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   16
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   64                      # 0x40
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 4)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   19                      # BTF_KIND_FWD(id = 5)
+; CHECK-NEXT:        .long   117440512               # 0x7000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 6)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   34                      # BTF_KIND_FUNC(id = 7)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=34
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=43
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=49
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1"                   # string offset=86
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   124
+; CHECK-NEXT:        .long   144
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   43                      # Offset reloc section string offset=43
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   86
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device** @llvm.preserve.struct.access.index.p0p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 6, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 9, type: !16, scopeLine: 9, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !25)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 1, size: 128, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 3, baseType: !23, size: 64, offset: 64)
+!23 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !24, size: 64)
+!24 = !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 3, flags: DIFlagFwdDecl)
+!25 = !{!26, !27}
+!26 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 9, type: !18)
+!27 = !DILocalVariable(name: "dev", scope: !15, file: !1, line: 10, type: !23)
+!28 = !DILocation(line: 0, scope: !15)
+!29 = !DILocation(line: 10, column: 3, scope: !15)
+!30 = !DILocation(line: 10, column: 22, scope: !15)
+!31 = !{!32, !32, i64 0}
+!32 = !{!"any pointer", !33, i64 0}
+!33 = !{!"omnipotent char", !34, i64 0}
+!34 = !{!"Simple C/C++ TBAA"}
+!35 = !DILocation(line: 11, column: 37, scope: !15)
+!36 = !DILocation(line: 11, column: 3, scope: !15)
+!37 = !DILocation(line: 12, column: 10, scope: !15)
+!38 = !DILocation(line: 12, column: 14, scope: !15)
+!39 = !DILocation(line: 13, column: 1, scope: !15)
+!40 = !DILocation(line: 12, column: 3, scope: !15)
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll
new file mode 100644
index 0000000..779b395
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-multilevel.ll
@@ -0,0 +1,197 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   struct net_device {
+;     int dev_id;
+;     int others;
+;   };
+;   struct sk_buff {
+;     int i;
+;     struct net_device dev;
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev.dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, %struct.net_device }
+%struct.net_device = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !28, metadata !DIExpression()), !dbg !30
+  %3 = bitcast i32* %2 to i8*, !dbg !31
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !31
+  %4 = tail call %struct.net_device* @llvm.preserve.struct.access.index.p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !32, !llvm.preserve.access.index !19
+  %5 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device* %4, i32 0, i32 0), !dbg !32, !llvm.preserve.access.index !23
+  %6 = bitcast i32* %5 to i8*, !dbg !32
+  %7 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %6) #4, !dbg !33
+  %8 = load i32, i32* %2, align 4, !dbg !34, !tbaa !35
+  call void @llvm.dbg.value(metadata i32 %8, metadata !29, metadata !DIExpression()), !dbg !30
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !39
+  ret i32 %8, !dbg !40
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   132
+; CHECK-NEXT:        .long   132
+; CHECK-NEXT:        .long   106
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   12
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   19                      # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   37
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 5)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   48                      # BTF_KIND_FUNC(id = 6)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=44
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=48
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=57
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=63
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:0"                 # string offset=100
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   57                      # Offset reloc section string offset=57
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   100
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device* @llvm.preserve.struct.access.index.p0s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 10, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 13, type: !16, scopeLine: 13, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 5, size: 96, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 6, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 7, baseType: !23, size: 64, offset: 32)
+!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 1, size: 64, elements: !24)
+!24 = !{!25, !26}
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !23, file: !1, line: 2, baseType: !9, size: 32)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !23, file: !1, line: 3, baseType: !9, size: 32, offset: 32)
+!27 = !{!28, !29}
+!28 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 13, type: !18)
+!29 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 14, type: !9)
+!30 = !DILocation(line: 0, scope: !15)
+!31 = !DILocation(line: 14, column: 3, scope: !15)
+!32 = !DILocation(line: 15, column: 40, scope: !15)
+!33 = !DILocation(line: 15, column: 3, scope: !15)
+!34 = !DILocation(line: 16, column: 10, scope: !15)
+!35 = !{!36, !36, i64 0}
+!36 = !{!"int", !37, i64 0}
+!37 = !{!"omnipotent char", !38, i64 0}
+!38 = !{!"Simple C/C++ TBAA"}
+!39 = !DILocation(line: 17, column: 1, scope: !15)
+!40 = !DILocation(line: 16, column: 3, scope: !15)
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
new file mode 100644
index 0000000..732187c
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-anonymous.ll
@@ -0,0 +1,213 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   struct sk_buff {
+;     int i;
+;     struct {
+;       int dev_id;
+;       int others;
+;     } dev[10];
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev[5].dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, [10 x %struct.anon] }
+%struct.anon = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !31, metadata !DIExpression()), !dbg !33
+  %3 = bitcast i32* %2 to i8*, !dbg !34
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !34
+  %4 = tail call [10 x %struct.anon]* @llvm.preserve.struct.access.index.p0a10s_struct.anons.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
+  %5 = tail call %struct.anon* @llvm.preserve.array.access.index.p0s_struct.anons.p0a10s_struct.anons([10 x %struct.anon]* %4, i32 1, i32 5), !dbg !35
+  %6 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.anons(%struct.anon* %5, i32 0, i32 0), !dbg !35, !llvm.preserve.access.index !24
+  %7 = bitcast i32* %6 to i8*, !dbg !35
+  %8 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %7) #4, !dbg !36
+  %9 = load i32, i32* %2, align 4, !dbg !37, !tbaa !38
+  call void @llvm.dbg.value(metadata i32 %9, metadata !32, metadata !DIExpression()), !dbg !33
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !42
+  ret i32 %9, !dbg !43
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   117
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   84
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   19
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   26
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_ARRAY(id = 5)
+; CHECK-NEXT:        .long   50331648                # 0x3000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   33                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 7)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   53
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   57                      # BTF_KIND_FUNC(id = 8)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=26
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "__ARRAY_SIZE_TYPE__"   # string offset=33
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=53
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=57
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=66
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=72
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:5:0"               # string offset=109
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   66                      # Offset reloc section string offset=66
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   109
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare [10 x %struct.anon]* @llvm.preserve.struct.access.index.p0a10s_struct.anons.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %struct.anon* @llvm.preserve.array.access.index.p0s_struct.anons.p0a10s_struct.anons([10 x %struct.anon]*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.anons(%struct.anon*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 9, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 12, type: !16, scopeLine: 12, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !30)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 1, size: 672, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 6, baseType: !23, size: 640, offset: 32)
+!23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 640, elements: !28)
+!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !19, file: !1, line: 3, size: 64, elements: !25)
+!25 = !{!26, !27}
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !24, file: !1, line: 4, baseType: !9, size: 32)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !24, file: !1, line: 5, baseType: !9, size: 32, offset: 32)
+!28 = !{!29}
+!29 = !DISubrange(count: 10)
+!30 = !{!31, !32}
+!31 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 12, type: !18)
+!32 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 13, type: !9)
+!33 = !DILocation(line: 0, scope: !15)
+!34 = !DILocation(line: 13, column: 3, scope: !15)
+!35 = !DILocation(line: 14, column: 40, scope: !15)
+!36 = !DILocation(line: 14, column: 3, scope: !15)
+!37 = !DILocation(line: 15, column: 10, scope: !15)
+!38 = !{!39, !39, i64 0}
+!39 = !{!"int", !40, i64 0}
+!40 = !{!"omnipotent char", !41, i64 0}
+!41 = !{!"Simple C/C++ TBAA"}
+!42 = !DILocation(line: 16, column: 1, scope: !15)
+!43 = !DILocation(line: 15, column: 3, scope: !15)
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
new file mode 100644
index 0000000..77d2375
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-struct-array.ll
@@ -0,0 +1,216 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   struct net_device {
+;     int dev_id;
+;     int others;
+;   };
+;   struct sk_buff {
+;     int i;
+;     struct net_device dev[10];
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(struct sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->dev[5].dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%struct.sk_buff = type { i32, [10 x %struct.net_device] }
+%struct.net_device = type { i32, i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%struct.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %struct.sk_buff* %0, metadata !31, metadata !DIExpression()), !dbg !33
+  %3 = bitcast i32* %2 to i8*, !dbg !34
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !34
+  %4 = tail call [10 x %struct.net_device]* @llvm.preserve.struct.access.index.p0a10s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff* %0, i32 1, i32 1), !dbg !35, !llvm.preserve.access.index !19
+  %5 = tail call %struct.net_device* @llvm.preserve.array.access.index.p0s_struct.net_devices.p0a10s_struct.net_devices([10 x %struct.net_device]* %4, i32 1, i32 5), !dbg !35
+  %6 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device* %5, i32 0, i32 0), !dbg !35, !llvm.preserve.access.index !24
+  %7 = bitcast i32* %6 to i8*, !dbg !35
+  %8 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %7) #4, !dbg !36
+  %9 = load i32, i32* %2, align 4, !dbg !37, !tbaa !38
+  call void @llvm.dbg.value(metadata i32 %9, metadata !32, metadata !DIExpression()), !dbg !33
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !42
+  ret i32 %9, !dbg !43
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   172
+; CHECK-NEXT:        .long   128
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_STRUCT(id = 2)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   84
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   15                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   19                      # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   30
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   37
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_ARRAY(id = 5)
+; CHECK-NEXT:        .long   50331648                # 0x3000000
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .long   10
+; CHECK-NEXT:        .long   44                      # BTF_KIND_INT(id = 6)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 7)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   68                      # BTF_KIND_FUNC(id = 8)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   7
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "net_device"            # string offset=19
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=30
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=37
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "__ARRAY_SIZE_TYPE__"   # string offset=44
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=64
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=68
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=77
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=83
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:5:0"               # string offset=120
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   77                      # Offset reloc section string offset=77
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   120
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare [10 x %struct.net_device]* @llvm.preserve.struct.access.index.p0a10s_struct.net_devices.p0s_struct.sk_buffs(%struct.sk_buff*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %struct.net_device* @llvm.preserve.array.access.index.p0s_struct.net_devices.p0a10s_struct.net_devices([10 x %struct.net_device]*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.net_devices(%struct.net_device*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 10, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 13, type: !16, scopeLine: 13, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !30)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "sk_buff", file: !1, line: 5, size: 672, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 6, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !19, file: !1, line: 7, baseType: !23, size: 640, offset: 32)
+!23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 640, elements: !28)
+!24 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "net_device", file: !1, line: 1, size: 64, elements: !25)
+!25 = !{!26, !27}
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !24, file: !1, line: 2, baseType: !9, size: 32)
+!27 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !24, file: !1, line: 3, baseType: !9, size: 32, offset: 32)
+!28 = !{!29}
+!29 = !DISubrange(count: 10)
+!30 = !{!31, !32}
+!31 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 13, type: !18)
+!32 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 14, type: !9)
+!33 = !DILocation(line: 0, scope: !15)
+!34 = !DILocation(line: 14, column: 3, scope: !15)
+!35 = !DILocation(line: 15, column: 40, scope: !15)
+!36 = !DILocation(line: 15, column: 3, scope: !15)
+!37 = !DILocation(line: 16, column: 10, scope: !15)
+!38 = !{!39, !39, i64 0}
+!39 = !{!"int", !40, i64 0}
+!40 = !{!"omnipotent char", !41, i64 0}
+!41 = !{!"Simple C/C++ TBAA"}
+!42 = !DILocation(line: 17, column: 1, scope: !15)
+!43 = !DILocation(line: 16, column: 3, scope: !15)
diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll
new file mode 100644
index 0000000..eefa1eb
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-union.ll
@@ -0,0 +1,220 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   union sk_buff {
+;     int i;
+;     struct {
+;       int netid;
+;       union {
+;         int dev_id;
+;         int others;
+;       } dev;
+;     } u;
+;   };
+;   #define _(x) (__builtin_preserve_access_index(x))
+;   static int (*bpf_probe_read)(void *dst, int size, void *unsafe_ptr)
+;       = (void *) 4;
+;
+;   int bpf_prog(union sk_buff *ctx) {
+;     int dev_id;
+;     bpf_probe_read(&dev_id, sizeof(int), _(&ctx->u.dev.dev_id));
+;     return dev_id;
+;   }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+%union.sk_buff = type { %struct.anon }
+%struct.anon = type { i32, %union.anon }
+%union.anon = type { i32 }
+
+; Function Attrs: nounwind
+define dso_local i32 @bpf_prog(%union.sk_buff*) local_unnamed_addr #0 !dbg !15 {
+  %2 = alloca i32, align 4
+  call void @llvm.dbg.value(metadata %union.sk_buff* %0, metadata !32, metadata !DIExpression()), !dbg !34
+  %3 = bitcast i32* %2 to i8*, !dbg !35
+  call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4, !dbg !35
+  %4 = tail call %union.sk_buff* @llvm.preserve.union.access.index.p0s_union.sk_buffs.p0s_union.sk_buffs(%union.sk_buff* %0, i32 1), !dbg !36, !llvm.preserve.access.index !19
+  %5 = getelementptr inbounds %union.sk_buff, %union.sk_buff* %4, i64 0, i32 0, !dbg !36
+  %6 = tail call %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.anons(%struct.anon* %5, i32 1, i32 1), !dbg !36, !llvm.preserve.access.index !23
+  %7 = tail call %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon* %6, i32 0), !dbg !36, !llvm.preserve.access.index !27
+  %8 = bitcast %union.anon* %7 to i8*, !dbg !36
+  %9 = call i32 inttoptr (i64 4 to i32 (i8*, i32, i8*)*)(i8* nonnull %3, i32 4, i8* %8) #4, !dbg !37
+  %10 = load i32, i32* %2, align 4, !dbg !38, !tbaa !39
+  call void @llvm.dbg.value(metadata i32 %10, metadata !33, metadata !DIExpression()), !dbg !34
+  call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4, !dbg !43
+  ret i32 %10, !dbg !44
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   168
+; CHECK-NEXT:        .long   105
+; CHECK-NEXT:        .long   0                       # BTF_KIND_PTR(id = 1)
+; CHECK-NEXT:        .long   33554432                # 0x2000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_UNION(id = 2)
+; CHECK-NEXT:        .long   83886082                # 0x5000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   9
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   11
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   13                      # BTF_KIND_INT(id = 3)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   0                       # BTF_KIND_STRUCT(id = 4)
+; CHECK-NEXT:        .long   67108866                # 0x4000002
+; CHECK-NEXT:        .long   8
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   23
+; CHECK-NEXT:        .long   5
+; CHECK-NEXT:        .long   32                      # 0x20
+; CHECK-NEXT:        .long   0                       # BTF_KIND_UNION(id = 5)
+; CHECK-NEXT:        .long   83886082                # 0x5000002
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   27
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   34
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   0                       # 0x0
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 6)
+; CHECK-NEXT:        .long   218103809               # 0xd000001
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   41
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   45                      # BTF_KIND_FUNC(id = 7)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   6
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "sk_buff"               # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   105                     # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   117                     # string offset=11
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=13
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "netid"                 # string offset=17
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev"                   # string offset=23
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "dev_id"                # string offset=27
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "others"                # string offset=34
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "ctx"                   # string offset=41
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "bpf_prog"              # string offset=45
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=54
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=60
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "0:1:1:0"               # string offset=97
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   76
+; CHECK-NEXT:        .long   96
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   120
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   8                       # FuncInfo
+
+; CHECK:             .long   12                      # OffsetReloc
+; CHECK-NEXT:        .long   54                      # Offset reloc section string offset=54
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp2
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   97
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone
+declare %union.sk_buff* @llvm.preserve.union.access.index.p0s_union.sk_buffs.p0s_union.sk_buffs(%union.sk_buff*, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %union.anon* @llvm.preserve.struct.access.index.p0s_union.anons.p0s_struct.anons(%struct.anon*, i32 immarg, i32 immarg) #2
+
+; Function Attrs: nounwind readnone
+declare %union.anon* @llvm.preserve.union.access.index.p0s_union.anons.p0s_union.anons(%union.anon*, i32 immarg) #2
+
+; Function Attrs: argmemonly nounwind
+declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #1
+
+; Function Attrs: nounwind readnone speculatable
+declare void @llvm.dbg.value(metadata, metadata, metadata) #3
+
+attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+attributes #1 = { argmemonly nounwind }
+attributes #2 = { nounwind readnone }
+attributes #3 = { nounwind readnone speculatable }
+attributes #4 = { nounwind }
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!11, !12, !13}
+!llvm.ident = !{!14}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !3, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{!4}
+!4 = !DIGlobalVariableExpression(var: !5, expr: !DIExpression())
+!5 = distinct !DIGlobalVariable(name: "bpf_probe_read", scope: !0, file: !1, line: 12, type: !6, isLocal: true, isDefinition: true)
+!6 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !7, size: 64)
+!7 = !DISubroutineType(types: !8)
+!8 = !{!9, !10, !9, !10}
+!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64)
+!11 = !{i32 2, !"Dwarf Version", i32 4}
+!12 = !{i32 2, !"Debug Info Version", i32 3}
+!13 = !{i32 1, !"wchar_size", i32 4}
+!14 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
+!15 = distinct !DISubprogram(name: "bpf_prog", scope: !1, file: !1, line: 15, type: !16, scopeLine: 15, flags: DIFlagPrototyped, isLocal: false, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !31)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!9, !18}
+!18 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !19, size: 64)
+!19 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "sk_buff", file: !1, line: 1, size: 64, elements: !20)
+!20 = !{!21, !22}
+!21 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !19, file: !1, line: 2, baseType: !9, size: 32)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "u", scope: !19, file: !1, line: 9, baseType: !23, size: 64)
+!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, scope: !19, file: !1, line: 3, size: 64, elements: !24)
+!24 = !{!25, !26}
+!25 = !DIDerivedType(tag: DW_TAG_member, name: "netid", scope: !23, file: !1, line: 4, baseType: !9, size: 32)
+!26 = !DIDerivedType(tag: DW_TAG_member, name: "dev", scope: !23, file: !1, line: 8, baseType: !27, size: 32, offset: 32)
+!27 = distinct !DICompositeType(tag: DW_TAG_union_type, scope: !23, file: !1, line: 5, size: 32, elements: !28)
+!28 = !{!29, !30}
+!29 = !DIDerivedType(tag: DW_TAG_member, name: "dev_id", scope: !27, file: !1, line: 6, baseType: !9, size: 32)
+!30 = !DIDerivedType(tag: DW_TAG_member, name: "others", scope: !27, file: !1, line: 7, baseType: !9, size: 32)
+!31 = !{!32, !33}
+!32 = !DILocalVariable(name: "ctx", arg: 1, scope: !15, file: !1, line: 15, type: !18)
+!33 = !DILocalVariable(name: "dev_id", scope: !15, file: !1, line: 16, type: !9)
+!34 = !DILocation(line: 0, scope: !15)
+!35 = !DILocation(line: 16, column: 3, scope: !15)
+!36 = !DILocation(line: 17, column: 40, scope: !15)
+!37 = !DILocation(line: 17, column: 3, scope: !15)
+!38 = !DILocation(line: 18, column: 10, scope: !15)
+!39 = !{!40, !40, i64 0}
+!40 = !{!"int", !41, i64 0}
+!41 = !{!"omnipotent char", !42, i64 0}
+!42 = !{!"Simple C/C++ TBAA"}
+!43 = !DILocation(line: 19, column: 1, scope: !15)
+!44 = !DILocation(line: 18, column: 3, scope: !15)
diff --git a/llvm/test/CodeGen/BPF/CORE/patchable-extern-char.ll b/llvm/test/CodeGen/BPF/CORE/patchable-extern-char.ll
new file mode 100644
index 0000000..fb30fd5
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/patchable-extern-char.ll
@@ -0,0 +1,107 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   extern __attribute__((section(".BPF.patchable_externs"))) char a;
+;   int foo() { return a; }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+@a = external dso_local local_unnamed_addr global i8, section ".BPF.patchable_externs", align 1
+
+; Function Attrs: norecurse nounwind readonly
+define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
+  %1 = load i8, i8* @a, align 1, !dbg !11, !tbaa !12
+  %2 = sext i8 %1 to i32, !dbg !11
+; CHECK:             r0 = 0
+; CHECK-NEXT:        r0 <<= 56
+; CHECK-NEXT:        r0 s>>= 56
+  ret i32 %2, !dbg !15
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   54
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
+; CHECK-NEXT:        .long   218103808               # 0xd000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   97                      # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=17
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   44
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   64
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2068                    # Line 2 Col 20
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
+
+attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!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 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 8.0.20181009 "}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 2, column: 20, scope: !7)
+!12 = !{!13, !13, i64 0}
+!13 = !{!"omnipotent char", !14, i64 0}
+!14 = !{!"Simple C/C++ TBAA"}
+!15 = !DILocation(line: 2, column: 13, scope: !7)
diff --git a/llvm/test/CodeGen/BPF/CORE/patchable-extern-uint.ll b/llvm/test/CodeGen/BPF/CORE/patchable-extern-uint.ll
new file mode 100644
index 0000000..ba3770b
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/patchable-extern-uint.ll
@@ -0,0 +1,102 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   extern __attribute__((section(".BPF.patchable_externs"))) unsigned a;
+;   int foo() { return a; }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+@a = external dso_local local_unnamed_addr global i32, section ".BPF.patchable_externs", align 4
+
+; Function Attrs: norecurse nounwind readonly
+define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
+  %1 = load i32, i32* @a, align 4, !dbg !11, !tbaa !12
+; CHECK:             r0 = 0
+; CHECK-NEXT:        exit
+  ret i32 %1, !dbg !16
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   49
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
+; CHECK-NEXT:        .long   218103808               # 0xd000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   97                      # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/yhs/work/tests/llvm/test.c" # string offset=17
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
+
+attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!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 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 8.0.20181009 "}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 2, column: 20, scope: !7)
+!12 = !{!13, !13, i64 0}
+!13 = !{!"int", !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
+!16 = !DILocation(line: 2, column: 13, scope: !7)
diff --git a/llvm/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll b/llvm/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll
new file mode 100644
index 0000000..c483cce
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/CORE/patchable-extern-ulonglong.ll
@@ -0,0 +1,103 @@
+; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck -check-prefixes=CHECK %s
+; Source code:
+;   extern __attribute__((section(".BPF.patchable_externs"))) unsigned long long a;
+;   int foo() { return a; }
+; Compilation flag:
+;   clang -target bpf -O2 -g -S -emit-llvm test.c
+
+@a = external dso_local local_unnamed_addr global i64, section ".BPF.patchable_externs", align 8
+
+; Function Attrs: norecurse nounwind readonly
+define dso_local i32 @foo() local_unnamed_addr #0 !dbg !7 {
+  %1 = load i64, i64* @a, align 8, !dbg !11, !tbaa !12
+  %2 = trunc i64 %1 to i32, !dbg !11
+; CHECK:             r0 = 0 ll
+; CHECK-NEXT:        exit
+  ret i32 %2, !dbg !16
+}
+
+; CHECK:             .section        .BTF,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   24
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   54
+; CHECK-NEXT:        .long   0                       # BTF_KIND_FUNC_PROTO(id = 1)
+; CHECK-NEXT:        .long   218103808               # 0xd000000
+; CHECK-NEXT:        .long   2
+; CHECK-NEXT:        .long   1                       # BTF_KIND_INT(id = 2)
+; CHECK-NEXT:        .long   16777216                # 0x1000000
+; CHECK-NEXT:        .long   4
+; CHECK-NEXT:        .long   16777248                # 0x1000020
+; CHECK-NEXT:        .long   5                       # BTF_KIND_FUNC(id = 3)
+; CHECK-NEXT:        .long   201326592               # 0xc000000
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .byte   0                       # string offset=0
+; CHECK-NEXT:        .ascii  "int"                   # string offset=1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "foo"                   # string offset=5
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  ".text"                 # string offset=9
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .byte   97                      # string offset=15
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .ascii  "/tmp/home/yhs/work/tests/llvm/test.c" # string offset=17
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .section        .BTF.ext,"",@progbits
+; CHECK-NEXT:        .short  60319                   # 0xeb9f
+; CHECK-NEXT:        .byte   1
+; CHECK-NEXT:        .byte   0
+; CHECK-NEXT:        .long   40
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   28
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   48
+; CHECK-NEXT:        .long   20
+; CHECK-NEXT:        .long   8                       # FuncInfo
+; CHECK-NEXT:        .long   9                       # FuncInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Lfunc_begin0
+; CHECK-NEXT:        .long   3
+; CHECK-NEXT:        .long   16                      # LineInfo
+; CHECK-NEXT:        .long   9                       # LineInfo section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   17
+; CHECK-NEXT:        .long   0
+; CHECK-NEXT:        .long   2061                    # Line 2 Col 13
+; CHECK-NEXT:        .long   8                       # ExternReloc
+; CHECK-NEXT:        .long   9                       # Extern reloc section string offset=9
+; CHECK-NEXT:        .long   1
+; CHECK-NEXT:        .long   .Ltmp{{[0-9]+}}
+; CHECK-NEXT:        .long   15
+
+attributes #0 = { norecurse nounwind readonly "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
+
+!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 8.0.20181009 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = !{i32 1, !"wchar_size", i32 4}
+!6 = !{!"clang version 8.0.20181009 "}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: true, unit: !0, retainedNodes: !2)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !DILocation(line: 2, column: 20, scope: !7)
+!12 = !{!13, !13, i64 0}
+!13 = !{!"long long", !14, i64 0}
+!14 = !{!"omnipotent char", !15, i64 0}
+!15 = !{!"Simple C/C++ TBAA"}
+!16 = !DILocation(line: 2, column: 13, scope: !7)
diff --git a/llvm/test/CodeGen/BPF/reloc-btf-2.ll b/llvm/test/CodeGen/BPF/reloc-btf-2.ll
index feabb08..2871daa 100644
--- a/llvm/test/CodeGen/BPF/reloc-btf-2.ll
+++ b/llvm/test/CodeGen/BPF/reloc-btf-2.ll
@@ -47,7 +47,7 @@
 !11 = !{i32 2, !"Debug Info Version", i32 3}
 !12 = !{i32 1, !"wchar_size", i32 4}
 !13 = !{!"clang version 9.0.0 (trunk 360739) (llvm/trunk 360747)"}
-!14 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !4)
+!14 = distinct !DISubprogram(name: "test", scope: !3, file: !3, line: 3, type: !15, scopeLine: 3, isLocal: false, isDefinition: true, isOptimized: true, unit: !2, retainedNodes: !4)
 !15 = !DISubroutineType(types: !16)
 !16 = !{!9}
 !17 = !DILocation(line: 4, column: 10, scope: !14)