| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 | |
| ; Test that library calls are emitted for LLVM IR intrinsics | |
| ; | |
| ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s | |
| define half @f1(half %x, i16 %y) nounwind { | |
| ; CHECK-LABEL: f1: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r13, %r15, 104(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: lhr %r13, %r2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: llgfr %r2, %r13 | |
| ; CHECK-NEXT: brasl %r14, __powisf2@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r13, %r15, 264(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.powi.f16.i16(half %x, i16 %y) | |
| ret half %tmp | |
| } | |
| define half @f2(half %x, half %y) nounwind { | |
| ; CHECK-LABEL: f2: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -176 | |
| ; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: ler %f8, %f2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f9, %f0 | |
| ; CHECK-NEXT: ler %f0, %f8 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f2, %f0 | |
| ; CHECK-NEXT: ler %f0, %f9 | |
| ; CHECK-NEXT: brasl %r14, powf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: lmg %r14, %r15, 288(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.pow.f16(half %x, half %y) | |
| ret half %tmp | |
| } | |
| define half @f3(half %x) nounwind { | |
| ; CHECK-LABEL: f3: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, sinf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.sin.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f4(half %x) nounwind { | |
| ; CHECK-LABEL: f4: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, cosf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.cos.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f5(half %x) nounwind { | |
| ; CHECK-LABEL: f5: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, expf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.exp.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f6(half %x) nounwind { | |
| ; CHECK-LABEL: f6: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, exp2f@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.exp2.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f7(half %x) nounwind { | |
| ; CHECK-LABEL: f7: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, logf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.log.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f8(half %x) nounwind { | |
| ; CHECK-LABEL: f8: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, log2f@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.log2.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f9(half %x) nounwind { | |
| ; CHECK-LABEL: f9: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -160 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: brasl %r14, log10f@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: lmg %r14, %r15, 272(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.log10.f16(half %x) | |
| ret half %tmp | |
| } | |
| define half @f10(half %x, half %y) nounwind { | |
| ; CHECK-LABEL: f10: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -176 | |
| ; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: ler %f8, %f2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f9, %f0 | |
| ; CHECK-NEXT: ler %f0, %f8 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f2, %f0 | |
| ; CHECK-NEXT: ler %f0, %f9 | |
| ; CHECK-NEXT: brasl %r14, fminf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: lmg %r14, %r15, 288(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.minnum.f16(half %x, half %y) | |
| ret half %tmp | |
| } | |
| define half @f11(half %x, half %y) nounwind { | |
| ; CHECK-LABEL: f11: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -176 | |
| ; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: ler %f8, %f2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f9, %f0 | |
| ; CHECK-NEXT: ler %f0, %f8 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f2, %f0 | |
| ; CHECK-NEXT: ler %f0, %f9 | |
| ; CHECK-NEXT: brasl %r14, fmaxf@PLT | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: lmg %r14, %r15, 288(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call half @llvm.maxnum.f16(half %x, half %y) | |
| ret half %tmp | |
| } | |
| ; Verify that "nnan" minnum/maxnum calls are transformed to | |
| ; compare+select sequences instead of libcalls. | |
| define half @f12(half %x, half %y) nounwind { | |
| ; CHECK-LABEL: f12: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -176 | |
| ; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: ler %f9, %f0 | |
| ; CHECK-NEXT: ler %f0, %f2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f8, %f0 | |
| ; CHECK-NEXT: ler %f0, %f9 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: cebr %f0, %f8 | |
| ; CHECK-NEXT: jl .LBB11_2 | |
| ; CHECK-NEXT: # %bb.1: | |
| ; CHECK-NEXT: ler %f0, %f8 | |
| ; CHECK-NEXT: .LBB11_2: | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: lmg %r14, %r15, 288(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call nnan half @llvm.minnum.f16(half %x, half %y) | |
| ret half %tmp | |
| } | |
| define half @f13(half %x, half %y) nounwind { | |
| ; CHECK-LABEL: f13: | |
| ; CHECK: # %bb.0: | |
| ; CHECK-NEXT: stmg %r14, %r15, 112(%r15) | |
| ; CHECK-NEXT: aghi %r15, -176 | |
| ; CHECK-NEXT: std %f8, 168(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: std %f9, 160(%r15) # 8-byte Spill | |
| ; CHECK-NEXT: ler %f9, %f0 | |
| ; CHECK-NEXT: ler %f0, %f2 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: ler %f8, %f0 | |
| ; CHECK-NEXT: ler %f0, %f9 | |
| ; CHECK-NEXT: brasl %r14, __extendhfsf2@PLT | |
| ; CHECK-NEXT: cebr %f0, %f8 | |
| ; CHECK-NEXT: jh .LBB12_2 | |
| ; CHECK-NEXT: # %bb.1: | |
| ; CHECK-NEXT: ler %f0, %f8 | |
| ; CHECK-NEXT: .LBB12_2: | |
| ; CHECK-NEXT: brasl %r14, __truncsfhf2@PLT | |
| ; CHECK-NEXT: ld %f8, 168(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: ld %f9, 160(%r15) # 8-byte Reload | |
| ; CHECK-NEXT: lmg %r14, %r15, 288(%r15) | |
| ; CHECK-NEXT: br %r14 | |
| %tmp = call nnan half @llvm.maxnum.f16(half %x, half %y) | |
| ret half %tmp | |
| } | |
| declare half @llvm.powi.f16.i16(half, i16) | |
| declare half @llvm.pow.f16(half, half) | |
| declare half @llvm.sin.f16(half) | |
| declare half @llvm.cos.f16(half) | |
| declare half @llvm.exp.f16(half) | |
| declare half @llvm.exp2.f16(half) | |
| declare half @llvm.log.f16(half) | |
| declare half @llvm.log2.f16(half) | |
| declare half @llvm.log10.f16(half) | |
| declare half @llvm.minnum.f16(half, half) | |
| declare half @llvm.maxnum.f16(half, half) |