[llvm] [AVR] Add a test for half support (NFC) (PR #152708)

Ben Shi via llvm-commits llvm-commits at lists.llvm.org
Sat Aug 9 00:08:11 PDT 2025


================
@@ -0,0 +1,750 @@
+; 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, r20
+; CHECK-NEXT:    mov r31, r21
+; CHECK-NEXT:    std Z+1, r23
+; CHECK-NEXT:    st Z, r22
+; 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 r22, Z
+; CHECK-NEXT:    ldd r23, Z+1
+; CHECK-NEXT:    ret
+  %r = load half, ptr %p
+  ret half %r
+}
+
+define dso_local double @loadd(ptr nocapture readonly %a) local_unnamed_addr nounwind {
+; CHECK-LABEL: loadd:
+; CHECK:       ; %bb.0: ; %entry
+; CHECK-NEXT:    mov r30, r24
+; CHECK-NEXT:    mov r31, r25
+; CHECK-NEXT:    ldd r24, Z+2
+; CHECK-NEXT:    ldd r25, Z+3
+; CHECK-NEXT:    rcall __extendhfsf2
+; CHECK-NEXT:    rcall __extendsfdf2
+; CHECK-NEXT:    ret
+entry:
+  %arrayidx = getelementptr inbounds i16, ptr %a, i64 1
+  %0 = load i16, ptr %arrayidx, align 2
+  %1 = tail call double @llvm.convert.from.fp16.f64(i16 %0)
+  ret double %1
+}
+
+define dso_local float @loadf(ptr nocapture readonly %a) local_unnamed_addr nounwind {
+; CHECK-LABEL: loadf:
+; CHECK:       ; %bb.0: ; %entry
+; CHECK-NEXT:    mov r30, r24
+; CHECK-NEXT:    mov r31, r25
+; CHECK-NEXT:    ldd r24, Z+2
+; CHECK-NEXT:    ldd r25, Z+3
+; CHECK-NEXT:    rcall __extendhfsf2
+; CHECK-NEXT:    ret
+entry:
+  %arrayidx = getelementptr inbounds i16, ptr %a, i64 1
+  %0 = load i16, ptr %arrayidx, align 2
+  %1 = tail call float @llvm.convert.from.fp16.f32(i16 %0)
+  ret float %1
+}
+
+define dso_local void @stored(ptr nocapture %a, double %b) local_unnamed_addr nounwind {
+; CHECK-LABEL: stored:
+; CHECK:       ; %bb.0: ; %entry
+; CHECK-NEXT:    push r16
+; CHECK-NEXT:    push r17
+; CHECK-NEXT:    mov r30, r22
+; CHECK-NEXT:    mov r31, r23
+; CHECK-NEXT:    mov r22, r20
+; CHECK-NEXT:    mov r23, r21
+; CHECK-NEXT:    mov r20, r18
+; CHECK-NEXT:    mov r21, r19
+; CHECK-NEXT:    mov r18, r16
+; CHECK-NEXT:    mov r19, r17
+; CHECK-NEXT:    mov r16, r24
+; CHECK-NEXT:    mov r17, r25
+; CHECK-NEXT:    mov r24, r30
+; CHECK-NEXT:    mov r25, r31
+; CHECK-NEXT:    rcall __truncdfhf2
+; CHECK-NEXT:    rcall __extendhfsf2
+; 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
+entry:
+  %0 = tail call i16 @llvm.convert.to.fp16.f64(double %b)
+  store i16 %0, ptr %a, align 2
+  ret void
+}
+
+define dso_local void @storef(ptr nocapture %a, float %b) local_unnamed_addr nounwind {
+; CHECK-LABEL: storef:
+; CHECK:       ; %bb.0: ; %entry
+; CHECK-NEXT:    push r16
+; CHECK-NEXT:    push r17
+; CHECK-NEXT:    mov r18, r22
+; CHECK-NEXT:    mov r19, r23
+; CHECK-NEXT:    mov r16, r24
+; CHECK-NEXT:    mov r17, r25
+; CHECK-NEXT:    mov r22, r20
+; CHECK-NEXT:    mov r23, r21
+; CHECK-NEXT:    mov r24, r18
+; CHECK-NEXT:    mov r25, r19
+; CHECK-NEXT:    rcall __truncsfhf2
+; CHECK-NEXT:    rcall __extendhfsf2
+; 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
+entry:
+  %0 = tail call i16 @llvm.convert.to.fp16.f32(float %b)
+  store i16 %0, ptr %a, align 2
+  ret void
+}
+
+define void @test_load_store(ptr %in, ptr %out) nounwind {
+; CHECK-LABEL: test_load_store:
+; CHECK:       ; %bb.0:
+; CHECK-NEXT:    push r16
+; CHECK-NEXT:    push r17
+; CHECK-NEXT:    mov r16, r22
+; CHECK-NEXT:    mov r17, r23
+; 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 __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
+  %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:    mov r22, r24
+; CHECK-NEXT:    mov r23, r25
+; 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:    mov r24, r22
+; CHECK-NEXT:    mov r25, r23
+; 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:    rcall __extendhfsf2
+; 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:    rcall __extendhfsf2
+; 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
+  %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:    rcall __extendhfsf2
+; 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:    rcall __extendhfsf2
+; 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 <4 x float> @test_extend32_vec4(ptr %p) nounwind {
----------------
benshi001 wrote:

I do not think tests for vector types are necessary, AVR is resource limited 8-bit CPU without complex computation such as vectcor. 

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


More information about the llvm-commits mailing list