Skip to content

[AArch64][GlobalISel] Expand handling for sitofp and uitofp #71282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 10, 2023

Conversation

davemgreen
Copy link
Collaborator

Similar to #70635, this expands the handling of integer to fp conversions. The code is very similar to the float->integer conversions with types handled oppositely. There are some extra unhandled cases which require more handling for ASR operations.

Similar to llvm#70635, this expands the handling of integer to fp conversions. The
code is very similar to the float->integer conversions with types handled
oppositely. There are some extra unhandled cases which require more handling
for ASR types.
@llvmbot
Copy link
Member

llvmbot commented Nov 4, 2023

@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

Changes

Similar to #70635, this expands the handling of integer to fp conversions. The code is very similar to the float->integer conversions with types handled oppositely. There are some extra unhandled cases which require more handling for ASR operations.


Patch is 230.88 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71282.diff

3 Files Affected:

  • (modified) llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp (+3-1)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp (+26-3)
  • (added) llvm/test/CodeGen/AArch64/itofp.ll (+6195)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 00d9f3f7c30c95f..cde5bc7d9a981f1 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -5126,7 +5126,9 @@ LegalizerHelper::moreElementsVector(MachineInstr &MI, unsigned TypeIdx,
   case TargetOpcode::G_FPTRUNC:
   case TargetOpcode::G_FPEXT:
   case TargetOpcode::G_FPTOSI:
-  case TargetOpcode::G_FPTOUI: {
+  case TargetOpcode::G_FPTOUI:
+  case TargetOpcode::G_SITOFP:
+  case TargetOpcode::G_UITOFP: {
     if (TypeIdx != 0)
       return UnableToLegalize;
     Observer.changingInstr(MI);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index 7edfa41d237836a..cd64be96e2d6b57 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -673,10 +673,33 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
 
   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
       .legalForCartesianProduct({s32, s64, v2s64, v4s32, v2s32})
+      .legalIf([=](const LegalityQuery &Query) {
+        return HasFP16 &&
+               (Query.Types[0] == s16 || Query.Types[0] == v4s16 ||
+                Query.Types[0] == v8s16) &&
+               (Query.Types[1] == s32 || Query.Types[1] == s64 ||
+                Query.Types[1] == v4s16 || Query.Types[1] == v8s16);
+      })
+      .widenScalarToNextPow2(1)
       .clampScalar(1, s32, s64)
-      .minScalarSameAs(1, 0)
-      .clampScalar(0, s32, s64)
-      .widenScalarToNextPow2(0);
+      .widenScalarToNextPow2(0)
+      .clampScalarOrElt(0, MinFPScalar, s64)
+      .moreElementsToNextPow2(0)
+      .widenScalarIf(
+          [=](const LegalityQuery &Query) {
+            return Query.Types[0].getScalarSizeInBits() <
+                   Query.Types[1].getScalarSizeInBits();
+          },
+          LegalizeMutations::changeElementSizeTo(0, 1))
+      .widenScalarIf(
+          [=](const LegalityQuery &Query) {
+            return Query.Types[0].getScalarSizeInBits() >
+                   Query.Types[1].getScalarSizeInBits();
+          },
+          LegalizeMutations::changeElementSizeTo(1, 0))
+      .clampNumElements(0, v4s16, v8s16)
+      .clampNumElements(0, v2s32, v4s32)
+      .clampMaxNumElements(0, s64, 2);
 
   // Control-flow
   getActionDefinitionsBuilder(G_BRCOND)
diff --git a/llvm/test/CodeGen/AArch64/itofp.ll b/llvm/test/CodeGen/AArch64/itofp.ll
new file mode 100644
index 000000000000000..fa5902c65ce05a0
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/itofp.ll
@@ -0,0 +1,6195 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
+; RUN: llc -mtriple=aarch64-none-eabi -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-SD-NOFP16
+; RUN: llc -mtriple=aarch64-none-eabi -mattr=+fullfp16 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD,CHECK-SD-FP16
+; RUN: llc -mtriple=aarch64-none-eabi -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-NOFP16
+; RUN: llc -mtriple=aarch64-none-eabi -mattr=+fullfp16 -global-isel -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI,CHECK-GI-FP16
+
+; CHECK-GI:       warning: Instruction selection used fallback path for stofp_v3i8_v3f64
+; CHECK-GI-NEXT:  warning: Instruction selection used fallback path for utofp_v3i8_v3f64
+; CHECK-GI-NEXT:  warning: Instruction selection used fallback path for stofp_v3i8_v3f32
+; CHECK-GI-NEXT:  warning: Instruction selection used fallback path for utofp_v3i8_v3f32
+; CHECK-GI-NOFP16-NEXT:  warning: Instruction selection used fallback path for stofp_v3i8_v3f16
+; CHECK-GI-NOFP16-NEXT:  warning: Instruction selection used fallback path for utofp_v3i8_v3f16
+; CHECK-GI-FP16-NEXT:  warning: Instruction selection used fallback path for stofp_v2i8_v2f16
+
+define double @stofp_i64_f64(i64 %a) {
+; CHECK-LABEL: stofp_i64_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf d0, x0
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i64 %a to double
+  ret double %c
+}
+
+define double @utofp_i64_f64(i64 %a) {
+; CHECK-LABEL: utofp_i64_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf d0, x0
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i64 %a to double
+  ret double %c
+}
+
+define double @stofp_i32_f64(i32 %a) {
+; CHECK-LABEL: stofp_i32_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf d0, w0
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i32 %a to double
+  ret double %c
+}
+
+define double @utofp_i32_f64(i32 %a) {
+; CHECK-LABEL: utofp_i32_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf d0, w0
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i32 %a to double
+  ret double %c
+}
+
+define double @stofp_i16_f64(i16 %a) {
+; CHECK-LABEL: stofp_i16_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    sxth w8, w0
+; CHECK-NEXT:    scvtf d0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i16 %a to double
+  ret double %c
+}
+
+define double @utofp_i16_f64(i16 %a) {
+; CHECK-LABEL: utofp_i16_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    and w8, w0, #0xffff
+; CHECK-NEXT:    ucvtf d0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i16 %a to double
+  ret double %c
+}
+
+define double @stofp_i8_f64(i8 %a) {
+; CHECK-LABEL: stofp_i8_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    sxtb w8, w0
+; CHECK-NEXT:    scvtf d0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i8 %a to double
+  ret double %c
+}
+
+define double @utofp_i8_f64(i8 %a) {
+; CHECK-LABEL: utofp_i8_f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    and w8, w0, #0xff
+; CHECK-NEXT:    ucvtf d0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i8 %a to double
+  ret double %c
+}
+
+define float @stofp_i64_f32(i64 %a) {
+; CHECK-LABEL: stofp_i64_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf s0, x0
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i64 %a to float
+  ret float %c
+}
+
+define float @utofp_i64_f32(i64 %a) {
+; CHECK-LABEL: utofp_i64_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf s0, x0
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i64 %a to float
+  ret float %c
+}
+
+define float @stofp_i32_f32(i32 %a) {
+; CHECK-LABEL: stofp_i32_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf s0, w0
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i32 %a to float
+  ret float %c
+}
+
+define float @utofp_i32_f32(i32 %a) {
+; CHECK-LABEL: utofp_i32_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf s0, w0
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i32 %a to float
+  ret float %c
+}
+
+define float @stofp_i16_f32(i16 %a) {
+; CHECK-LABEL: stofp_i16_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    sxth w8, w0
+; CHECK-NEXT:    scvtf s0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i16 %a to float
+  ret float %c
+}
+
+define float @utofp_i16_f32(i16 %a) {
+; CHECK-LABEL: utofp_i16_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    and w8, w0, #0xffff
+; CHECK-NEXT:    ucvtf s0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i16 %a to float
+  ret float %c
+}
+
+define float @stofp_i8_f32(i8 %a) {
+; CHECK-LABEL: stofp_i8_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    sxtb w8, w0
+; CHECK-NEXT:    scvtf s0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp i8 %a to float
+  ret float %c
+}
+
+define float @utofp_i8_f32(i8 %a) {
+; CHECK-LABEL: utofp_i8_f32:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    and w8, w0, #0xff
+; CHECK-NEXT:    ucvtf s0, w8
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp i8 %a to float
+  ret float %c
+}
+
+define half @stofp_i64_f16(i64 %a) {
+; CHECK-SD-NOFP16-LABEL: stofp_i64_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    scvtf s0, x0
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: stofp_i64_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    scvtf h0, x0
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: stofp_i64_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    scvtf s0, x0
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: stofp_i64_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    scvtf h0, x0
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = sitofp i64 %a to half
+  ret half %c
+}
+
+define half @utofp_i64_f16(i64 %a) {
+; CHECK-SD-NOFP16-LABEL: utofp_i64_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    ucvtf s0, x0
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: utofp_i64_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    ucvtf h0, x0
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: utofp_i64_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    ucvtf s0, x0
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: utofp_i64_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    ucvtf h0, x0
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = uitofp i64 %a to half
+  ret half %c
+}
+
+define half @stofp_i32_f16(i32 %a) {
+; CHECK-SD-NOFP16-LABEL: stofp_i32_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    scvtf s0, w0
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: stofp_i32_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    scvtf h0, w0
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: stofp_i32_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    scvtf s0, w0
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: stofp_i32_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    scvtf h0, w0
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = sitofp i32 %a to half
+  ret half %c
+}
+
+define half @utofp_i32_f16(i32 %a) {
+; CHECK-SD-NOFP16-LABEL: utofp_i32_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    ucvtf s0, w0
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: utofp_i32_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    ucvtf h0, w0
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: utofp_i32_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    ucvtf s0, w0
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: utofp_i32_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    ucvtf h0, w0
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = uitofp i32 %a to half
+  ret half %c
+}
+
+define half @stofp_i16_f16(i16 %a) {
+; CHECK-SD-NOFP16-LABEL: stofp_i16_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    sxth w8, w0
+; CHECK-SD-NOFP16-NEXT:    scvtf s0, w8
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: stofp_i16_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    sxth w8, w0
+; CHECK-SD-FP16-NEXT:    scvtf h0, w8
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: stofp_i16_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    sxth w8, w0
+; CHECK-GI-NOFP16-NEXT:    scvtf s0, w8
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: stofp_i16_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    sxth w8, w0
+; CHECK-GI-FP16-NEXT:    scvtf h0, w8
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = sitofp i16 %a to half
+  ret half %c
+}
+
+define half @utofp_i16_f16(i16 %a) {
+; CHECK-SD-NOFP16-LABEL: utofp_i16_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    and w8, w0, #0xffff
+; CHECK-SD-NOFP16-NEXT:    ucvtf s0, w8
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: utofp_i16_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    and w8, w0, #0xffff
+; CHECK-SD-FP16-NEXT:    ucvtf h0, w8
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: utofp_i16_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    and w8, w0, #0xffff
+; CHECK-GI-NOFP16-NEXT:    ucvtf s0, w8
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: utofp_i16_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    and w8, w0, #0xffff
+; CHECK-GI-FP16-NEXT:    ucvtf h0, w8
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = uitofp i16 %a to half
+  ret half %c
+}
+
+define half @stofp_i8_f16(i8 %a) {
+; CHECK-SD-NOFP16-LABEL: stofp_i8_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    sxtb w8, w0
+; CHECK-SD-NOFP16-NEXT:    scvtf s0, w8
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: stofp_i8_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    sxtb w8, w0
+; CHECK-SD-FP16-NEXT:    scvtf h0, w8
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: stofp_i8_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    sxtb w8, w0
+; CHECK-GI-NOFP16-NEXT:    scvtf s0, w8
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: stofp_i8_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    sxtb w8, w0
+; CHECK-GI-FP16-NEXT:    scvtf h0, w8
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = sitofp i8 %a to half
+  ret half %c
+}
+
+define half @utofp_i8_f16(i8 %a) {
+; CHECK-SD-NOFP16-LABEL: utofp_i8_f16:
+; CHECK-SD-NOFP16:       // %bb.0: // %entry
+; CHECK-SD-NOFP16-NEXT:    and w8, w0, #0xff
+; CHECK-SD-NOFP16-NEXT:    ucvtf s0, w8
+; CHECK-SD-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-SD-NOFP16-NEXT:    ret
+;
+; CHECK-SD-FP16-LABEL: utofp_i8_f16:
+; CHECK-SD-FP16:       // %bb.0: // %entry
+; CHECK-SD-FP16-NEXT:    and w8, w0, #0xff
+; CHECK-SD-FP16-NEXT:    ucvtf h0, w8
+; CHECK-SD-FP16-NEXT:    ret
+;
+; CHECK-GI-NOFP16-LABEL: utofp_i8_f16:
+; CHECK-GI-NOFP16:       // %bb.0: // %entry
+; CHECK-GI-NOFP16-NEXT:    and w8, w0, #0xff
+; CHECK-GI-NOFP16-NEXT:    ucvtf s0, w8
+; CHECK-GI-NOFP16-NEXT:    fcvt h0, s0
+; CHECK-GI-NOFP16-NEXT:    ret
+;
+; CHECK-GI-FP16-LABEL: utofp_i8_f16:
+; CHECK-GI-FP16:       // %bb.0: // %entry
+; CHECK-GI-FP16-NEXT:    and w8, w0, #0xff
+; CHECK-GI-FP16-NEXT:    ucvtf h0, w8
+; CHECK-GI-FP16-NEXT:    ret
+entry:
+  %c = uitofp i8 %a to half
+  ret half %c
+}
+
+define <2 x double> @stofp_v2i64_v2f64(<2 x i64> %a) {
+; CHECK-LABEL: stofp_v2i64_v2f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp <2 x i64> %a to <2 x double>
+  ret <2 x double> %c
+}
+
+define <2 x double> @utofp_v2i64_v2f64(<2 x i64> %a) {
+; CHECK-LABEL: utofp_v2i64_v2f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp <2 x i64> %a to <2 x double>
+  ret <2 x double> %c
+}
+
+define <3 x double> @stofp_v3i64_v3f64(<3 x i64> %a) {
+; CHECK-SD-LABEL: stofp_v3i64_v3f64:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-SD-NEXT:    // kill: def $d2 killed $d2 def $q2
+; CHECK-SD-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-SD-NEXT:    scvtf v2.2d, v2.2d
+; CHECK-SD-NEXT:    // kill: def $d2 killed $d2 killed $q2
+; CHECK-SD-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-SD-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: stofp_v3i64_v3f64:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT:    // kill: def $d2 killed $d2 def $q2
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-GI-NEXT:    scvtf v2.2d, v2.2d
+; CHECK-GI-NEXT:    // kill: def $d2 killed $d2 killed $q2
+; CHECK-GI-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-GI-NEXT:    mov d1, v0.d[1]
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
+entry:
+  %c = sitofp <3 x i64> %a to <3 x double>
+  ret <3 x double> %c
+}
+
+define <3 x double> @utofp_v3i64_v3f64(<3 x i64> %a) {
+; CHECK-SD-LABEL: utofp_v3i64_v3f64:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-SD-NEXT:    // kill: def $d2 killed $d2 def $q2
+; CHECK-SD-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-SD-NEXT:    ucvtf v2.2d, v2.2d
+; CHECK-SD-NEXT:    // kill: def $d2 killed $d2 killed $q2
+; CHECK-SD-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-SD-NEXT:    ext v1.16b, v0.16b, v0.16b, #8
+; CHECK-SD-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-SD-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: utofp_v3i64_v3f64:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
+; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 def $q1
+; CHECK-GI-NEXT:    // kill: def $d2 killed $d2 def $q2
+; CHECK-GI-NEXT:    mov v0.d[1], v1.d[0]
+; CHECK-GI-NEXT:    ucvtf v2.2d, v2.2d
+; CHECK-GI-NEXT:    // kill: def $d2 killed $d2 killed $q2
+; CHECK-GI-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-GI-NEXT:    mov d1, v0.d[1]
+; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-GI-NEXT:    ret
+entry:
+  %c = uitofp <3 x i64> %a to <3 x double>
+  ret <3 x double> %c
+}
+
+define <4 x double> @stofp_v4i64_v4f64(<4 x i64> %a) {
+; CHECK-LABEL: stofp_v4i64_v4f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-NEXT:    scvtf v1.2d, v1.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp <4 x i64> %a to <4 x double>
+  ret <4 x double> %c
+}
+
+define <4 x double> @utofp_v4i64_v4f64(<4 x i64> %a) {
+; CHECK-LABEL: utofp_v4i64_v4f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-NEXT:    ucvtf v1.2d, v1.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp <4 x i64> %a to <4 x double>
+  ret <4 x double> %c
+}
+
+define <8 x double> @stofp_v8i64_v8f64(<8 x i64> %a) {
+; CHECK-LABEL: stofp_v8i64_v8f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-NEXT:    scvtf v1.2d, v1.2d
+; CHECK-NEXT:    scvtf v2.2d, v2.2d
+; CHECK-NEXT:    scvtf v3.2d, v3.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp <8 x i64> %a to <8 x double>
+  ret <8 x double> %c
+}
+
+define <8 x double> @utofp_v8i64_v8f64(<8 x i64> %a) {
+; CHECK-LABEL: utofp_v8i64_v8f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-NEXT:    ucvtf v1.2d, v1.2d
+; CHECK-NEXT:    ucvtf v2.2d, v2.2d
+; CHECK-NEXT:    ucvtf v3.2d, v3.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = uitofp <8 x i64> %a to <8 x double>
+  ret <8 x double> %c
+}
+
+define <16 x double> @stofp_v16i64_v16f64(<16 x i64> %a) {
+; CHECK-LABEL: stofp_v16i64_v16f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    scvtf v0.2d, v0.2d
+; CHECK-NEXT:    scvtf v1.2d, v1.2d
+; CHECK-NEXT:    scvtf v2.2d, v2.2d
+; CHECK-NEXT:    scvtf v3.2d, v3.2d
+; CHECK-NEXT:    scvtf v4.2d, v4.2d
+; CHECK-NEXT:    scvtf v5.2d, v5.2d
+; CHECK-NEXT:    scvtf v6.2d, v6.2d
+; CHECK-NEXT:    scvtf v7.2d, v7.2d
+; CHECK-NEXT:    ret
+entry:
+  %c = sitofp <16 x i64> %a to <16 x double>
+  ret <16 x double> %c
+}
+
+define <16 x double> @utofp_v16i64_v16f64(<16 x i64> %a) {
+; CHECK-LABEL: utofp_v16i64_v16f64:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    ucvtf v0.2d, v0.2d
+; CHECK-NEXT:    ucvtf v1.2d, v1.2d
+; CHECK-NEXT:    ucvtf v2.2d, v2.2d
+; CHECK-NEXT:    ucvtf v3.2d, v3.2d
+; CHECK-NEXT:    ucvtf v4.2d, v4.2d
+; CHECK-NEXT:    ucvtf v5.2d, v5.2d
+; CHECK-NEXT:    ucvtf v6.2d, v6.2d
+; CH...
[truncated]

@@ -673,10 +673,33 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)

getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
.legalForCartesianProduct({s32, s64, v2s64, v4s32, v2s32})
.legalIf([=](const LegalityQuery &Query) {
return HasFP16 &&
Copy link

@tschuett tschuett Nov 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typeInSet(0, {s16, v4s16, v8s16})(Query) && typeInSet(1, {s32, s64, v4s16, v8s16})(Query)

Or

.legalForCartesianProduct(Is64Bit ? PtrTypes64 : PtrTypes32, {p0})

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello. This way at least feels clear to me what is going on and matches what we have elsewhere. We might be able to adjust them in the future to clean things up, but for the moment it's probably best to keep G_SITOFP similar to G_FPTOSI.

I'm interested to hear your suggestions if we can make the whole things clearer. Maybe it would be worth having a .legalIf(HasFP16, {{s16, s32}, {s16, s64}, ...})

@davemgreen davemgreen merged commit 10ce319 into llvm:main Nov 10, 2023
@davemgreen davemgreen deleted the gh-gi-itofp branch November 10, 2023 13:41
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
Similar to llvm#70635, this expands the handling of integer to fp
conversions. The code is very similar to the float->integer conversions
with types handled oppositely. There are some extra unhandled cases
which require more handling for ASR operations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants