[clang] [llvm] [SystemZ] Add support for half (fp16) (PR #109164)

Matt Arsenault via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 7 00:16:36 PDT 2024


================
@@ -0,0 +1,201 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z16 | FileCheck %s
+;
+; Tests for 16-bit floating point (half).
+
+; Incoming half arguments added together and returned.
+define half @fun0(half %Op0, half %Op1) {
+; CHECK-LABEL: fun0:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stmg %r13, %r15, 104(%r15)
+; CHECK-NEXT:    .cfi_offset %r13, -56
+; CHECK-NEXT:    .cfi_offset %r14, -48
+; CHECK-NEXT:    .cfi_offset %r15, -40
+; CHECK-NEXT:    aghi %r15, -168
+; CHECK-NEXT:    .cfi_def_cfa_offset 328
+; CHECK-NEXT:    std %f8, 160(%r15) # 8-byte Folded Spill
+; CHECK-NEXT:    .cfi_offset %f8, -168
+; CHECK-NEXT:    vlgvf %r0, %v2, 0
+; CHECK-NEXT:    llghr %r2, %r0
+; CHECK-NEXT:    vlgvf %r13, %v0, 0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    llghr %r2, %r13
+; CHECK-NEXT:    ldr %f8, %f0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    aebr %f0, %f8
+; CHECK-NEXT:    brasl %r14, __gnu_f2h_ieee at PLT
+; CHECK-NEXT:    ld %f8, 160(%r15) # 8-byte Folded Reload
+; CHECK-NEXT:    vlvgf %v0, %r2, 0
+; CHECK-NEXT:    lmg %r13, %r15, 272(%r15)
+; CHECK-NEXT:    br %r14
+entry:
+  %Res = fadd half %Op0, %Op1
+  ret half %Res
+}
+
+; The half values are loaded and stored instead.
+define void @fun1(ptr %Op0, ptr %Op1, ptr %Dst) {
+; CHECK-LABEL: fun1:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stmg %r12, %r15, 96(%r15)
+; CHECK-NEXT:    .cfi_offset %r12, -64
+; CHECK-NEXT:    .cfi_offset %r13, -56
+; CHECK-NEXT:    .cfi_offset %r14, -48
+; CHECK-NEXT:    .cfi_offset %r15, -40
+; CHECK-NEXT:    aghi %r15, -168
+; CHECK-NEXT:    .cfi_def_cfa_offset 328
+; CHECK-NEXT:    std %f8, 160(%r15) # 8-byte Folded Spill
+; CHECK-NEXT:    .cfi_offset %f8, -168
+; CHECK-NEXT:    llgh %r12, 0(%r2)
+; CHECK-NEXT:    llgh %r2, 0(%r3)
+; CHECK-NEXT:    lgr %r13, %r4
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    lgr %r2, %r12
+; CHECK-NEXT:    ldr %f8, %f0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    aebr %f0, %f8
+; CHECK-NEXT:    brasl %r14, __gnu_f2h_ieee at PLT
+; CHECK-NEXT:    ld %f8, 160(%r15) # 8-byte Folded Reload
+; CHECK-NEXT:    sth %r2, 0(%r13)
+; CHECK-NEXT:    lmg %r12, %r15, 264(%r15)
+; CHECK-NEXT:    br %r14
+entry:
+  %0 = load half, ptr %Op0, align 2
+  %1 = load half, ptr %Op1, align 2
+  %add = fadd half %0, %1
+  store half %add, ptr %Dst, align 2
+  ret void
+}
+
+; Test a chain of half operations which should have each operation surrounded
+; by conversions to/from fp32 for proper emulation.
+define half @fun2(half %Op0, half %Op1, half %Op2) {
+; CHECK-LABEL: fun2:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stmg %r12, %r15, 96(%r15)
+; CHECK-NEXT:    .cfi_offset %r12, -64
+; CHECK-NEXT:    .cfi_offset %r13, -56
+; CHECK-NEXT:    .cfi_offset %r14, -48
+; CHECK-NEXT:    .cfi_offset %r15, -40
+; CHECK-NEXT:    aghi %r15, -168
+; CHECK-NEXT:    .cfi_def_cfa_offset 328
+; CHECK-NEXT:    std %f8, 160(%r15) # 8-byte Folded Spill
+; CHECK-NEXT:    .cfi_offset %f8, -168
+; CHECK-NEXT:    vlgvf %r0, %v2, 0
+; CHECK-NEXT:    llghr %r2, %r0
+; CHECK-NEXT:    vlgvf %r13, %v4, 0
+; CHECK-NEXT:    vlgvf %r12, %v0, 0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    llghr %r2, %r12
+; CHECK-NEXT:    ldr %f8, %f0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    aebr %f0, %f8
+; CHECK-NEXT:    brasl %r14, __gnu_f2h_ieee at PLT
+; CHECK-NEXT:    llghr %r2, %r2
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    llghr %r2, %r13
+; CHECK-NEXT:    ldr %f8, %f0
+; CHECK-NEXT:    brasl %r14, __gnu_h2f_ieee at PLT
+; CHECK-NEXT:    wfasb %f0, %f8, %f0
+; CHECK-NEXT:    brasl %r14, __gnu_f2h_ieee at PLT
+; CHECK-NEXT:    ld %f8, 160(%r15) # 8-byte Folded Reload
+; CHECK-NEXT:    vlvgf %v0, %r2, 0
+; CHECK-NEXT:    lmg %r12, %r15, 264(%r15)
+; CHECK-NEXT:    br %r14
+entry:
+  %A0 = fadd half %Op0, %Op1
+  %Res = fadd half %A0, %Op2
+  ret half %Res
+}
+
+; Store an incoming half argument and return a loaded one.
+define half @fun3(half %Op0, ptr %Dst, ptr %Src) {
+; CHECK-LABEL: fun3:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    vlgvf %r0, %v0, 0
+; CHECK-NEXT:    sth %r0, 0(%r2)
+; CHECK-NEXT:    lh %r0, 0(%r3)
+; CHECK-NEXT:    vlvgf %v0, %r0, 0
+; CHECK-NEXT:    br %r14
+entry:
+  store half %Op0, ptr %Dst
+
+  %Res = load half, ptr %Src
+  ret half %Res
+}
+
+; Call a function with half argument and return values.
+declare half @foo(half)
+define void @fun4(ptr %Src, ptr %Dst) {
+; CHECK-LABEL: fun4:
+; CHECK:       # %bb.0: # %entry
+; CHECK-NEXT:    stmg %r13, %r15, 104(%r15)
+; CHECK-NEXT:    .cfi_offset %r13, -56
+; CHECK-NEXT:    .cfi_offset %r14, -48
+; CHECK-NEXT:    .cfi_offset %r15, -40
+; CHECK-NEXT:    aghi %r15, -160
+; CHECK-NEXT:    .cfi_def_cfa_offset 320
+; CHECK-NEXT:    lh %r0, 0(%r2)
+; CHECK-NEXT:    vlvgf %v0, %r0, 0
+; CHECK-NEXT:    lgr %r13, %r3
+; CHECK-NEXT:    brasl %r14, foo at PLT
+; CHECK-NEXT:    vlgvf %r0, %v0, 0
+; CHECK-NEXT:    sth %r0, 0(%r13)
+; CHECK-NEXT:    lmg %r13, %r15, 264(%r15)
+; CHECK-NEXT:    br %r14
+entry:
+  %arg = load half, ptr %Src
+  %Res = call half @foo(half %arg)
+  store half %Res, ptr %Dst
+  ret void
+}
----------------
arsenm wrote:

Test a tail call too 

https://github.com/llvm/llvm-project/pull/109164


More information about the cfe-commits mailing list