From ba72823998bf68dc7079c1bc42a6a8a1a92dcf96 Mon Sep 17 00:00:00 2001 From: Demetrius Kanios Date: Thu, 30 Apr 2026 10:03:24 -0700 Subject: [PATCH] [WebAssembly][GlobalISel] Implement basic floating point instructions (#194798) Adds `RegBankSelect` support for floats, and adds legalization of most basic FP instructions. Split from #157161 --- .../GISel/WebAssemblyLegalizerInfo.cpp | 35 +++++++++++++-- .../GISel/WebAssemblyRegisterBankInfo.cpp | 12 ++++- .../GlobalISel/instructions/fabs.ll | 29 ++++++++++++ .../GlobalISel/instructions/fadd.ll | 28 ++++++++++++ .../GlobalISel/instructions/fceil.ll | 29 ++++++++++++ .../GlobalISel/instructions/fconstant.ll | 22 ++++++++++ .../GlobalISel/instructions/fcopysign.ll | 31 +++++++++++++ .../GlobalISel/instructions/fcopysign.mir | 44 +++++++++++++++++++ .../GlobalISel/instructions/fdiv.ll | 28 ++++++++++++ .../GlobalISel/instructions/ffloor.ll | 29 ++++++++++++ .../GlobalISel/instructions/fmul.ll | 28 ++++++++++++ .../GlobalISel/instructions/fnearbyint.ll | 29 ++++++++++++ .../GlobalISel/instructions/fneg.mir | 37 ++++++++++++++++ .../GlobalISel/instructions/fpext.ll | 15 +++++++ .../GlobalISel/instructions/fptrunc.ll | 15 +++++++ .../GlobalISel/instructions/frint.ll | 29 ++++++++++++ .../GlobalISel/instructions/fsqrt.ll | 29 ++++++++++++ .../GlobalISel/instructions/fsub.ll | 28 ++++++++++++ .../GlobalISel/instructions/implicit_def.mir | 32 ++++++++++++++ .../instructions/intrinsic_roundeven.ll | 29 ++++++++++++ .../instructions/intrinsic_trunc.ll | 29 ++++++++++++ 21 files changed, 583 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fabs.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fadd.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fceil.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fconstant.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.mir create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fdiv.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ffloor.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmul.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fnearbyint.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fneg.mir create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fpext.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptrunc.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frint.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsqrt.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsub.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_roundeven.ll create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_trunc.ll diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp index 12c53c788f7b..7178934ccd1a 100644 --- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp +++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp @@ -28,12 +28,19 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo( const LLT i32 = LLT::integer(32); const LLT i64 = LLT::integer(64); + const LLT f32 = LLT::floatIEEE(32); + const LLT f64 = LLT::floatIEEE(64); + const LLT s32 = LLT::scalar(32); const LLT s64 = LLT::scalar(64); - getActionDefinitionsBuilder({G_CONSTANT, G_IMPLICIT_DEF, G_ADD, G_SUB, G_MUL, - G_UDIV, G_SDIV, G_UREM, G_SREM, G_AND, G_OR, - G_XOR}) + getActionDefinitionsBuilder(G_IMPLICIT_DEF) + .legalFor({i32, i64, f32, f64}) + .widenScalarToNextPow2(0) + .clampScalar(0, s32, s64); + + getActionDefinitionsBuilder({G_CONSTANT, G_ADD, G_SUB, G_MUL, G_UDIV, G_SDIV, + G_UREM, G_SREM, G_AND, G_OR, G_XOR}) .legalFor({i32, i64}) .widenScalarToNextPow2(0) .clampScalar(0, s32, s64); @@ -74,6 +81,28 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo( .clampScalar(0, s32, s64) .lower(); + getActionDefinitionsBuilder({G_FCONSTANT, G_FABS, G_FNEG, G_FCEIL, G_FFLOOR, + G_INTRINSIC_TRUNC, G_FNEARBYINT, G_FRINT, + G_INTRINSIC_ROUNDEVEN, G_FSQRT, G_FADD, G_FSUB, + G_FMUL, G_FDIV}) + .legalFor({f32, f64}) + .minScalar(0, s32); + + getActionDefinitionsBuilder(G_FCOPYSIGN) + .legalFor({f32, f64}) + .minScalar(0, s32) + .scalarSameSizeAs(1, 0); + + getActionDefinitionsBuilder(G_FPEXT) + .legalFor({{f64, f32}}) + .clampScalar(0, s64, s64) + .clampScalar(1, s32, s32); + + getActionDefinitionsBuilder(G_FPTRUNC) + .legalFor({{f32, f64}}) + .clampScalar(0, s32, s32) + .clampScalar(1, s64, s64); + getLegacyLegalizerInfo().computeTables(); } diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp index 3d370d04c087..7e50ca6ab22f 100644 --- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp +++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp @@ -28,11 +28,15 @@ enum PartialMappingIdx { PMI_None = -1, PMI_I32 = 1, PMI_I64, + PMI_F32, + PMI_F64, PMI_Min = PMI_I32, }; const RegisterBankInfo::PartialMapping PartMappings[]{{0, 32, I32RegBank}, - {0, 64, I64RegBank}}; + {0, 64, I64RegBank}, + {0, 32, F32RegBank}, + {0, 64, F64RegBank}}; } // namespace WebAssembly } // namespace llvm @@ -79,6 +83,12 @@ WebAssemblyRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { } else if (OpSize[Idx] == 64) { OpRegBankIdx[Idx] = WebAssembly::PMI_I64; } + } else if (Ty.isFloatIEEE()) { + if (OpSize[Idx] == 32) { + OpRegBankIdx[Idx] = WebAssembly::PMI_F32; + } else if (OpSize[Idx] == 64) { + OpRegBankIdx[Idx] = WebAssembly::PMI_F64; + } } } diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fabs.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fabs.ll new file mode 100644 index 000000000000..b72b89b463cd --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fabs.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.fabs.f32(float) +declare double @llvm.fabs.f64(double) + +define float @fabs_f32(float %x) { +; CHECK-LABEL: fabs_f32: +; CHECK: .functype fabs_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.abs $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.fabs.f32(float %x) + ret float %a +} + +define double @fabs_f64(double %x) { +; CHECK-LABEL: fabs_f64: +; CHECK: .functype fabs_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.abs $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.fabs.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fadd.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fadd.ll new file mode 100644 index 000000000000..beb64f48e75b --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fadd.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @fadd_f32(float %x, float %y) { +; CHECK-LABEL: fadd_f32: +; CHECK: .functype fadd_f32 (f32, f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f32.add $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fadd float %x, %y + ret float %a +} + +define double @fadd_f64(double %x, double %y) { +; CHECK-LABEL: fadd_f64: +; CHECK: .functype fadd_f64 (f64, f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f64.add $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fadd double %x, %y + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fceil.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fceil.ll new file mode 100644 index 000000000000..748b3575ca98 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fceil.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.ceil.f32(float) +declare double @llvm.ceil.f64(double) + +define float @fceil_f32(float %x) { +; CHECK-LABEL: fceil_f32: +; CHECK: .functype fceil_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.ceil $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.ceil.f32(float %x) + ret float %a +} + +define double @fceil_f64(double %x) { +; CHECK-LABEL: fceil_f64: +; CHECK: .functype fceil_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.ceil $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.ceil.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fconstant.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fconstant.ll new file mode 100644 index 000000000000..df5ff9f96348 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fconstant.ll @@ -0,0 +1,22 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @const_f32() { +; CHECK-LABEL: const_f32: +; CHECK: .functype const_f32 () -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: f32.const $push0=, 0x1.91eb86p1 +; CHECK-NEXT: return $pop0 + ret float 3.14 +} + +define double @const_f64() { +; CHECK-LABEL: const_f64: +; CHECK: .functype const_f64 () -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: f64.const $push0=, 0x1.91eb851eb851fp2 +; CHECK-NEXT: return $pop0 + ret double 6.28 +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.ll new file mode 100644 index 000000000000..566ee89a37e2 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.ll @@ -0,0 +1,31 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.copysign.f32(float, float) +declare double @llvm.copysign.f64(double, double) + +define float @fcopysign_f32(float %x, float %y) { +; CHECK-LABEL: fcopysign_f32: +; CHECK: .functype fcopysign_f32 (f32, f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f32.copysign $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.copysign.f32(float %x, float %y) + ret float %a +} + +define double @fcopysign_f64(double %x, double %y) { +; CHECK-LABEL: fcopysign_f64: +; CHECK: .functype fcopysign_f64 (f64, f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f64.copysign $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.copysign.f64(double %x, double %y) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.mir new file mode 100644 index 000000000000..9f7b0df4d9bb --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcopysign.mir @@ -0,0 +1,44 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6 +# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s + +--- +name: fcopysign_f32_from_f64 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: fcopysign_f32_from_f64 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_f32_:%[0-9]+]]:f32 = ARGUMENT_f32 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_f64_:%[0-9]+]]:f64 = ARGUMENT_f64 1, implicit $arguments + ; CHECK-NEXT: [[F32_DEMOTE_F64_:%[0-9]+]]:f32 = F32_DEMOTE_F64 [[ARGUMENT_f64_]], implicit-def dead $arguments + ; CHECK-NEXT: [[COPYSIGN_F32_:%[0-9]+]]:f32 = COPYSIGN_F32 [[ARGUMENT_f32_]], [[F32_DEMOTE_F64_]], implicit-def dead $arguments + ; CHECK-NEXT: RETURN [[COPYSIGN_F32_]], implicit-def $arguments + %0:f32(f32) = ARGUMENT_f32 0, implicit $arguments + %1:f64(f64) = ARGUMENT_f64 1, implicit $arguments + %2:_(f32) = G_FCOPYSIGN %0, %1(f64) + RETURN %2(f32), implicit-def $arguments +... + +--- +name: fcopysign_f64_from_f32 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: fcopysign_f64_from_f32 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_f64_:%[0-9]+]]:f64 = ARGUMENT_f64 0, implicit $arguments + ; CHECK-NEXT: [[ARGUMENT_f32_:%[0-9]+]]:f32 = ARGUMENT_f32 1, implicit $arguments + ; CHECK-NEXT: [[F64_PROMOTE_F32_:%[0-9]+]]:f64 = F64_PROMOTE_F32 [[ARGUMENT_f32_]], implicit-def dead $arguments + ; CHECK-NEXT: [[COPYSIGN_F64_:%[0-9]+]]:f64 = COPYSIGN_F64 [[ARGUMENT_f64_]], [[F64_PROMOTE_F32_]], implicit-def dead $arguments + ; CHECK-NEXT: RETURN [[COPYSIGN_F64_]], implicit-def $arguments + %0:f64(f64) = ARGUMENT_f64 0, implicit $arguments + %1:f32(f32) = ARGUMENT_f32 1, implicit $arguments + %2:_(f64) = G_FCOPYSIGN %0, %1(f32) + RETURN %2(f64), implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fdiv.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fdiv.ll new file mode 100644 index 000000000000..303f9d10a371 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fdiv.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @fdiv_f32(float %x, float %y) { +; CHECK-LABEL: fdiv_f32: +; CHECK: .functype fdiv_f32 (f32, f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f32.div $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fdiv float %x, %y + ret float %a +} + +define double @fdiv_f64(double %x, double %y) { +; CHECK-LABEL: fdiv_f64: +; CHECK: .functype fdiv_f64 (f64, f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f64.div $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fdiv double %x, %y + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ffloor.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ffloor.ll new file mode 100644 index 000000000000..35647fe1477b --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ffloor.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.floor.f32(float) +declare double @llvm.floor.f64(double) + +define float @ffloor_f32(float %x) { +; CHECK-LABEL: ffloor_f32: +; CHECK: .functype ffloor_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.floor $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.floor.f32(float %x) + ret float %a +} + +define double @ffloor_f64(double %x) { +; CHECK-LABEL: ffloor_f64: +; CHECK: .functype ffloor_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.floor $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.floor.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmul.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmul.ll new file mode 100644 index 000000000000..7a11ed8ed55d --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmul.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @fmul_f32(float %x, float %y) { +; CHECK-LABEL: fmul_f32: +; CHECK: .functype fmul_f32 (f32, f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f32.mul $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fmul float %x, %y + ret float %a +} + +define double @fmul_f64(double %x, double %y) { +; CHECK-LABEL: fmul_f64: +; CHECK: .functype fmul_f64 (f64, f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f64.mul $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fmul double %x, %y + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fnearbyint.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fnearbyint.ll new file mode 100644 index 000000000000..da3704393635 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fnearbyint.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.nearbyint.f32(float) +declare double @llvm.nearbyint.f64(double) + +define float @fnearbyint_f32(float %x) { +; CHECK-LABEL: fnearbyint_f32: +; CHECK: .functype fnearbyint_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.nearbyint.f32(float %x) + ret float %a +} + +define double @fnearbyint_f64(double %x) { +; CHECK-LABEL: fnearbyint_f64: +; CHECK: .functype fnearbyint_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.nearbyint.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fneg.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fneg.mir new file mode 100644 index 000000000000..82e959b0fcaf --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fneg.mir @@ -0,0 +1,37 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6 +# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s + +--- +name: fneg_f32 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: fneg_f32 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_f32_:%[0-9]+]]:f32 = ARGUMENT_f32 0, implicit $arguments + ; CHECK-NEXT: [[NEG_F32_:%[0-9]+]]:f32 = NEG_F32 [[ARGUMENT_f32_]], implicit-def dead $arguments + ; CHECK-NEXT: RETURN [[NEG_F32_]], implicit-def $arguments + %0:f32(f32) = ARGUMENT_f32 0, implicit $arguments + %1:_(f32) = G_FNEG %0 + RETURN %1(f32), implicit-def $arguments +... +--- +name: fneg_f64 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: fneg_f64 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[ARGUMENT_f64_:%[0-9]+]]:f64 = ARGUMENT_f64 0, implicit $arguments + ; CHECK-NEXT: [[NEG_F64_:%[0-9]+]]:f64 = NEG_F64 [[ARGUMENT_f64_]], implicit-def dead $arguments + ; CHECK-NEXT: RETURN [[NEG_F64_]], implicit-def $arguments + %0:f64(f64) = ARGUMENT_f64 0, implicit $arguments + %1:_(f64) = G_FNEG %0 + RETURN %1(f64), implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fpext.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fpext.ll new file mode 100644 index 000000000000..ee59925b1b58 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fpext.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define double @fpext_f32_to_f64(float %x) { +; CHECK-LABEL: fpext_f32_to_f64: +; CHECK: .functype fpext_f32_to_f64 (f32) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.promote_f32 $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = fpext float %x to double + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptrunc.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptrunc.ll new file mode 100644 index 000000000000..fd0748b3dbc8 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptrunc.ll @@ -0,0 +1,15 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @fptrunc_f64_to_f32(double %x) { +; CHECK-LABEL: fptrunc_f64_to_f32: +; CHECK: .functype fptrunc_f64_to_f32 (f64) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.demote_f64 $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = fptrunc double %x to float + ret float %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frint.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frint.ll new file mode 100644 index 000000000000..0876a70a8a5d --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frint.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.rint.f32(float) +declare double @llvm.rint.f64(double) + +define float @frint_f32(float %x) { +; CHECK-LABEL: frint_f32: +; CHECK: .functype frint_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.rint.f32(float %x) + ret float %a +} + +define double @frint_f64(double %x) { +; CHECK-LABEL: frint_f64: +; CHECK: .functype frint_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.rint.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsqrt.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsqrt.ll new file mode 100644 index 000000000000..4c04f56b2a3b --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsqrt.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.sqrt.f32(float) +declare double @llvm.sqrt.f64(double) + +define float @fsqrt_f32(float %x) { +; CHECK-LABEL: fsqrt_f32: +; CHECK: .functype fsqrt_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.sqrt $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.sqrt.f32(float %x) + ret float %a +} + +define double @fsqrt_f64(double %x) { +; CHECK-LABEL: fsqrt_f64: +; CHECK: .functype fsqrt_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.sqrt $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.sqrt.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsub.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsub.ll new file mode 100644 index 000000000000..4546272c6bcc --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fsub.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +define float @fsub_f32(float %x, float %y) { +; CHECK-LABEL: fsub_f32: +; CHECK: .functype fsub_f32 (f32, f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f32.sub $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fsub float %x, %y + ret float %a +} + +define double @fsub_f64(double %x, double %y) { +; CHECK-LABEL: fsub_f64: +; CHECK: .functype fsub_f64 (f64, f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push2=, 0 +; CHECK-NEXT: local.get $push1=, 1 +; CHECK-NEXT: f64.sub $push0=, $pop2, $pop1 +; CHECK-NEXT: return $pop0 + %a = fsub double %x, %y + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir index 38d464c11312..3498ff229ca8 100644 --- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir @@ -66,3 +66,35 @@ body: | %0:_(i64) = G_IMPLICIT_DEF RETURN %0(i64), implicit-def $arguments ... + +--- +name: implicit_def_f32 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: implicit_def_f32 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[DEF:%[0-9]+]]:f32 = IMPLICIT_DEF + ; CHECK-NEXT: RETURN [[DEF]], implicit-def $arguments + %0:_(f32) = G_IMPLICIT_DEF + RETURN %0(f32), implicit-def $arguments +... + +--- +name: implicit_def_f64 +tracksRegLiveness: true +body: | + bb.1.entry: + liveins: $arguments + + ; CHECK-LABEL: name: implicit_def_f64 + ; CHECK: liveins: $arguments + ; CHECK-NEXT: {{ $}} + ; CHECK-NEXT: [[DEF:%[0-9]+]]:f64 = IMPLICIT_DEF + ; CHECK-NEXT: RETURN [[DEF]], implicit-def $arguments + %0:_(f64) = G_IMPLICIT_DEF + RETURN %0(f64), implicit-def $arguments +... diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_roundeven.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_roundeven.ll new file mode 100644 index 000000000000..7041975a0b38 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_roundeven.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.round.f32(float) +declare double @llvm.roundeven.f64(double) + +define float @intrinsic_roundeven_f32(float %x) { +; CHECK-LABEL: intrinsic_roundeven_f32: +; CHECK: .functype intrinsic_roundeven_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.roundeven.f32(float %x) + ret float %a +} + +define double @intrinsic_roundeven_f64(double %x) { +; CHECK-LABEL: intrinsic_roundeven_f64: +; CHECK: .functype intrinsic_roundeven_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.nearest $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.roundeven.f64(double %x) + ret double %a +} diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_trunc.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_trunc.ll new file mode 100644 index 000000000000..ddf6d898e5d1 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/intrinsic_trunc.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 +; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s + +target triple = "wasm32-unknown-unknown" + +declare float @llvm.trunc.f32(float) +declare double @llvm.trunc.f64(double) + +define float @intrinsic_trunc_f32(float %x) { +; CHECK-LABEL: intrinsic_trunc_f32: +; CHECK: .functype intrinsic_trunc_f32 (f32) -> (f32) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f32.trunc $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call float @llvm.trunc.f32(float %x) + ret float %a +} + +define double @intrinsic_trunc_f64(double %x) { +; CHECK-LABEL: intrinsic_trunc_f64: +; CHECK: .functype intrinsic_trunc_f64 (f64) -> (f64) +; CHECK-NEXT: # %bb.0: +; CHECK-NEXT: local.get $push1=, 0 +; CHECK-NEXT: f64.trunc $push0=, $pop1 +; CHECK-NEXT: return $pop0 + %a = call double @llvm.trunc.f64(double %x) + ret double %a +}