[WebAssembly][GlobalISel] Implement basic floating point instructions (#194798)

Adds `RegBankSelect` support for floats, and adds legalization of most
basic FP instructions.

Split from #157161
This commit is contained in:
Demetrius Kanios
2026-04-30 10:03:24 -07:00
committed by GitHub
parent 2b0fde2809
commit ba72823998
21 changed files with 583 additions and 4 deletions

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
...

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
...

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
...

View File

@@ -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
}

View File

@@ -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
}