Trevor Gross a78a0f8d20
[X86] Align f128 and i128 to 16 bytes when passing on x86-32 (#138092)
The i386 psABI specifies that `__float128` has 16 byte alignment and
must be passed on the stack; however, LLVM currently stores it in a
stack slot that has an offset of 4. Add a custom lowering to correct
this alignment to 16-byte.

i386 does not specify an `__int128`, but it seems reasonable to keep the
same behavior as `__float128` so this is changed as well. There also
isn't a good way to distinguish whether a set of four registers came
from an integer or a float.

The main test demonstrating this change is `store_perturbed` in
`llvm/test/CodeGen/X86/i128-fp128-abi.ll`.

Referenced ABI:
https://gitlab.com/x86-psABIs/i386-ABI/-/wikis/uploads/14c05f1b1e156e0e46b61bfa7c1df1e2/intel386-psABI-2020-08-07.pdf
Fixes: https://github.com/llvm/llvm-project/issues/77401
2025-07-17 11:30:36 +02:00

131 lines
4.0 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s --check-prefix=X64
; RUN: llc < %s -mtriple=i386-unknown | FileCheck %s --check-prefix=X86
define i128 @foo(i128 %t, i128 %u) {
; X64-LABEL: foo:
; X64: # %bb.0:
; X64-NEXT: movq %rdx, %r8
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: imulq %rdi, %rcx
; X64-NEXT: mulq %rdx
; X64-NEXT: addq %rcx, %rdx
; X64-NEXT: imulq %rsi, %r8
; X64-NEXT: addq %r8, %rdx
; X64-NEXT: retq
;
; X86-LABEL: foo:
; X86: # %bb.0:
; X86-NEXT: pushl %ebp
; X86-NEXT: .cfi_def_cfa_offset 8
; X86-NEXT: .cfi_offset %ebp, -8
; X86-NEXT: movl %esp, %ebp
; X86-NEXT: .cfi_def_cfa_register %ebp
; X86-NEXT: pushl %ebx
; X86-NEXT: pushl %edi
; X86-NEXT: pushl %esi
; X86-NEXT: andl $-16, %esp
; X86-NEXT: subl $16, %esp
; X86-NEXT: .cfi_offset %esi, -20
; X86-NEXT: .cfi_offset %edi, -16
; X86-NEXT: .cfi_offset %ebx, -12
; X86-NEXT: movl 32(%ebp), %ecx
; X86-NEXT: movl 40(%ebp), %edi
; X86-NEXT: movl 44(%ebp), %esi
; X86-NEXT: imull %ecx, %esi
; X86-NEXT: movl %edi, %eax
; X86-NEXT: mull %ecx
; X86-NEXT: movl %eax, (%esp) # 4-byte Spill
; X86-NEXT: movl %edx, %ebx
; X86-NEXT: addl %esi, %ebx
; X86-NEXT: movl 36(%ebp), %eax
; X86-NEXT: imull %edi, %eax
; X86-NEXT: addl %eax, %ebx
; X86-NEXT: movl 48(%ebp), %eax
; X86-NEXT: movl %eax, %ecx
; X86-NEXT: imull 28(%ebp), %ecx
; X86-NEXT: movl 24(%ebp), %edi
; X86-NEXT: mull %edi
; X86-NEXT: addl %ecx, %edx
; X86-NEXT: movl 52(%ebp), %esi
; X86-NEXT: imull %edi, %esi
; X86-NEXT: addl %edx, %esi
; X86-NEXT: addl (%esp), %eax # 4-byte Folded Reload
; X86-NEXT: movl %eax, (%esp) # 4-byte Spill
; X86-NEXT: adcl %ebx, %esi
; X86-NEXT: movl %edi, %eax
; X86-NEXT: movl 40(%ebp), %ecx
; X86-NEXT: mull %ecx
; X86-NEXT: movl %edx, %ebx
; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: movl 28(%ebp), %eax
; X86-NEXT: mull %ecx
; X86-NEXT: movl %edx, %edi
; X86-NEXT: movl %eax, %ecx
; X86-NEXT: addl %ebx, %ecx
; X86-NEXT: adcl $0, %edi
; X86-NEXT: movl 24(%ebp), %eax
; X86-NEXT: mull 44(%ebp)
; X86-NEXT: movl %edx, %ebx
; X86-NEXT: addl %ecx, %eax
; X86-NEXT: movl %eax, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
; X86-NEXT: adcl %edi, %ebx
; X86-NEXT: setb %cl
; X86-NEXT: movl 28(%ebp), %eax
; X86-NEXT: mull 44(%ebp)
; X86-NEXT: addl %ebx, %eax
; X86-NEXT: movzbl %cl, %ecx
; X86-NEXT: adcl %ecx, %edx
; X86-NEXT: addl (%esp), %eax # 4-byte Folded Reload
; X86-NEXT: adcl %esi, %edx
; X86-NEXT: movl 8(%ebp), %ecx
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
; X86-NEXT: movl %esi, 4(%ecx)
; X86-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %esi # 4-byte Reload
; X86-NEXT: movl %esi, (%ecx)
; X86-NEXT: movl %eax, 8(%ecx)
; X86-NEXT: movl %edx, 12(%ecx)
; X86-NEXT: movl %ecx, %eax
; X86-NEXT: leal -12(%ebp), %esp
; X86-NEXT: popl %esi
; X86-NEXT: popl %edi
; X86-NEXT: popl %ebx
; X86-NEXT: popl %ebp
; X86-NEXT: .cfi_def_cfa %esp, 4
; X86-NEXT: retl $4
%k = mul i128 %t, %u
ret i128 %k
}
@aaa = external dso_local global i128
@bbb = external dso_local global i128
define void @PR13897() nounwind {
; X64-LABEL: PR13897:
; X64: # %bb.0: # %"0x0"
; X64-NEXT: movq bbb(%rip), %rax
; X64-NEXT: movl %eax, %ecx
; X64-NEXT: shlq $32, %rax
; X64-NEXT: orq %rcx, %rax
; X64-NEXT: movq %rax, aaa+8(%rip)
; X64-NEXT: movq %rax, aaa(%rip)
; X64-NEXT: retq
;
; X86-LABEL: PR13897:
; X86: # %bb.0: # %"0x0"
; X86-NEXT: movl bbb, %eax
; X86-NEXT: movl %eax, aaa+12
; X86-NEXT: movl %eax, aaa+8
; X86-NEXT: movl %eax, aaa+4
; X86-NEXT: movl %eax, aaa
; X86-NEXT: retl
"0x0":
%0 = load i128, ptr @bbb
%1 = and i128 %0, 4294967295
%2 = shl i128 %0, 96
%3 = mul i128 %1, 18446744078004518913
%4 = add i128 %3, %2
store i128 %4, ptr @aaa
ret void
}