[llvm] 0408b13 - [SelectionDAG][AVR] Add support for lrint and lround intrinsics
Ayke van Laethem via llvm-commits
llvm-commits at lists.llvm.org
Sun Jan 8 09:56:36 PST 2023
Author: Ayke van Laethem
Date: 2023-01-08T18:56:07+01:00
New Revision: 0408b131eb66ef842e7d57c1a0410a2a14f891ac
URL: https://github.com/llvm/llvm-project/commit/0408b131eb66ef842e7d57c1a0410a2a14f891ac
DIFF: https://github.com/llvm/llvm-project/commit/0408b131eb66ef842e7d57c1a0410a2a14f891ac.diff
LOG: [SelectionDAG][AVR] Add support for lrint and lround intrinsics
Integer legalization already supported splitting the output integer of
llround and llrint, but did not support this for lround and lrint yet.
This is not a problem for 32-bit architectures, but for 8/16-bit
architectures like AVR it results in a crash like this:
ExpandIntegerResult #0: t7: i32 = lround t6
LLVM ERROR: Do not know how to expand the result of this operator!
This patch simply add lrint/lround to the list of ISD opcodes to expand.
Fixes https://github.com/llvm/llvm-project/issues/59573.
Differential Revision: https://reviews.llvm.org/D140822
Added:
llvm/test/CodeGen/AVR/llrint.ll
llvm/test/CodeGen/AVR/llround-conv.ll
llvm/test/CodeGen/AVR/lrint.ll
llvm/test/CodeGen/AVR/lround-conv.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index 2e4ccaebf02b3..4e640247a5bf7 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -2435,10 +2435,14 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break;
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT: ExpandIntRes_FP_TO_XINT_SAT(N, Lo, Hi); break;
+ case ISD::STRICT_LROUND:
+ case ISD::STRICT_LRINT:
+ case ISD::LROUND:
+ case ISD::LRINT:
case ISD::STRICT_LLROUND:
case ISD::STRICT_LLRINT:
case ISD::LLROUND:
- case ISD::LLRINT: ExpandIntRes_LLROUND_LLRINT(N, Lo, Hi); break;
+ case ISD::LLRINT: ExpandIntRes_XROUND_XRINT(N, Lo, Hi); break;
case ISD::LOAD: ExpandIntRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break;
case ISD::READCYCLECOUNTER: ExpandIntRes_READCYCLECOUNTER(N, Lo, Hi); break;
@@ -3474,8 +3478,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_XINT_SAT(SDNode *N, SDValue &Lo,
SplitInteger(Res, Lo, Hi);
}
-void DAGTypeLegalizer::ExpandIntRes_LLROUND_LLRINT(SDNode *N, SDValue &Lo,
- SDValue &Hi) {
+void DAGTypeLegalizer::ExpandIntRes_XROUND_XRINT(SDNode *N, SDValue &Lo,
+ SDValue &Hi) {
SDLoc dl(N);
bool IsStrict = N->isStrictFPOpcode();
SDValue Op = N->getOperand(IsStrict ? 1 : 0);
@@ -3498,7 +3502,33 @@ void DAGTypeLegalizer::ExpandIntRes_LLROUND_LLRINT(SDNode *N, SDValue &Lo,
}
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (N->getOpcode() == ISD::LLROUND ||
+ if (N->getOpcode() == ISD::LROUND ||
+ N->getOpcode() == ISD::STRICT_LROUND) {
+ if (VT == MVT::f32)
+ LC = RTLIB::LROUND_F32;
+ else if (VT == MVT::f64)
+ LC = RTLIB::LROUND_F64;
+ else if (VT == MVT::f80)
+ LC = RTLIB::LROUND_F80;
+ else if (VT == MVT::f128)
+ LC = RTLIB::LROUND_F128;
+ else if (VT == MVT::ppcf128)
+ LC = RTLIB::LROUND_PPCF128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected lround input type!");
+ } else if (N->getOpcode() == ISD::LRINT ||
+ N->getOpcode() == ISD::STRICT_LRINT) {
+ if (VT == MVT::f32)
+ LC = RTLIB::LRINT_F32;
+ else if (VT == MVT::f64)
+ LC = RTLIB::LRINT_F64;
+ else if (VT == MVT::f80)
+ LC = RTLIB::LRINT_F80;
+ else if (VT == MVT::f128)
+ LC = RTLIB::LRINT_F128;
+ else if (VT == MVT::ppcf128)
+ LC = RTLIB::LRINT_PPCF128;
+ assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected lrint input type!");
+ } else if (N->getOpcode() == ISD::LLROUND ||
N->getOpcode() == ISD::STRICT_LLROUND) {
if (VT == MVT::f32)
LC = RTLIB::LLROUND_F32;
diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index e57a030fe143f..4dea7d663af13 100644
--- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -441,7 +441,7 @@ class LLVM_LIBRARY_VISIBILITY DAGTypeLegalizer {
void ExpandIntRes_FP_TO_SINT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_FP_TO_UINT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_FP_TO_XINT_SAT (SDNode *N, SDValue &Lo, SDValue &Hi);
- void ExpandIntRes_LLROUND_LLRINT (SDNode *N, SDValue &Lo, SDValue &Hi);
+ void ExpandIntRes_XROUND_XRINT (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_Logical (SDNode *N, SDValue &Lo, SDValue &Hi);
void ExpandIntRes_ADDSUB (SDNode *N, SDValue &Lo, SDValue &Hi);
diff --git a/llvm/test/CodeGen/AVR/llrint.ll b/llvm/test/CodeGen/AVR/llrint.ll
new file mode 100644
index 0000000000000..32b4c7ab12a4b
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/llrint.ll
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s
+
+define i64 @testmsxs_builtin(float %x) {
+; CHECK-LABEL: testmsxs_builtin:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llrintf
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llrint.f32(float %x)
+ ret i64 %0
+}
+
+define i64 @testmsxd_builtin(double %x) {
+; CHECK-LABEL: testmsxd_builtin:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llrint
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llrint.f64(double %x)
+ ret i64 %0
+}
+
+declare i64 @llvm.llrint.f32(float) nounwind readnone
+declare i64 @llvm.llrint.f64(double) nounwind readnone
diff --git a/llvm/test/CodeGen/AVR/llround-conv.ll b/llvm/test/CodeGen/AVR/llround-conv.ll
new file mode 100644
index 0000000000000..3e81d082735f2
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/llround-conv.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s
+
+define signext i32 @testmsws(float %x) {
+; CHECK-LABEL: testmsws:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llroundf
+; CHECK-NEXT: movw r22, r18
+; CHECK-NEXT: movw r24, r20
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llround.i64.f32(float %x)
+ %conv = trunc i64 %0 to i32
+ ret i32 %conv
+}
+
+define i64 @testmsxs(float %x) {
+; CHECK-LABEL: testmsxs:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llroundf
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llround.i64.f32(float %x)
+ ret i64 %0
+}
+
+define signext i32 @testmswd(double %x) {
+; CHECK-LABEL: testmswd:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llround
+; CHECK-NEXT: movw r22, r18
+; CHECK-NEXT: movw r24, r20
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llround.i64.f64(double %x)
+ %conv = trunc i64 %0 to i32
+ ret i32 %conv
+}
+
+define i64 @testmsxd(double %x) {
+; CHECK-LABEL: testmsxd:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call llround
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i64 @llvm.llround.i64.f64(double %x)
+ ret i64 %0
+}
+
+declare i64 @llvm.llround.i64.f32(float) nounwind readnone
+declare i64 @llvm.llround.i64.f64(double) nounwind readnone
diff --git a/llvm/test/CodeGen/AVR/lrint.ll b/llvm/test/CodeGen/AVR/lrint.ll
new file mode 100644
index 0000000000000..d7568305f7b51
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/lrint.ll
@@ -0,0 +1,25 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s
+
+define i32 @testmsws_builtin(float %x) {
+; CHECK-LABEL: testmsws_builtin:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lrintf
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lrint.i32.f32(float %x)
+ ret i32 %0
+}
+
+define i32 @testmswd_builtin(double %x) {
+; CHECK-LABEL: testmswd_builtin:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lrint
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lrint.i32.f64(double %x)
+ ret i32 %0
+}
+
+declare i32 @llvm.lrint.i32.f32(float) nounwind readnone
+declare i32 @llvm.lrint.i32.f64(double) nounwind readnone
diff --git a/llvm/test/CodeGen/AVR/lround-conv.ll b/llvm/test/CodeGen/AVR/lround-conv.ll
new file mode 100644
index 0000000000000..aaf7af8e4805f
--- /dev/null
+++ b/llvm/test/CodeGen/AVR/lround-conv.ll
@@ -0,0 +1,49 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=avr -mcpu=atmega328p | FileCheck %s
+
+define signext i16 @testmsws(float %x) {
+; CHECK-LABEL: testmsws:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lroundf
+; CHECK-NEXT: movw r24, r22
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lround.i32.f32(float %x)
+ %conv = trunc i32 %0 to i16
+ ret i16 %conv
+}
+
+define i32 @testmsxs(float %x) {
+; CHECK-LABEL: testmsxs:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lroundf
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lround.i32.f32(float %x)
+ ret i32 %0
+}
+
+define signext i16 @testmswd(double %x) {
+; CHECK-LABEL: testmswd:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lround
+; CHECK-NEXT: movw r24, r22
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lround.i32.f64(double %x)
+ %conv = trunc i32 %0 to i16
+ ret i16 %conv
+}
+
+define i32 @testmsxd(double %x) {
+; CHECK-LABEL: testmsxd:
+; CHECK: ; %bb.0: ; %entry
+; CHECK-NEXT: call lround
+; CHECK-NEXT: ret
+entry:
+ %0 = tail call i32 @llvm.lround.i32.f64(double %x)
+ ret i32 %0
+}
+
+declare i32 @llvm.lround.i32.f32(float) nounwind readnone
+declare i32 @llvm.lround.i32.f64(double) nounwind readnone
More information about the llvm-commits
mailing list