[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