Skip to content

Commit b09f25e

Browse files
committed
[SelectionDAG] Add f16 soft promotion for lrint and lround
On platforms that soft promote `half`, using `lrint` intrinsics crashes with the following: SoftPromoteHalfOperand Op #0: t5: i32 = lrint t4 LLVM ERROR: Do not know how to soft promote this operator's operand! PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace. Stack dump: 0. Program arguments: /Users/tmgross/Documents/projects/llvm/llvm-build/bin/llc -mtriple=riscv32 1. Running pass 'Function Pass Manager' on module '<stdin>'. 2. Running pass 'RISC-V DAG->DAG Pattern Instruction Selection' on function '@test_lrint_ixx_f16' Resolve this by adding a soft promotion. `SoftPromoteHalfOp_FP_TO_XINT` is reused here since it provides the correct input and output types. It is renamed `PromoteFloatOp_UnaryOp` to match `PromoteFloatOp_UnaryOp` and similar functions that are used to handle the same sets of intrinsics.
1 parent c0e510c commit b09f25e

File tree

8 files changed

+139
-55
lines changed

8 files changed

+139
-55
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "LegalizeTypes.h"
2222
#include "llvm/Analysis/TargetLibraryInfo.h"
23+
#include "llvm/CodeGen/ISDOpcodes.h"
2324
#include "llvm/Support/ErrorHandling.h"
2425
#include "llvm/Support/raw_ostream.h"
2526
using namespace llvm;
@@ -3729,10 +3730,18 @@ bool DAGTypeLegalizer::SoftPromoteHalfOperand(SDNode *N, unsigned OpNo) {
37293730
Res = SoftPromoteHalfOp_FAKE_USE(N, OpNo);
37303731
break;
37313732
case ISD::FCOPYSIGN: Res = SoftPromoteHalfOp_FCOPYSIGN(N, OpNo); break;
3733+
case ISD::LLRINT:
3734+
case ISD::LLROUND:
3735+
case ISD::LRINT:
3736+
case ISD::LROUND:
3737+
case ISD::STRICT_LLRINT:
3738+
case ISD::STRICT_LLROUND:
3739+
case ISD::STRICT_LRINT:
3740+
case ISD::STRICT_LROUND:
37323741
case ISD::STRICT_FP_TO_SINT:
37333742
case ISD::STRICT_FP_TO_UINT:
37343743
case ISD::FP_TO_SINT:
3735-
case ISD::FP_TO_UINT: Res = SoftPromoteHalfOp_FP_TO_XINT(N); break;
3744+
case ISD::FP_TO_UINT: Res = SoftPromoteHalfOp_UnaryOp(N); break;
37363745
case ISD::FP_TO_SINT_SAT:
37373746
case ISD::FP_TO_UINT_SAT:
37383747
Res = SoftPromoteHalfOp_FP_TO_XINT_SAT(N); break;
@@ -3811,7 +3820,7 @@ SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_EXTEND(SDNode *N) {
38113820
return DAG.getNode(GetPromotionOpcode(SVT, RVT), SDLoc(N), RVT, Op);
38123821
}
38133822

3814-
SDValue DAGTypeLegalizer::SoftPromoteHalfOp_FP_TO_XINT(SDNode *N) {
3823+
SDValue DAGTypeLegalizer::SoftPromoteHalfOp_UnaryOp(SDNode *N) {
38153824
EVT RVT = N->getValueType(0);
38163825
bool IsStrict = N->isStrictFPOpcode();
38173826
SDValue Op = N->getOperand(IsStrict ? 1 : 0);

llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
840840
SDValue SoftPromoteHalfOp_FAKE_USE(SDNode *N, unsigned OpNo);
841841
SDValue SoftPromoteHalfOp_FCOPYSIGN(SDNode *N, unsigned OpNo);
842842
SDValue SoftPromoteHalfOp_FP_EXTEND(SDNode *N);
843-
SDValue SoftPromoteHalfOp_FP_TO_XINT(SDNode *N);
843+
SDValue SoftPromoteHalfOp_UnaryOp(SDNode *N);
844844
SDValue SoftPromoteHalfOp_FP_TO_XINT_SAT(SDNode *N);
845845
SDValue SoftPromoteHalfOp_SETCC(SDNode *N);
846846
SDValue SoftPromoteHalfOp_SELECT_CC(SDNode *N, unsigned OpNo);

llvm/test/CodeGen/ARM/lrint-conv.ll

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
; RUN: llc < %s -mtriple=arm-eabi -float-abi=soft | FileCheck %s --check-prefix=SOFTFP
22
; RUN: llc < %s -mtriple=arm-eabi -float-abi=hard | FileCheck %s --check-prefix=HARDFP
33

4-
; FIXME: crash
5-
; define i32 @testmswh_builtin(half %x) {
6-
; entry:
7-
; %0 = tail call i32 @llvm.lrint.i32.f16(half %x)
8-
; ret i32 %0
9-
; }
4+
; SOFTFP-LABEL: testmswh_builtin:
5+
; SOFTFP: bl lrintf
6+
; HARDFP-LABEL: testmswh_builtin:
7+
; HARDFP: bl lrintf
8+
define i32 @testmswh_builtin(half %x) {
9+
entry:
10+
%0 = tail call i32 @llvm.lrint.i32.f16(half %x)
11+
ret i32 %0
12+
}
1013

1114
; SOFTFP-LABEL: testmsws_builtin:
1215
; SOFTFP: bl lrintf

llvm/test/CodeGen/LoongArch/lrint-conv.ll

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,31 @@
55
; RUN: sed 's/ITy/i32/g' %s | llc -mtriple=loongarch64 | FileCheck %s --check-prefixes=LA64-I32
66
; RUN: sed 's/ITy/i64/g' %s | llc -mtriple=loongarch64 | FileCheck %s --check-prefixes=LA64-I64
77

8-
; FIXME: crash
9-
; define ITy @test_lrint_ixx_f16(half %x) nounwind {
10-
; %res = tail call ITy @llvm.lrint.ITy.f16(half %x)
11-
; ret ITy %res
12-
; }
8+
define ITy @test_lrint_ixx_f16(half %x) nounwind {
9+
; LA32-LABEL: test_lrint_ixx_f16:
10+
; LA32: bl lrintf
11+
;
12+
; LA64-I32-LABEL: test_lrint_ixx_f16:
13+
; LA64-I32: pcaddu18i $ra, %call36(lrintf)
14+
;
15+
; LA64-I64-LABEL: test_lrint_ixx_f16:
16+
; LA64-I64: pcaddu18i $t8, %call36(lrintf)
17+
%res = tail call ITy @llvm.lrint.ITy.f16(half %x)
18+
ret ITy %res
19+
}
1320

14-
; define ITy @test_llrint_ixx_f16(half %x) nounwind {
15-
; %res = tail call ITy @llvm.llrint.ITy.f16(half %x)
16-
; ret ITy %res
17-
; }
21+
define ITy @test_llrint_ixx_f16(half %x) nounwind {
22+
; LA32-LABEL: test_llrint_ixx_f16:
23+
; LA32: bl lrintf
24+
;
25+
; LA64-I32-LABEL: test_llrint_ixx_f16:
26+
; LA64-I32: pcaddu18i $ra, %call36(lrintf)
27+
;
28+
; LA64-I64-LABEL: test_llrint_ixx_f16:
29+
; LA64-I64: pcaddu18i $t8, %call36(lrintf)
30+
%res = tail call ITy @llvm.llrint.ITy.f16(half %x)
31+
ret ITy %res
32+
}
1833

1934
define ITy @test_lrint_ixx_f32(float %x) nounwind {
2035
; LA32-LABEL: test_lrint_ixx_f32:

llvm/test/CodeGen/Mips/llrint-conv.ll

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
; RUN: llc < %s -mtriple=mips64el -mattr=+soft-float | FileCheck %s
22
; RUN: llc < %s -mtriple=mips -mattr=+soft-float | FileCheck %s
33

4-
; FIXME: crash
5-
; define signext i32 @testmswh(half %x) {
6-
; entry:
7-
; %0 = tail call i64 @llvm.llrint.f16(half %x)
8-
; %conv = trunc i64 %0 to i32
9-
; ret i32 %conv
10-
; }
4+
define signext i32 @testmswh(half %x) {
5+
; CHECK-LABEL: testmswh:
6+
; CHECK: jal llrintf
7+
entry:
8+
%0 = tail call i64 @llvm.llrint.f16(half %x)
9+
%conv = trunc i64 %0 to i32
10+
ret i32 %conv
11+
}
1112

12-
; define i64 @testmsxh(half %x) {
13-
; entry:
14-
; %0 = tail call i64 @llvm.llrint.f16(half %x)
15-
; ret i64 %0
16-
; }
13+
define i64 @testmsxh(half %x) {
14+
; CHECK-LABEL: testmsxh:
15+
; CHECK: jal llrintf
16+
entry:
17+
%0 = tail call i64 @llvm.llrint.f16(half %x)
18+
ret i64 %0
19+
}
1720

1821
define signext i32 @testmsws(float %x) {
1922
; CHECK-LABEL: testmsws:

llvm/test/CodeGen/Mips/lrint-conv.ll

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
; RUN: llc < %s -mtriple=mips64el -mattr=+soft-float | FileCheck %s
22
; RUN: llc < %s -mtriple=mips -mattr=+soft-float | FileCheck %s
33

4-
; FIXME: crash
5-
; define signext i32 @testmswh(half %x) {
6-
; entry:
7-
; %0 = tail call i64 @llvm.lrint.i64.f16(half %x)
8-
; %conv = trunc i64 %0 to i32
9-
; ret i32 %conv
10-
; }
4+
define signext i32 @testmswh(half %x) {
5+
; CHECK-LABEL: testmswh:
6+
; CHECK: jal lrintf
7+
entry:
8+
%0 = tail call i64 @llvm.lrint.i64.f16(half %x)
9+
%conv = trunc i64 %0 to i32
10+
ret i32 %conv
11+
}
1112

12-
; define i64 @testmsxh(half %x) {
13-
; entry:
14-
; %0 = tail call i64 @llvm.lrint.i64.f16(half %x)
15-
; ret i64 %0
16-
; }
13+
define i64 @testmsxh(half %x) {
14+
; CHECK-LABEL: testmsxh:
15+
; CHECK: jal lrintf
16+
entry:
17+
%0 = tail call i64 @llvm.lrint.i64.f16(half %x)
18+
ret i64 %0
19+
}
1720

1821
define signext i32 @testmsws(float %x) {
1922
; CHECK-LABEL: testmsws:

llvm/test/CodeGen/RISCV/lrint-conv.ll

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,25 @@
55
; RUN: sed 's/ITy/i32/g' %s | llc -mtriple=riscv64 | FileCheck %s --check-prefixes=RV64
66
; RUN: sed 's/ITy/i64/g' %s | llc -mtriple=riscv64 | FileCheck %s --check-prefixes=RV64
77

8-
; FIXME: crash
9-
; define ITy @test_lrint_ixx_f16(half %x) nounwind {
10-
; %res = tail call ITy @llvm.lrint.ITy.f16(half %x)
11-
; }
8+
define ITy @test_lrint_ixx_f16(half %x) nounwind {
9+
; RV32-LABEL: test_lrint_ixx_f16:
10+
; RV32: call lrintf
11+
;
12+
; RV64-LABEL: test_lrint_ixx_f16:
13+
; RV64: call lrintf
14+
%res = tail call ITy @llvm.lrint.ITy.f16(half %x)
15+
ret ITy %res
16+
}
1217

13-
; define ITy @test_llrint_ixx_f16(half %x) nounwind {
14-
; %res = tail call ITy @llvm.llrint.ITy.f16(half %x)
15-
; }
18+
define ITy @test_llrint_ixx_f16(half %x) nounwind {
19+
; RV32-LABEL: test_llrint_ixx_f16:
20+
; RV32: call llrintf
21+
;
22+
; RV64-LABEL: test_llrint_ixx_f16:
23+
; RV64: call llrintf
24+
%res = tail call ITy @llvm.llrint.ITy.f16(half %x)
25+
ret ITy %res
26+
}
1627

1728
define ITy @test_lrint_ixx_f32(float %x) nounwind {
1829
; RV32-LABEL: test_lrint_ixx_f32:

llvm/test/CodeGen/X86/lrint-conv-i32.ll

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,52 @@
77
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=avx | FileCheck %s --check-prefixes=X64,X64-AVX
88
; RUN: llc < %s -mtriple=x86_64-unknown -mattr=avx512f | FileCheck %s --check-prefixes=X64,X64-AVX
99

10-
; FIXME: crash
11-
; define i32 @testmswh(half %x) nounwind {
12-
; entry:
13-
; %0 = tail call i32 @llvm.lrint.i32.f16(half %x)
14-
; ret i32 %0
15-
; }
10+
define i32 @testmswh(half %x) nounwind {
11+
; X86-NOSSE-LABEL: testmswh:
12+
; X86-NOSSE: # %bb.0: # %entry
13+
; X86-NOSSE-NEXT: pushl %eax
14+
; X86-NOSSE-NEXT: movzwl {{[0-9]+}}(%esp), %eax
15+
; X86-NOSSE-NEXT: pushl %eax
16+
; X86-NOSSE-NEXT: calll __extendhfsf2
17+
; X86-NOSSE-NEXT: addl $4, %esp
18+
; X86-NOSSE-NEXT: fistpl (%esp)
19+
; X86-NOSSE-NEXT: movl (%esp), %eax
20+
; X86-NOSSE-NEXT: popl %ecx
21+
; X86-NOSSE-NEXT: retl
22+
;
23+
; X86-SSE2-LABEL: testmswh:
24+
; X86-SSE2: # %bb.0: # %entry
25+
; X86-SSE2-NEXT: subl $8, %esp
26+
; X86-SSE2-NEXT: pinsrw $0, {{[0-9]+}}(%esp), %xmm0
27+
; X86-SSE2-NEXT: pextrw $0, %xmm0, %eax
28+
; X86-SSE2-NEXT: movw %ax, (%esp)
29+
; X86-SSE2-NEXT: calll __extendhfsf2
30+
; X86-SSE2-NEXT: fstps (%esp)
31+
; X86-SSE2-NEXT: calll rintf
32+
; X86-SSE2-NEXT: fstps (%esp)
33+
; X86-SSE2-NEXT: calll __truncsfhf2
34+
; X86-SSE2-NEXT: pextrw $0, %xmm0, %eax
35+
; X86-SSE2-NEXT: movw %ax, (%esp)
36+
; X86-SSE2-NEXT: calll __extendhfsf2
37+
; X86-SSE2-NEXT: fstps {{[0-9]+}}(%esp)
38+
; X86-SSE2-NEXT: cvttss2si {{[0-9]+}}(%esp), %eax
39+
; X86-SSE2-NEXT: addl $8, %esp
40+
; X86-SSE2-NEXT: retl
41+
;
42+
; X64-SSE-LABEL: testmswh:
43+
; X64-SSE: # %bb.0: # %entry
44+
; X64-SSE-NEXT: pushq %rax
45+
; X64-SSE-NEXT: callq __extendhfsf2@PLT
46+
; X64-SSE-NEXT: callq rintf@PLT
47+
; X64-SSE-NEXT: callq __truncsfhf2@PLT
48+
; X64-SSE-NEXT: callq __extendhfsf2@PLT
49+
; X64-SSE-NEXT: cvttss2si %xmm0, %eax
50+
; X64-SSE-NEXT: popq %rcx
51+
; X64-SSE-NEXT: retq
52+
entry:
53+
%0 = tail call i32 @llvm.lrint.i32.f16(half %x)
54+
ret i32 %0
55+
}
1656

1757
define i32 @testmsws(float %x) nounwind {
1858
; X86-NOSSE-LABEL: testmsws:

0 commit comments

Comments
 (0)