158 lines · plain
1## Check that in lite mode llvm-bolt updates function references in2## non-optimized code.3 4# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown %s -o %t.o5# RUN: llvm-mc -filetype=obj -triple aarch64-unknown-unknown \6# RUN: --defsym COMPACT=1 %s -o %t.compact.o7# RUN: link_fdata %s %t.o %t.fdata8# RUN: llvm-strip --strip-unneeded %t*.o9# RUN: %clang %cflags %t.o -o %t.exe -Wl,-q -static10# RUN: %clang %cflags %t.compact.o -o %t.compact.exe -Wl,-q -static11# RUN: llvm-bolt %t.exe -o %t.bolt --data %t.fdata --lite12# RUN: llvm-bolt %t.compact.exe -o %t.compact.bolt --data %t.fdata --lite \13# RUN: --compact-code-model14# RUN: llvm-objdump -d --disassemble-symbols=cold_function %t.exe \15# RUN: | FileCheck %s --check-prefix=CHECK-INPUT16# RUN: llvm-objdump -d --disassemble-symbols=cold_function %t.bolt \17# RUN: | FileCheck %s18# RUN: llvm-objdump -d --disassemble-symbols=_start.org.0 %t.bolt \19# RUN: | FileCheck %s --check-prefix=CHECK-PATCH20# RUN: llvm-objdump -d %t.compact.bolt \21# RUN: | FileCheck %s --check-prefix=CHECK-COMPACT22 23## In compact mode, make sure we do not create an unnecessary patch thunk.24# CHECK-COMPACT-NOT: <_start.org.0>25 26## Verify that the number of FDEs matches the number of functions in the output27## binary. There are three original functions and two optimized.28## NOTE: at the moment we are emitting extra FDEs for patched functions, thus29## there is one more FDE for _start.30# RUN: llvm-readelf -u %t.bolt | grep -wc FDE \31# RUN: | FileCheck --check-prefix=CHECK-FDE %s32# CHECK-FDE: 633 34## In lite mode, optimized code will be separated from the original .text by35## over 128MB, making it impossible for call/bl instructions in cold functions36## to reach optimized functions directly.37 38 .text39 .globl _start40 .type _start, %function41_start:42# FDATA: 0 [unknown] 0 1 _start 0 0 10043 .cfi_startproc44 45## Check that the code at the original location is converted into a46## veneer/thunk.47# CHECK-PATCH-LABEL: <_start.org.0>48# CHECK-PATCH-NEXT: adrp x1649# CHECK-PATCH-NEXT: add x16, x16,50# CHECK-PATCH-NEXT: br x1651 cmp x0, 152 b.eq .L053 bl cold_function54.L0:55 ret x3056 .cfi_endproc57 .size _start, .-_start58 59## Cold non-optimized function with references to hot functions.60# CHECK: Disassembly of section .bolt.org.text:61# CHECK-LABEL: <cold_function>62 .globl cold_function63 .type cold_function, %function64cold_function:65 .cfi_startproc66 67## Absolute 64-bit function pointer reference.68## We check for the lower 16 bits of _start to be zeros after update.69 movz x0, :abs_g3:_start70 movk x0, :abs_g2_nc:_start71 movk x0, :abs_g1_nc:_start72# CHECK-INPUT-NOT: movk x0, #0x0{{$}}73# CHECK: movk x0, #0x0{{$}}74 movk x0, :abs_g0_nc:_start75 76## Relaxable address reference.77# CHECK-INPUT: nop78# CHECK-INPUT-NEXT: adr x179# CHECK-NEXT: adrp x1, [[ADDR:0x[0-9a-f]+]] <{{.*}}>80# CHECK-NEXT: add x181 adrp x1, _start82 add x1, x1, :lo12:_start83 84## Non-relaxable address reference.85# CHECK-INPUT-NEXT: adrp x286# CHECK-INPUT-NEXT: add x287# CHECK-NEXT: adrp x2, [[ADDR]]88# CHECK-NEXT: add x289 adrp x2, far_func90 add x2, x2, :lo12:far_func91 92## Check that fully-relaxed GOT reference is converted into ADRP+ADD.93 adrp x3, :got:_start94 ldr x3, [x3, #:got_lo12:_start]95# CHECK-INPUT-NEXT: nop96# CHECK-INPUT-NEXT: adr x397# CHECK-NEXT: adrp x3, [[ADDR]]98# CHECK-NEXT: add x399 100## Check that partially-relaxed GOT reference is converted into ADRP+ADD.101 adrp x4, :got:far_func102 ldr x4, [x4, #:got_lo12:far_func]103# CHECK-INPUT-NEXT: adrp x4104# CHECK-INPUT-NEXT: add x4105# CHECK-NEXT: adrp x4, [[ADDR]]106# CHECK-NEXT: add x4107 108## Check that non-relaxable GOT load is left intact.109 adrp x5, :got:far_func110 nop111 ldr x5, [x5, #:got_lo12:far_func]112# CHECK-INPUT-NEXT: adrp x5113# CHECK-INPUT-NEXT: nop114# CHECK-INPUT-NEXT: ldr x5115# CHECK-NEXT: adrp x5116# CHECK-NOT: [[ADDR]]117# CHECK-NEXT: nop118# CHECK-NEXT: ldr x5119 120## Since _start is relocated further than 128MB from the call site, we check121## that the call is converted into a call to its original version. That original122## version should contain a veneer/thunk code that we check separately.123 bl _start124# CHECK-INPUT-NEXT: bl {{.*}} <_start>125# CHECK-NEXT: bl {{.*}} <_start.org.0>126 127## Same as above, but the instruction is a tail call.128 b _start129# CHECK-INPUT-NEXT: b {{.*}} <_start>130# CHECK-NEXT: b {{.*}} <_start.org.0>131 132## Quick test for conditional tail calls. A proper test is being added in:133## https://github.com/llvm/llvm-project/pull/139565134## For now check that llvm-bolt doesn't choke on CTCs.135.ifndef COMPACT136 b.eq _start137 cbz x0, _start138 tbz x0, 42, _start139.endif140 141 .cfi_endproc142 .size cold_function, .-cold_function143 144.ifndef COMPACT145## Reserve 128MB of space to make functions that follow unreachable by ADRs in146## code that precedes this gap.147.space 0x8000000148.endif149 150 .globl far_func151 .type far_func, %function152far_func:153# FDATA: 0 [unknown] 0 1 far_func 0 0 100154 .cfi_startproc155 ret x30156 .cfi_endproc157 .size far_func, .-far_func158