[llvm-branch-commits] [llvm] release/19.x: [loongarch][DAG][FREEZE] Fix crash when FREEZE a half(f16) type on loongarch (#107791) (PR #109093)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 18 00:25:20 PDT 2024


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/109093

Backport 13280d99aec5b4f383a2f3d5c10ecb148a07384e

Requested by: @nikic

>From 3539b82c0ba5b412ed51e2031880c1999a401b3d Mon Sep 17 00:00:00 2001
From: YANG Xudong <yangxudong at ymatrix.cn>
Date: Fri, 13 Sep 2024 08:49:54 +0800
Subject: [PATCH] [loongarch][DAG][FREEZE] Fix crash when FREEZE a half(f16)
 type on loongarch (#107791)

For zig with LLVM 19.1.0rc4, we are seeing the following error when
bootstrapping a `loongarch64-linux-musl` target.

https://github.com/ziglang/zig-bootstrap/issues/164#issuecomment-2332357069

It seems that this issue is caused by `PromoteFloatResult` is not
handling FREEZE OP on loongarch.

Here is the reproduction of the error: https://godbolt.org/z/PPfvWjjG5

~~This patch adds the FREEZE OP handling with `PromoteFloatRes_UnaryOp`
and adds a test case.~~

This patch changes loongarch's way of floating point promotion to soft
promotion to avoid this problem.

See: loongarch's handling of `half`:
- https://github.com/llvm/llvm-project/issues/93894
- https://github.com/llvm/llvm-project/pull/94456

Also see: other float promotion FREEZE handling
-
https://github.com/llvm/llvm-project/commit/0019c2f194a5e1f4cd65c5284e204328cc40ab3d

(cherry picked from commit 13280d99aec5b4f383a2f3d5c10ecb148a07384e)
---
 .../Target/LoongArch/LoongArchISelLowering.h  |   2 +
 llvm/test/CodeGen/LoongArch/fp16-promote.ll   | 198 +++++++++++-------
 2 files changed, 128 insertions(+), 72 deletions(-)

diff --git a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
index fc5b36c2124e01..267837add575dc 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelLowering.h
@@ -332,6 +332,8 @@ class LoongArchTargetLowering : public TargetLowering {
   bool isEligibleForTailCallOptimization(
       CCState &CCInfo, CallLoweringInfo &CLI, MachineFunction &MF,
       const SmallVectorImpl<CCValAssign> &ArgLocs) const;
+
+  bool softPromoteHalfType() const override { return true; }
 };
 
 } // end namespace llvm
diff --git a/llvm/test/CodeGen/LoongArch/fp16-promote.ll b/llvm/test/CodeGen/LoongArch/fp16-promote.ll
index 75f920b43a06ce..03965ac81f3763 100644
--- a/llvm/test/CodeGen/LoongArch/fp16-promote.ll
+++ b/llvm/test/CodeGen/LoongArch/fp16-promote.ll
@@ -126,42 +126,40 @@ define void @test_fptrunc_double(double %d, ptr %p) nounwind {
 define half @test_fadd_reg(half %a, half %b) nounwind {
 ; LA32-LABEL: test_fadd_reg:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    addi.w $sp, $sp, -32
-; LA32-NEXT:    st.w $ra, $sp, 28 # 4-byte Folded Spill
-; LA32-NEXT:    fst.d $fs0, $sp, 16 # 8-byte Folded Spill
-; LA32-NEXT:    fst.d $fs1, $sp, 8 # 8-byte Folded Spill
+; LA32-NEXT:    addi.w $sp, $sp, -16
+; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-NEXT:    st.w $fp, $sp, 8 # 4-byte Folded Spill
+; LA32-NEXT:    fst.d $fs0, $sp, 0 # 8-byte Folded Spill
+; LA32-NEXT:    move $fp, $a0
+; LA32-NEXT:    move $a0, $a1
+; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA32-NEXT:    fmov.s $fs0, $fa0
-; LA32-NEXT:    fmov.s $fa0, $fa1
-; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA32-NEXT:    move $a0, $fp
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fmov.s $fs1, $fa0
-; LA32-NEXT:    fmov.s $fa0, $fs0
+; LA32-NEXT:    fadd.s $fa0, $fa0, $fs0
 ; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fadd.s $fa0, $fa0, $fs1
-; LA32-NEXT:    fld.d $fs1, $sp, 8 # 8-byte Folded Reload
-; LA32-NEXT:    fld.d $fs0, $sp, 16 # 8-byte Folded Reload
-; LA32-NEXT:    ld.w $ra, $sp, 28 # 4-byte Folded Reload
-; LA32-NEXT:    addi.w $sp, $sp, 32
+; LA32-NEXT:    fld.d $fs0, $sp, 0 # 8-byte Folded Reload
+; LA32-NEXT:    ld.w $fp, $sp, 8 # 4-byte Folded Reload
+; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-NEXT:    addi.w $sp, $sp, 16
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_fadd_reg:
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    addi.d $sp, $sp, -32
 ; LA64-NEXT:    st.d $ra, $sp, 24 # 8-byte Folded Spill
-; LA64-NEXT:    fst.d $fs0, $sp, 16 # 8-byte Folded Spill
-; LA64-NEXT:    fst.d $fs1, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    st.d $fp, $sp, 16 # 8-byte Folded Spill
+; LA64-NEXT:    fst.d $fs0, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    move $fp, $a0
+; LA64-NEXT:    move $a0, $a1
+; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA64-NEXT:    fmov.s $fs0, $fa0
-; LA64-NEXT:    fmov.s $fa0, $fa1
-; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA64-NEXT:    move $a0, $fp
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fmov.s $fs1, $fa0
-; LA64-NEXT:    fmov.s $fa0, $fs0
+; LA64-NEXT:    fadd.s $fa0, $fa0, $fs0
 ; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fadd.s $fa0, $fa0, $fs1
-; LA64-NEXT:    fld.d $fs1, $sp, 8 # 8-byte Folded Reload
-; LA64-NEXT:    fld.d $fs0, $sp, 16 # 8-byte Folded Reload
+; LA64-NEXT:    fld.d $fs0, $sp, 8 # 8-byte Folded Reload
+; LA64-NEXT:    ld.d $fp, $sp, 16 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $ra, $sp, 24 # 8-byte Folded Reload
 ; LA64-NEXT:    addi.d $sp, $sp, 32
 ; LA64-NEXT:    ret
@@ -177,16 +175,16 @@ define void @test_fadd_mem(ptr %p, ptr %q) nounwind {
 ; LA32-NEXT:    st.w $fp, $sp, 24 # 4-byte Folded Spill
 ; LA32-NEXT:    st.w $s0, $sp, 20 # 4-byte Folded Spill
 ; LA32-NEXT:    fst.d $fs0, $sp, 8 # 8-byte Folded Spill
-; LA32-NEXT:    move $fp, $a1
-; LA32-NEXT:    move $s0, $a0
-; LA32-NEXT:    ld.hu $a0, $a0, 0
+; LA32-NEXT:    move $fp, $a0
+; LA32-NEXT:    ld.hu $s0, $a0, 0
+; LA32-NEXT:    ld.hu $a0, $a1, 0
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA32-NEXT:    fmov.s $fs0, $fa0
-; LA32-NEXT:    ld.hu $a0, $fp, 0
+; LA32-NEXT:    move $a0, $s0
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fadd.s $fa0, $fs0, $fa0
+; LA32-NEXT:    fadd.s $fa0, $fa0, $fs0
 ; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA32-NEXT:    st.h $a0, $s0, 0
+; LA32-NEXT:    st.h $a0, $fp, 0
 ; LA32-NEXT:    fld.d $fs0, $sp, 8 # 8-byte Folded Reload
 ; LA32-NEXT:    ld.w $s0, $sp, 20 # 4-byte Folded Reload
 ; LA32-NEXT:    ld.w $fp, $sp, 24 # 4-byte Folded Reload
@@ -201,16 +199,16 @@ define void @test_fadd_mem(ptr %p, ptr %q) nounwind {
 ; LA64-NEXT:    st.d $fp, $sp, 16 # 8-byte Folded Spill
 ; LA64-NEXT:    st.d $s0, $sp, 8 # 8-byte Folded Spill
 ; LA64-NEXT:    fst.d $fs0, $sp, 0 # 8-byte Folded Spill
-; LA64-NEXT:    move $fp, $a1
-; LA64-NEXT:    move $s0, $a0
-; LA64-NEXT:    ld.hu $a0, $a0, 0
+; LA64-NEXT:    move $fp, $a0
+; LA64-NEXT:    ld.hu $s0, $a0, 0
+; LA64-NEXT:    ld.hu $a0, $a1, 0
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA64-NEXT:    fmov.s $fs0, $fa0
-; LA64-NEXT:    ld.hu $a0, $fp, 0
+; LA64-NEXT:    move $a0, $s0
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fadd.s $fa0, $fs0, $fa0
+; LA64-NEXT:    fadd.s $fa0, $fa0, $fs0
 ; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA64-NEXT:    st.h $a0, $s0, 0
+; LA64-NEXT:    st.h $a0, $fp, 0
 ; LA64-NEXT:    fld.d $fs0, $sp, 0 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $s0, $sp, 8 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $fp, $sp, 16 # 8-byte Folded Reload
@@ -227,42 +225,40 @@ define void @test_fadd_mem(ptr %p, ptr %q) nounwind {
 define half @test_fmul_reg(half %a, half %b) nounwind {
 ; LA32-LABEL: test_fmul_reg:
 ; LA32:       # %bb.0:
-; LA32-NEXT:    addi.w $sp, $sp, -32
-; LA32-NEXT:    st.w $ra, $sp, 28 # 4-byte Folded Spill
-; LA32-NEXT:    fst.d $fs0, $sp, 16 # 8-byte Folded Spill
-; LA32-NEXT:    fst.d $fs1, $sp, 8 # 8-byte Folded Spill
+; LA32-NEXT:    addi.w $sp, $sp, -16
+; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-NEXT:    st.w $fp, $sp, 8 # 4-byte Folded Spill
+; LA32-NEXT:    fst.d $fs0, $sp, 0 # 8-byte Folded Spill
+; LA32-NEXT:    move $fp, $a0
+; LA32-NEXT:    move $a0, $a1
+; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA32-NEXT:    fmov.s $fs0, $fa0
-; LA32-NEXT:    fmov.s $fa0, $fa1
-; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA32-NEXT:    move $a0, $fp
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fmov.s $fs1, $fa0
-; LA32-NEXT:    fmov.s $fa0, $fs0
+; LA32-NEXT:    fmul.s $fa0, $fa0, $fs0
 ; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fmul.s $fa0, $fa0, $fs1
-; LA32-NEXT:    fld.d $fs1, $sp, 8 # 8-byte Folded Reload
-; LA32-NEXT:    fld.d $fs0, $sp, 16 # 8-byte Folded Reload
-; LA32-NEXT:    ld.w $ra, $sp, 28 # 4-byte Folded Reload
-; LA32-NEXT:    addi.w $sp, $sp, 32
+; LA32-NEXT:    fld.d $fs0, $sp, 0 # 8-byte Folded Reload
+; LA32-NEXT:    ld.w $fp, $sp, 8 # 4-byte Folded Reload
+; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-NEXT:    addi.w $sp, $sp, 16
 ; LA32-NEXT:    ret
 ;
 ; LA64-LABEL: test_fmul_reg:
 ; LA64:       # %bb.0:
 ; LA64-NEXT:    addi.d $sp, $sp, -32
 ; LA64-NEXT:    st.d $ra, $sp, 24 # 8-byte Folded Spill
-; LA64-NEXT:    fst.d $fs0, $sp, 16 # 8-byte Folded Spill
-; LA64-NEXT:    fst.d $fs1, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    st.d $fp, $sp, 16 # 8-byte Folded Spill
+; LA64-NEXT:    fst.d $fs0, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    move $fp, $a0
+; LA64-NEXT:    move $a0, $a1
+; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA64-NEXT:    fmov.s $fs0, $fa0
-; LA64-NEXT:    fmov.s $fa0, $fa1
-; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA64-NEXT:    move $a0, $fp
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fmov.s $fs1, $fa0
-; LA64-NEXT:    fmov.s $fa0, $fs0
+; LA64-NEXT:    fmul.s $fa0, $fa0, $fs0
 ; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fmul.s $fa0, $fa0, $fs1
-; LA64-NEXT:    fld.d $fs1, $sp, 8 # 8-byte Folded Reload
-; LA64-NEXT:    fld.d $fs0, $sp, 16 # 8-byte Folded Reload
+; LA64-NEXT:    fld.d $fs0, $sp, 8 # 8-byte Folded Reload
+; LA64-NEXT:    ld.d $fp, $sp, 16 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $ra, $sp, 24 # 8-byte Folded Reload
 ; LA64-NEXT:    addi.d $sp, $sp, 32
 ; LA64-NEXT:    ret
@@ -278,16 +274,16 @@ define void @test_fmul_mem(ptr %p, ptr %q) nounwind {
 ; LA32-NEXT:    st.w $fp, $sp, 24 # 4-byte Folded Spill
 ; LA32-NEXT:    st.w $s0, $sp, 20 # 4-byte Folded Spill
 ; LA32-NEXT:    fst.d $fs0, $sp, 8 # 8-byte Folded Spill
-; LA32-NEXT:    move $fp, $a1
-; LA32-NEXT:    move $s0, $a0
-; LA32-NEXT:    ld.hu $a0, $a0, 0
+; LA32-NEXT:    move $fp, $a0
+; LA32-NEXT:    ld.hu $s0, $a0, 0
+; LA32-NEXT:    ld.hu $a0, $a1, 0
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA32-NEXT:    fmov.s $fs0, $fa0
-; LA32-NEXT:    ld.hu $a0, $fp, 0
+; LA32-NEXT:    move $a0, $s0
 ; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA32-NEXT:    fmul.s $fa0, $fs0, $fa0
+; LA32-NEXT:    fmul.s $fa0, $fa0, $fs0
 ; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA32-NEXT:    st.h $a0, $s0, 0
+; LA32-NEXT:    st.h $a0, $fp, 0
 ; LA32-NEXT:    fld.d $fs0, $sp, 8 # 8-byte Folded Reload
 ; LA32-NEXT:    ld.w $s0, $sp, 20 # 4-byte Folded Reload
 ; LA32-NEXT:    ld.w $fp, $sp, 24 # 4-byte Folded Reload
@@ -302,16 +298,16 @@ define void @test_fmul_mem(ptr %p, ptr %q) nounwind {
 ; LA64-NEXT:    st.d $fp, $sp, 16 # 8-byte Folded Spill
 ; LA64-NEXT:    st.d $s0, $sp, 8 # 8-byte Folded Spill
 ; LA64-NEXT:    fst.d $fs0, $sp, 0 # 8-byte Folded Spill
-; LA64-NEXT:    move $fp, $a1
-; LA64-NEXT:    move $s0, $a0
-; LA64-NEXT:    ld.hu $a0, $a0, 0
+; LA64-NEXT:    move $fp, $a0
+; LA64-NEXT:    ld.hu $s0, $a0, 0
+; LA64-NEXT:    ld.hu $a0, $a1, 0
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
 ; LA64-NEXT:    fmov.s $fs0, $fa0
-; LA64-NEXT:    ld.hu $a0, $fp, 0
+; LA64-NEXT:    move $a0, $s0
 ; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
-; LA64-NEXT:    fmul.s $fa0, $fs0, $fa0
+; LA64-NEXT:    fmul.s $fa0, $fa0, $fs0
 ; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
-; LA64-NEXT:    st.h $a0, $s0, 0
+; LA64-NEXT:    st.h $a0, $fp, 0
 ; LA64-NEXT:    fld.d $fs0, $sp, 0 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $s0, $sp, 8 # 8-byte Folded Reload
 ; LA64-NEXT:    ld.d $fp, $sp, 16 # 8-byte Folded Reload
@@ -324,3 +320,61 @@ define void @test_fmul_mem(ptr %p, ptr %q) nounwind {
   store half %r, ptr %p
   ret void
 }
+
+define half @freeze_half_undef() nounwind {
+; LA32-LABEL: freeze_half_undef:
+; LA32:       # %bb.0:
+; LA32-NEXT:    addi.w $sp, $sp, -16
+; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-NEXT:    movgr2fr.w $fa0, $zero
+; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
+; LA32-NEXT:    fadd.s $fa0, $fa0, $fa0
+; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-NEXT:    addi.w $sp, $sp, 16
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: freeze_half_undef:
+; LA64:       # %bb.0:
+; LA64-NEXT:    addi.d $sp, $sp, -16
+; LA64-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    movgr2fr.w $fa0, $zero
+; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
+; LA64-NEXT:    fadd.s $fa0, $fa0, $fa0
+; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA64-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-NEXT:    addi.d $sp, $sp, 16
+; LA64-NEXT:    ret
+  %y1 = freeze half undef
+  %t1 = fadd half %y1, %y1
+  ret half %t1
+}
+
+define half @freeze_half_poison(half %maybe.poison) nounwind {
+; LA32-LABEL: freeze_half_poison:
+; LA32:       # %bb.0:
+; LA32-NEXT:    addi.w $sp, $sp, -16
+; LA32-NEXT:    st.w $ra, $sp, 12 # 4-byte Folded Spill
+; LA32-NEXT:    bl %plt(__gnu_h2f_ieee)
+; LA32-NEXT:    fadd.s $fa0, $fa0, $fa0
+; LA32-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA32-NEXT:    ld.w $ra, $sp, 12 # 4-byte Folded Reload
+; LA32-NEXT:    addi.w $sp, $sp, 16
+; LA32-NEXT:    ret
+;
+; LA64-LABEL: freeze_half_poison:
+; LA64:       # %bb.0:
+; LA64-NEXT:    addi.d $sp, $sp, -16
+; LA64-NEXT:    st.d $ra, $sp, 8 # 8-byte Folded Spill
+; LA64-NEXT:    bl %plt(__gnu_h2f_ieee)
+; LA64-NEXT:    fadd.s $fa0, $fa0, $fa0
+; LA64-NEXT:    bl %plt(__gnu_f2h_ieee)
+; LA64-NEXT:    ld.d $ra, $sp, 8 # 8-byte Folded Reload
+; LA64-NEXT:    addi.d $sp, $sp, 16
+; LA64-NEXT:    ret
+  %y1 = freeze half %maybe.poison
+  %t1 = fadd half %y1, %y1
+  ret half %t1
+}



More information about the llvm-branch-commits mailing list