These are long overdue for removal. These were originally a hack to support loading half values before there was any / decent support for the half type through the backend. There's no reason to continue supporting these, they're equivalent to fpext/fptrunc with a bitcast. SelectionDAG stopped translating these directly, and used the bitcast + fp cast since f7a02c17628e825, so there's been no reason to use these since 2014.
444 lines
12 KiB
LLVM
444 lines
12 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc %s -o - -mtriple=avr | FileCheck %s
|
|
|
|
; Tests for various operations on half precison float. Much of the test is
|
|
; copied from test/CodeGen/X86/half.ll.
|
|
|
|
define void @store(half %x, ptr %p) nounwind {
|
|
; CHECK-LABEL: store:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r22
|
|
; CHECK-NEXT: mov r31, r23
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
store half %x, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define half @return(ptr %p) nounwind {
|
|
; CHECK-LABEL: return:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: ret
|
|
%r = load half, ptr %p
|
|
ret half %r
|
|
}
|
|
|
|
define void @test_load_store(ptr %in, ptr %out) nounwind {
|
|
; CHECK-LABEL: test_load_store:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: mov r30, r22
|
|
; CHECK-NEXT: mov r31, r23
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
%val = load half, ptr %in
|
|
store half %val, ptr %out
|
|
ret void
|
|
}
|
|
|
|
define i16 @test_bitcast_from_half(ptr %addr) nounwind {
|
|
; CHECK-LABEL: test_bitcast_from_half:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: ret
|
|
%val = load half, ptr %addr
|
|
%val_int = bitcast half %val to i16
|
|
ret i16 %val_int
|
|
}
|
|
|
|
define void @test_bitcast_to_half(ptr %addr, i16 %in) nounwind {
|
|
; CHECK-LABEL: test_bitcast_to_half:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: std Z+1, r23
|
|
; CHECK-NEXT: st Z, r22
|
|
; CHECK-NEXT: ret
|
|
%val_fp = bitcast i16 %in to half
|
|
store half %val_fp, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define half @from_bits(i16 %x) nounwind {
|
|
; CHECK-LABEL: from_bits:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%res = bitcast i16 %x to half
|
|
ret half %res
|
|
}
|
|
|
|
define i16 @to_bits(half %x) nounwind {
|
|
; CHECK-LABEL: to_bits:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: ret
|
|
%res = bitcast half %x to i16
|
|
ret i16 %res
|
|
}
|
|
|
|
define float @test_extend32(ptr %addr) nounwind {
|
|
; CHECK-LABEL: test_extend32:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: ret
|
|
%val16 = load half, ptr %addr
|
|
%val32 = fpext half %val16 to float
|
|
ret float %val32
|
|
}
|
|
|
|
define double @test_extend64(ptr %addr) nounwind {
|
|
; CHECK-LABEL: test_extend64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: rcall __extendsfdf2
|
|
; CHECK-NEXT: ret
|
|
%val16 = load half, ptr %addr
|
|
%val32 = fpext half %val16 to double
|
|
ret double %val32
|
|
}
|
|
|
|
define void @test_trunc32(float %in, ptr %addr) nounwind {
|
|
; CHECK-LABEL: test_trunc32:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: push r16
|
|
; CHECK-NEXT: push r17
|
|
; CHECK-NEXT: mov r16, r20
|
|
; CHECK-NEXT: mov r17, r21
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: pop r17
|
|
; CHECK-NEXT: pop r16
|
|
; CHECK-NEXT: ret
|
|
%val16 = fptrunc float %in to half
|
|
store half %val16, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define void @test_trunc64(double %in, ptr %addr) nounwind {
|
|
; CHECK-LABEL: test_trunc64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: rcall __truncdfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
%val16 = fptrunc double %in to half
|
|
store half %val16, ptr %addr
|
|
ret void
|
|
}
|
|
|
|
define i64 @test_fptosi_i64(ptr %p) nounwind {
|
|
; CHECK-LABEL: test_fptosi_i64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: rcall __fixsfdi
|
|
; CHECK-NEXT: ret
|
|
%a = load half, ptr %p, align 2
|
|
%r = fptosi half %a to i64
|
|
ret i64 %r
|
|
}
|
|
|
|
define void @test_sitofp_i64(i64 %a, ptr %p) nounwind {
|
|
; CHECK-LABEL: test_sitofp_i64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: rcall __floatdisf
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
%r = sitofp i64 %a to half
|
|
store half %r, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define i64 @test_fptoui_i64(ptr %p) nounwind {
|
|
; CHECK-LABEL: test_fptoui_i64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: rcall __fixunssfdi
|
|
; CHECK-NEXT: ret
|
|
%a = load half, ptr %p, align 2
|
|
%r = fptoui half %a to i64
|
|
ret i64 %r
|
|
}
|
|
|
|
define void @test_uitofp_i64(i64 %a, ptr %p) nounwind {
|
|
; CHECK-LABEL: test_uitofp_i64:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: rcall __floatundisf
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
%r = uitofp i64 %a to half
|
|
store half %r, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define <2 x float> @test_extend32_vec2(ptr %p) nounwind {
|
|
; CHECK-LABEL: test_extend32_vec2:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: push r12
|
|
; CHECK-NEXT: push r13
|
|
; CHECK-NEXT: push r14
|
|
; CHECK-NEXT: push r15
|
|
; CHECK-NEXT: push r16
|
|
; CHECK-NEXT: push r17
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: mov r12, r30
|
|
; CHECK-NEXT: mov r13, r31
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: mov r16, r22
|
|
; CHECK-NEXT: mov r17, r23
|
|
; CHECK-NEXT: mov r14, r24
|
|
; CHECK-NEXT: mov r15, r25
|
|
; CHECK-NEXT: mov r30, r12
|
|
; CHECK-NEXT: mov r31, r13
|
|
; CHECK-NEXT: ldd r24, Z+2
|
|
; CHECK-NEXT: ldd r25, Z+3
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: mov r18, r16
|
|
; CHECK-NEXT: mov r19, r17
|
|
; CHECK-NEXT: mov r20, r14
|
|
; CHECK-NEXT: mov r21, r15
|
|
; CHECK-NEXT: pop r17
|
|
; CHECK-NEXT: pop r16
|
|
; CHECK-NEXT: pop r15
|
|
; CHECK-NEXT: pop r14
|
|
; CHECK-NEXT: pop r13
|
|
; CHECK-NEXT: pop r12
|
|
; CHECK-NEXT: ret
|
|
%a = load <2 x half>, ptr %p, align 8
|
|
%b = fpext <2 x half> %a to <2 x float>
|
|
ret <2 x float> %b
|
|
}
|
|
|
|
define <1 x double> @test_extend64_vec1(ptr %p) nounwind {
|
|
; CHECK-LABEL: test_extend64_vec1:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: mov r30, r24
|
|
; CHECK-NEXT: mov r31, r25
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: rcall __extendsfdf2
|
|
; CHECK-NEXT: ret
|
|
%a = load <1 x half>, ptr %p, align 8
|
|
%b = fpext <1 x half> %a to <1 x double>
|
|
ret <1 x double> %b
|
|
}
|
|
|
|
define void @test_trunc32_vec2(<2 x float> %a, ptr %p) nounwind {
|
|
; CHECK-LABEL: test_trunc32_vec2:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: push r12
|
|
; CHECK-NEXT: push r13
|
|
; CHECK-NEXT: push r14
|
|
; CHECK-NEXT: push r15
|
|
; CHECK-NEXT: mov r14, r20
|
|
; CHECK-NEXT: mov r15, r21
|
|
; CHECK-NEXT: mov r12, r18
|
|
; CHECK-NEXT: mov r13, r19
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+3, r25
|
|
; CHECK-NEXT: std Z+2, r24
|
|
; CHECK-NEXT: mov r22, r12
|
|
; CHECK-NEXT: mov r23, r13
|
|
; CHECK-NEXT: mov r24, r14
|
|
; CHECK-NEXT: mov r25, r15
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: pop r15
|
|
; CHECK-NEXT: pop r14
|
|
; CHECK-NEXT: pop r13
|
|
; CHECK-NEXT: pop r12
|
|
; CHECK-NEXT: ret
|
|
%v = fptrunc <2 x float> %a to <2 x half>
|
|
store <2 x half> %v, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define void @test_trunc64_vec1(<1 x double> %a, ptr %p) nounwind {
|
|
; CHECK-LABEL: test_trunc64_vec1:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: rcall __truncdfhf2
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: std Z+1, r25
|
|
; CHECK-NEXT: st Z, r24
|
|
; CHECK-NEXT: ret
|
|
%v = fptrunc <1 x double> %a to <1 x half>
|
|
store <1 x half> %v, ptr %p
|
|
ret void
|
|
}
|
|
|
|
define float @test_sitofp_fadd_i32(i32 %a, ptr %b) nounwind {
|
|
; CHECK-LABEL: test_sitofp_fadd_i32:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: push r12
|
|
; CHECK-NEXT: push r13
|
|
; CHECK-NEXT: push r14
|
|
; CHECK-NEXT: push r15
|
|
; CHECK-NEXT: push r16
|
|
; CHECK-NEXT: push r17
|
|
; CHECK-NEXT: mov r16, r20
|
|
; CHECK-NEXT: mov r17, r21
|
|
; CHECK-NEXT: rcall __floatsisf
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: mov r14, r24
|
|
; CHECK-NEXT: mov r15, r25
|
|
; CHECK-NEXT: mov r30, r16
|
|
; CHECK-NEXT: mov r31, r17
|
|
; CHECK-NEXT: ld r24, Z
|
|
; CHECK-NEXT: ldd r25, Z+1
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: mov r16, r22
|
|
; CHECK-NEXT: mov r17, r23
|
|
; CHECK-NEXT: mov r12, r24
|
|
; CHECK-NEXT: mov r13, r25
|
|
; CHECK-NEXT: mov r24, r14
|
|
; CHECK-NEXT: mov r25, r15
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: mov r18, r22
|
|
; CHECK-NEXT: mov r19, r23
|
|
; CHECK-NEXT: mov r20, r24
|
|
; CHECK-NEXT: mov r21, r25
|
|
; CHECK-NEXT: mov r22, r16
|
|
; CHECK-NEXT: mov r23, r17
|
|
; CHECK-NEXT: mov r24, r12
|
|
; CHECK-NEXT: mov r25, r13
|
|
; CHECK-NEXT: rcall __addsf3
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: pop r17
|
|
; CHECK-NEXT: pop r16
|
|
; CHECK-NEXT: pop r15
|
|
; CHECK-NEXT: pop r14
|
|
; CHECK-NEXT: pop r13
|
|
; CHECK-NEXT: pop r12
|
|
; CHECK-NEXT: ret
|
|
%tmp0 = load half, ptr %b
|
|
%tmp1 = sitofp i32 %a to half
|
|
%tmp2 = fadd half %tmp0, %tmp1
|
|
%tmp3 = fpext half %tmp2 to float
|
|
ret float %tmp3
|
|
}
|
|
|
|
define half @chained_fp_ops(half %x) {
|
|
; CHECK-LABEL: chained_fp_ops:
|
|
; CHECK: ; %bb.0: ; %start
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: mov r18, r22
|
|
; CHECK-NEXT: mov r19, r23
|
|
; CHECK-NEXT: mov r20, r24
|
|
; CHECK-NEXT: mov r21, r25
|
|
; CHECK-NEXT: rcall __addsf3
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: ldi r18, 0
|
|
; CHECK-NEXT: ldi r19, 0
|
|
; CHECK-NEXT: ldi r20, 0
|
|
; CHECK-NEXT: ldi r21, 63
|
|
; CHECK-NEXT: rcall __mulsf3
|
|
; CHECK-NEXT: rcall __truncsfhf2
|
|
; CHECK-NEXT: ret
|
|
start:
|
|
%y = fmul half %x, 0xH4000
|
|
%z = fdiv half %y, 0xH4000
|
|
ret half %z
|
|
}
|
|
|
|
define half @test_select_cc(half) nounwind {
|
|
; CHECK-LABEL: test_select_cc:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: push r16
|
|
; CHECK-NEXT: push r17
|
|
; CHECK-NEXT: rcall __extendhfsf2
|
|
; CHECK-NEXT: ldi r16, 0
|
|
; CHECK-NEXT: ldi r17, 0
|
|
; CHECK-NEXT: mov r18, r16
|
|
; CHECK-NEXT: mov r19, r17
|
|
; CHECK-NEXT: mov r20, r16
|
|
; CHECK-NEXT: mov r21, r17
|
|
; CHECK-NEXT: rcall __nesf2
|
|
; CHECK-NEXT: cpi r24, 0
|
|
; CHECK-NEXT: breq .LBB21_2
|
|
; CHECK-NEXT: ; %bb.1:
|
|
; CHECK-NEXT: ldi r16, 0
|
|
; CHECK-NEXT: ldi r17, 60
|
|
; CHECK-NEXT: .LBB21_2:
|
|
; CHECK-NEXT: mov r24, r16
|
|
; CHECK-NEXT: mov r25, r17
|
|
; CHECK-NEXT: pop r17
|
|
; CHECK-NEXT: pop r16
|
|
; CHECK-NEXT: ret
|
|
%2 = fcmp une half %0, 0xH0000
|
|
%3 = uitofp i1 %2 to half
|
|
ret half %3
|
|
}
|
|
|
|
define half @fabs(half %x) nounwind {
|
|
; CHECK-LABEL: fabs:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: andi r25, 127
|
|
; CHECK-NEXT: ret
|
|
%a = call half @llvm.fabs.f16(half %x)
|
|
ret half %a
|
|
}
|
|
|
|
define half @fcopysign(half %x, half %y) nounwind {
|
|
; CHECK-LABEL: fcopysign:
|
|
; CHECK: ; %bb.0:
|
|
; CHECK-NEXT: andi r22, 0
|
|
; CHECK-NEXT: andi r23, 128
|
|
; CHECK-NEXT: andi r25, 127
|
|
; CHECK-NEXT: or r24, r22
|
|
; CHECK-NEXT: or r25, r23
|
|
; CHECK-NEXT: ret
|
|
%a = call half @llvm.copysign.f16(half %x, half %y)
|
|
ret half %a
|
|
}
|