https://discourse.llvm.org/t/rfc-enhancing-function-alignment-attributes/88019/17 The recently-introduced .prefalign only worked when each function was in its own section (-ffunction-sections), because the section size gave the function body size needed for the alignment rule. This led to -ffunction-sections and -fno-function-sections AsmPrinter differences (#155529), which is rather unusual. This patch fixes this AsmPrinter difference by extending .prefalign to accept an end symbol and a required fill operand: .prefalign <log2_align>, <end_sym>, nop .prefalign <log2_align>, <end_sym>, <fill_byte> The first operand is a log2 alignment value (e.g. 4 means 16-byte alignment). The body size (end_sym_offset - start_offset) determines the alignment: body_size < pref_align => ComputedAlign = std::bit_ceil(body_size) body_size >= pref_align => ComputedAlign = pref_align To also enforce a minimum alignment, emit a .p2align before .prefalign. The fill operand is required: `nop` generates target-appropriate NOP instructions via writeNopData, while an integer in [0,255] fills the padding with that byte value. Initialize MCSection::CurFragList to nullptr and add a null check to skip ELFObjectWriter-created sections like .strtab/.symtab that never receive changeSection calls. relaxPrefAlign is called in both layoutSection and relaxFragment. The layoutSection call ensures correct initial padding before relaxOnce, and is also needed for the post-finishLayout re-layout where relaxOnce is not used. relaxPrefAlign walks forward to the end symbol to compute BodySize (summing fragment sizes), avoiding dependence on stale downstream symbol offsets.
54 lines
1.5 KiB
LLVM
54 lines
1.5 KiB
LLVM
; RUN: llc -mtriple=x86_64-unknown-linux-gnu -verify-machineinstrs < %s | FileCheck %s
|
|
|
|
; CHECK: .prefalign 4, .Lfunc_end0, nop
|
|
; CHECK-LABEL: __cfi_f1:
|
|
; CHECK-COUNT-11: nop
|
|
; CHECK-NEXT: movl $12345678, %eax
|
|
; CHECK-LABEL: .Lcfi_func_end0:
|
|
; CHECK-NEXT: .size __cfi_f1, .Lcfi_func_end0-__cfi_f1
|
|
; CHECK-LABEL: f1:
|
|
define void @f1(ptr noundef %x) !kcfi_type !1 {
|
|
; CHECK: addl -4(%r{{..}}), %r10d
|
|
call void %x() [ "kcfi"(i32 12345678) ]
|
|
ret void
|
|
}
|
|
; CHECK: .Lfunc_end0:
|
|
|
|
; CHECK: .prefalign 4
|
|
; CHECK-NOT: __cfi_f2:
|
|
; CHECK-NOT: {{^[[:space:]]+}}nop
|
|
; CHECK-LABEL: f2:
|
|
define void @f2(ptr noundef %x) {
|
|
; CHECK: addl -4(%r{{..}}), %r10d
|
|
call void %x() [ "kcfi"(i32 12345678) ]
|
|
ret void
|
|
}
|
|
|
|
; CHECK: .prefalign 4
|
|
; CHECK-LABEL: __cfi_f3:
|
|
; CHECK-NOT: {{^[[:space:]]+}}nop
|
|
; CHECK-NEXT: movl $12345678, %eax
|
|
; CHECK-COUNT-11: nop
|
|
; CHECK-LABEL: f3:
|
|
define void @f3(ptr noundef %x) #0 !kcfi_type !1 {
|
|
; CHECK: addl -15(%r{{..}}), %r10d
|
|
call void %x() [ "kcfi"(i32 12345678) ]
|
|
ret void
|
|
}
|
|
|
|
; CHECK: .prefalign 4
|
|
; CHECK-NOT: __cfi_f4:
|
|
; CHECK-COUNT-16: {{^[[:space:]]+}}nop
|
|
; CHECK-LABEL: f4:
|
|
define void @f4(ptr noundef %x) #0 {
|
|
; CHECK: addl -15(%r{{..}}), %r10d
|
|
call void %x() [ "kcfi"(i32 12345678) ]
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { "patchable-function-prefix"="11" }
|
|
|
|
!llvm.module.flags = !{!0}
|
|
!0 = !{i32 4, !"kcfi", i32 1}
|
|
!1 = !{i32 12345678}
|