Files
llvm-project/llvm/test/CodeGen/X86/kcfi-patchable-function-prefix.ll
Fangrui Song 193d7a6ace [MC,CodeGen] Update .prefalign for symbol-based preferred alignment (#184032)
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.
2026-04-11 06:16:43 +00:00

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}