llvm-project/lld/test/ELF/basic-block-sections-delete...

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

129 lines
2.7 KiB
ArmAsm
Raw Normal View History

LLD Support for Basic Block Sections This is part of the Propeller framework to do post link code layout optimizations. Please see the RFC here: https://groups.google.com/forum/#!msg/llvm-dev/ef3mKzAdJ7U/1shV64BYBAAJ and the detailed RFC doc here: https://github.com/google/llvm-propeller/blob/plo-dev/Propeller_RFC.pdf This patch adds lld support for basic block sections and performs relaxations after the basic blocks have been reordered. After the linker has reordered the basic block sections according to the desired sequence, it runs a relaxation pass to optimize jump instructions. Currently, the compiler emits the long form of all jump instructions. AMD64 ISA supports variants of jump instructions with one byte offset or a four byte offset. The compiler generates jump instructions with R_X86_64 32-bit PC relative relocations. We would like to use a new relocation type for these jump instructions as it makes it easy and accurate while relaxing these instructions. The relaxation pass does two things: First, it deletes all explicit fall-through direct jump instructions between adjacent basic blocks. This is done by discarding the tail of the basic block section. Second, If there are consecutive jump instructions, it checks if the first conditional jump can be inverted to convert the second into a fall through and delete the second. The jump instructions are relaxed by using jump instruction mods, something like relocations. These are used to modify the opcode of the jump instruction. Jump instruction mods contain three values, instruction offset, jump type and size. While writing this jump instruction out to the final binary, the linker uses the jump instruction mod to determine the opcode and the size of the modified jump instruction. These mods are required because the input object files are memory-mapped without write permissions and directly modifying the object files requires copying these sections. Copying a large number of basic block sections significantly bloats memory. Differential Revision: https://reviews.llvm.org/D68065
2020-04-07 21:48:18 +08:00
# REQUIRES: x86
## basic-block-sections tests.
LLD Support for Basic Block Sections This is part of the Propeller framework to do post link code layout optimizations. Please see the RFC here: https://groups.google.com/forum/#!msg/llvm-dev/ef3mKzAdJ7U/1shV64BYBAAJ and the detailed RFC doc here: https://github.com/google/llvm-propeller/blob/plo-dev/Propeller_RFC.pdf This patch adds lld support for basic block sections and performs relaxations after the basic blocks have been reordered. After the linker has reordered the basic block sections according to the desired sequence, it runs a relaxation pass to optimize jump instructions. Currently, the compiler emits the long form of all jump instructions. AMD64 ISA supports variants of jump instructions with one byte offset or a four byte offset. The compiler generates jump instructions with R_X86_64 32-bit PC relative relocations. We would like to use a new relocation type for these jump instructions as it makes it easy and accurate while relaxing these instructions. The relaxation pass does two things: First, it deletes all explicit fall-through direct jump instructions between adjacent basic blocks. This is done by discarding the tail of the basic block section. Second, If there are consecutive jump instructions, it checks if the first conditional jump can be inverted to convert the second into a fall through and delete the second. The jump instructions are relaxed by using jump instruction mods, something like relocations. These are used to modify the opcode of the jump instruction. Jump instruction mods contain three values, instruction offset, jump type and size. While writing this jump instruction out to the final binary, the linker uses the jump instruction mod to determine the opcode and the size of the modified jump instruction. These mods are required because the input object files are memory-mapped without write permissions and directly modifying the object files requires copying these sections. Copying a large number of basic block sections significantly bloats memory. Differential Revision: https://reviews.llvm.org/D68065
2020-04-07 21:48:18 +08:00
## This simple test checks if redundant direct jumps are converted to
## implicit fallthrus. The jcc's must be converted to their inverted
## opcode, for instance jne to je and jmp must be deleted.
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
# RUN: ld.lld --optimize-bb-jumps %t.o -o %t.out
# RUN: llvm-objdump -d %t.out| FileCheck %s
# CHECK: <foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jne 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
.section .text,"ax",@progbits
.type foo,@function
foo:
nopl (%rax)
je a.BB.foo
jmp r.BB.foo
# CHECK: <a.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: je 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
.section .text,"ax",@progbits,unique,3
a.BB.foo:
nopl (%rax)
jne aa.BB.foo
jmp r.BB.foo
# CHECK: <aa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jle 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,4
aa.BB.foo:
nopl (%rax)
jg aaa.BB.foo
jmp r.BB.foo
# CHECK: <aaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jl 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,5
aaa.BB.foo:
nopl (%rax)
jge aaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jae 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,6
aaaa.BB.foo:
nopl (%rax)
jb aaaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: ja 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,7
aaaaa.BB.foo:
nopl (%rax)
jbe aaaaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jge 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,8
aaaaaa.BB.foo:
nopl (%rax)
jl aaaaaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaaaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jg 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,9
aaaaaaa.BB.foo:
nopl (%rax)
jle aaaaaaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaaaaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jbe 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,10
aaaaaaaa.BB.foo:
nopl (%rax)
ja aaaaaaaaa.BB.foo
jmp r.BB.foo
# CHECK: <aaaaaaaaa.BB.foo>:
# CHECK-NEXT: nopl (%rax)
# CHECK-NEXT: jb 0x{{[[:xdigit:]]+}} <r.BB.foo>
# CHECK-NOT: jmp
#
.section .text,"ax",@progbits,unique,11
aaaaaaaaa.BB.foo:
nopl (%rax)
jae aaaaaaaaaa.BB.foo
jmp r.BB.foo
.section .text,"ax",@progbits,unique,20
aaaaaaaaaa.BB.foo:
nopl (%rax)
r.BB.foo:
ret