1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[WebAssembly] Remove saturating fp-to-int target intrinsics

Use the target-independent @llvm.fptosi and @llvm.fptoui intrinsics instead.
This includes removing the instrinsics for i32x4.trunc_sat_zero_f64x2_{s,u},
which are now represented in IR as a saturating truncation to a v2i32 followed by
a concatenation with a zero vector.

Differential Revision: https://reviews.llvm.org/D100596
This commit is contained in:
Thomas Lively 2021-04-16 12:11:20 -07:00
parent 773674bb59
commit 135ccc6ee6
10 changed files with 188 additions and 695 deletions

View File

@ -264,12 +264,6 @@ def int_wasm_extadd_pairwise_unsigned :
[IntrNoMem, IntrSpeculatable]>;
// TODO: Remove these if possible if they are merged to the spec.
def int_wasm_trunc_sat_zero_signed :
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_trunc_sat_zero_unsigned :
Intrinsic<[llvm_v4i32_ty], [llvm_v2f64_ty],
[IntrNoMem, IntrSpeculatable]>;
def int_wasm_demote_zero :
Intrinsic<[llvm_v4f32_ty], [llvm_v2f64_ty],
[IntrNoMem, IntrSpeculatable]>;

View File

@ -1493,8 +1493,6 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
// WebAssembly float semantics are always known
case Intrinsic::wasm_trunc_signed:
case Intrinsic::wasm_trunc_unsigned:
case Intrinsic::wasm_trunc_saturate_signed:
case Intrinsic::wasm_trunc_saturate_unsigned:
return true;
// Floating point operations cannot be folded in strictfp functions in
@ -1896,17 +1894,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
APFloat U = Op->getValueAPF();
if (IntrinsicID == Intrinsic::wasm_trunc_signed ||
IntrinsicID == Intrinsic::wasm_trunc_unsigned ||
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned) {
bool Saturating = IntrinsicID == Intrinsic::wasm_trunc_saturate_signed ||
IntrinsicID == Intrinsic::wasm_trunc_saturate_unsigned;
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed ||
IntrinsicID == Intrinsic::wasm_trunc_saturate_signed;
IntrinsicID == Intrinsic::wasm_trunc_unsigned) {
bool Signed = IntrinsicID == Intrinsic::wasm_trunc_signed;
if (U.isNaN())
return Saturating ? ConstantInt::get(Ty, 0) : nullptr;
return nullptr;
unsigned Width = Ty->getIntegerBitWidth();
APSInt Int(Width, !Signed);
@ -1917,15 +1909,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
if (Status == APFloat::opOK || Status == APFloat::opInexact)
return ConstantInt::get(Ty, Int);
if (!Saturating)
return nullptr;
if (U.isNegative())
return Signed ? ConstantInt::get(Ty, APInt::getSignedMinValue(Width))
: ConstantInt::get(Ty, APInt::getMinValue(Width));
else
return Signed ? ConstantInt::get(Ty, APInt::getSignedMaxValue(Width))
: ConstantInt::get(Ty, APInt::getMaxValue(Width));
return nullptr;
}
if (IntrinsicID == Intrinsic::fptoui_sat ||

View File

@ -35,6 +35,8 @@ HANDLE_NODETYPE(EXTEND_HIGH_S)
HANDLE_NODETYPE(EXTEND_HIGH_U)
HANDLE_NODETYPE(CONVERT_LOW_S)
HANDLE_NODETYPE(CONVERT_LOW_U)
HANDLE_NODETYPE(TRUNC_SAT_ZERO_S)
HANDLE_NODETYPE(TRUNC_SAT_ZERO_U)
HANDLE_NODETYPE(THROW)
HANDLE_NODETYPE(CATCH)
HANDLE_NODETYPE(MEMORY_COPY)

View File

@ -121,6 +121,11 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setOperationAction(Op, T, Expand);
}
if (Subtarget->hasNontrappingFPToInt())
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
for (auto T : {MVT::i32, MVT::i64})
setOperationAction(Op, T, Custom);
// SIMD-specific configuration
if (Subtarget->hasSIMD128()) {
// Hoist bitcasts out of shuffles
@ -134,6 +139,9 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
setTargetDAGCombine(ISD::SINT_TO_FP);
setTargetDAGCombine(ISD::UINT_TO_FP);
// Combine concat of {s,u}int_to_fp_sat to i32x4.trunc_sat_f64x2_zero_{s,u}
setTargetDAGCombine(ISD::CONCAT_VECTORS);
// Support saturating add for i8x16 and i16x8
for (auto Op : {ISD::SADDSAT, ISD::UADDSAT})
for (auto T : {MVT::v16i8, MVT::v8i16})
@ -198,6 +206,10 @@ WebAssemblyTargetLowering::WebAssemblyTargetLowering(
{ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
for (auto T : {MVT::v2i64, MVT::v2f64})
setOperationAction(Op, T, Expand);
// But saturating fp_to_int converstions are
for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
setOperationAction(Op, MVT::v4i32, Custom);
}
// As a special case, these operators use the type to mean the type to
@ -1237,6 +1249,9 @@ SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
case ISD::SRA:
case ISD::SRL:
return LowerShift(Op, DAG);
case ISD::FP_TO_SINT_SAT:
case ISD::FP_TO_UINT_SAT:
return LowerFP_TO_INT_SAT(Op, DAG);
}
}
@ -1953,6 +1968,21 @@ SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
}
SDValue WebAssemblyTargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT ResT = Op.getValueType();
uint64_t Width = Op.getConstantOperandVal(1);
if ((ResT == MVT::i32 || ResT == MVT::i64) && (Width == 32 || Width == 64))
return Op;
if (ResT == MVT::v4i32 && Width == 32)
return Op;
return SDValue();
}
//===----------------------------------------------------------------------===//
// Custom DAG combine hooks
//===----------------------------------------------------------------------===//
@ -2041,6 +2071,8 @@ performVectorConvertLowCombine(SDNode *N,
if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
return SDValue();
auto Source = Extract.getOperand(0);
if (Source.getValueType() != MVT::v4i32)
return SDValue();
auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
if (IndexNode == nullptr)
return SDValue();
@ -2062,6 +2094,49 @@ performVectorConvertLowCombine(SDNode *N,
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
}
static SDValue
performVectorTruncSatLowCombine(SDNode *N,
TargetLowering::DAGCombinerInfo &DCI) {
auto &DAG = DCI.DAG;
assert(N->getOpcode() == ISD::CONCAT_VECTORS);
// Combine this:
//
// (concat_vectors (v2i32 (fp_to_{s,u}int_sat $x, 32)), (v2i32 (splat 0)))
//
// into (i32x4.trunc_sat_f64x2_zero_{s,u} $x).
EVT ResVT = N->getValueType(0);
if (ResVT != MVT::v4i32)
return SDValue();
auto FPToInt = N->getOperand(0);
auto FPToIntOp = FPToInt.getOpcode();
if (FPToIntOp != ISD::FP_TO_SINT_SAT && FPToIntOp != ISD::FP_TO_UINT_SAT)
return SDValue();
if (FPToInt.getConstantOperandVal(1) != 32)
return SDValue();
auto Source = FPToInt.getOperand(0);
if (Source.getValueType() != MVT::v2f64)
return SDValue();
auto *Splat = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
APInt SplatValue, SplatUndef;
unsigned SplatBitSize;
bool HasAnyUndefs;
if (!Splat || !Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
HasAnyUndefs))
return SDValue();
if (SplatValue != 0)
return SDValue();
unsigned Op = FPToIntOp == ISD::FP_TO_SINT_SAT
? WebAssemblyISD::TRUNC_SAT_ZERO_S
: WebAssemblyISD::TRUNC_SAT_ZERO_U;
return DAG.getNode(Op, SDLoc(N), ResVT, Source);
}
SDValue
WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
DAGCombinerInfo &DCI) const {
@ -2076,5 +2151,7 @@ WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP:
return performVectorConvertLowCombine(N, DCI);
case ISD::CONCAT_VECTORS:
return performVectorTruncSatLowCombine(N, DCI);
}
}

View File

@ -119,6 +119,7 @@ private:
SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerAccessVectorElement(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFP_TO_INT_SAT(SDValue Op, SelectionDAG &DAG) const;
// Custom DAG combine hooks
SDValue

View File

@ -96,23 +96,15 @@ defm I64_TRUNC_U_SAT_F64 : I<(outs I64:$dst), (ins F64:$src), (outs), (ins),
"i64.trunc_sat_f64_u", 0xfc07>,
Requires<[HasNontrappingFPToInt]>;
// Lower llvm.wasm.trunc.saturate.* to saturating instructions
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
(I32_TRUNC_S_SAT_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
(I32_TRUNC_U_SAT_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
(I32_TRUNC_S_SAT_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
(I32_TRUNC_U_SAT_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_saturate_signed F32:$src),
(I64_TRUNC_S_SAT_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_saturate_unsigned F32:$src),
(I64_TRUNC_U_SAT_F32 F32:$src)>;
def : Pat<(int_wasm_trunc_saturate_signed F64:$src),
(I64_TRUNC_S_SAT_F64 F64:$src)>;
def : Pat<(int_wasm_trunc_saturate_unsigned F64:$src),
(I64_TRUNC_U_SAT_F64 F64:$src)>;
// Support the explicitly saturating operations as well.
def : Pat<(fp_to_sint_sat F32:$src, (i32 32)), (I32_TRUNC_S_SAT_F32 F32:$src)>;
def : Pat<(fp_to_uint_sat F32:$src, (i32 32)), (I32_TRUNC_U_SAT_F32 F32:$src)>;
def : Pat<(fp_to_sint_sat F64:$src, (i32 32)), (I32_TRUNC_S_SAT_F64 F64:$src)>;
def : Pat<(fp_to_uint_sat F64:$src, (i32 32)), (I32_TRUNC_U_SAT_F64 F64:$src)>;
def : Pat<(fp_to_sint_sat F32:$src, (i32 64)), (I64_TRUNC_S_SAT_F32 F32:$src)>;
def : Pat<(fp_to_uint_sat F32:$src, (i32 64)), (I64_TRUNC_U_SAT_F32 F32:$src)>;
def : Pat<(fp_to_sint_sat F64:$src, (i32 64)), (I64_TRUNC_S_SAT_F64 F64:$src)>;
def : Pat<(fp_to_uint_sat F64:$src, (i32 64)), (I64_TRUNC_U_SAT_F64 F64:$src)>;
// Conversion from floating point to integer pseudo-instructions which don't
// trap on overflow or invalid.

View File

@ -1091,11 +1091,21 @@ multiclass SIMDConvert<Vec vec, Vec arg, SDPatternOperator op, string name,
defm "" : SIMDConvert<I32x4, F32x4, fp_to_sint, "trunc_sat_f32x4_s", 248>;
defm "" : SIMDConvert<I32x4, F32x4, fp_to_uint, "trunc_sat_f32x4_u", 249>;
// Lower llvm.wasm.trunc.sat.* to saturating instructions
def : Pat<(v4i32 (int_wasm_trunc_saturate_signed (v4f32 V128:$src))),
(fp_to_sint_I32x4 $src)>;
def : Pat<(v4i32 (int_wasm_trunc_saturate_unsigned (v4f32 V128:$src))),
(fp_to_uint_I32x4 $src)>;
// Support the saturating variety as well.
def trunc_s_sat32 : PatFrag<(ops node:$x), (fp_to_sint_sat $x, (i32 32))>;
def trunc_u_sat32 : PatFrag<(ops node:$x), (fp_to_uint_sat $x, (i32 32))>;
def : Pat<(v4i32 (trunc_s_sat32 (v4f32 V128:$src))), (fp_to_sint_I32x4 $src)>;
def : Pat<(v4i32 (trunc_u_sat32 (v4f32 V128:$src))), (fp_to_uint_I32x4 $src)>;
def trunc_sat_zero_t : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>;
def trunc_sat_zero_s :
SDNode<"WebAssemblyISD::TRUNC_SAT_ZERO_S", trunc_sat_zero_t>;
def trunc_sat_zero_u :
SDNode<"WebAssemblyISD::TRUNC_SAT_ZERO_U", trunc_sat_zero_t>;
defm "" : SIMDConvert<I32x4, F64x2, trunc_sat_zero_s, "trunc_sat_zero_f64x2_s",
0xfc>;
defm "" : SIMDConvert<I32x4, F64x2, trunc_sat_zero_u, "trunc_sat_zero_f64x2_u",
0xfd>;
// Integer to floating point: convert
def convert_low_t : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>;
@ -1248,10 +1258,6 @@ defm "" : SIMDConvert<F32x4, F64x2, int_wasm_demote_zero,
"demote_zero_f64x2", 0x5e>;
defm "" : SIMDConvert<F64x2, F32x4, int_wasm_promote_low,
"promote_low_f32x4", 0x5f>;
defm "" : SIMDConvert<I32x4, F64x2, int_wasm_trunc_sat_zero_signed,
"trunc_sat_zero_f64x2_s", 0xfc>;
defm "" : SIMDConvert<I32x4, F64x2, int_wasm_trunc_sat_zero_unsigned,
"trunc_sat_zero_f64x2_u", 0xfd>;
//===----------------------------------------------------------------------===//
// Saturating Rounding Q-Format Multiplication

View File

@ -45,9 +45,9 @@ define i32 @i32_trunc_s_f32(float %x) {
; CHECK-NEXT: .functype i32_trunc_sat_s_f32 (f32) -> (i32){{$}}
; CHECK-NEXT: i32.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
declare i32 @llvm.fptosi.sat.i32.f32(float)
define i32 @i32_trunc_sat_s_f32(float %x) {
%a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %x)
%a = call i32 @llvm.fptosi.sat.i32.f32(float %x)
ret i32 %a
}
@ -64,9 +64,9 @@ define i32 @i32_trunc_u_f32(float %x) {
; CHECK-NEXT: .functype i32_trunc_sat_u_f32 (f32) -> (i32){{$}}
; CHECK-NEXT: i32.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
declare i32 @llvm.fptoui.sat.i32.f32(float)
define i32 @i32_trunc_sat_u_f32(float %x) {
%a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %x)
%a = call i32 @llvm.fptoui.sat.i32.f32(float %x)
ret i32 %a
}
@ -83,9 +83,9 @@ define i32 @i32_trunc_s_f64(double %x) {
; CHECK-NEXT: .functype i32_trunc_sat_s_f64 (f64) -> (i32){{$}}
; CHECK-NEXT: i32.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
declare i32 @llvm.fptosi.sat.i32.f64(double)
define i32 @i32_trunc_sat_s_f64(double %x) {
%a = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %x)
%a = call i32 @llvm.fptosi.sat.i32.f64(double %x)
ret i32 %a
}
@ -102,9 +102,9 @@ define i32 @i32_trunc_u_f64(double %x) {
; CHECK-NEXT: .functype i32_trunc_sat_u_f64 (f64) -> (i32){{$}}
; CHECK-NEXT: i32.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
declare i32 @llvm.fptoui.sat.i32.f64(double)
define i32 @i32_trunc_sat_u_f64(double %x) {
%a = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %x)
%a = call i32 @llvm.fptoui.sat.i32.f64(double %x)
ret i32 %a
}
@ -121,9 +121,9 @@ define i64 @i64_trunc_s_f32(float %x) {
; CHECK-NEXT: .functype i64_trunc_sat_s_f32 (f32) -> (i64){{$}}
; CHECK-NEXT: i64.trunc_sat_f32_s $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
declare i64 @llvm.fptosi.sat.i64.f32(float)
define i64 @i64_trunc_sat_s_f32(float %x) {
%a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %x)
%a = call i64 @llvm.fptosi.sat.i64.f32(float %x)
ret i64 %a
}
@ -140,9 +140,9 @@ define i64 @i64_trunc_u_f32(float %x) {
; CHECK-NEXT: .functype i64_trunc_sat_u_f32 (f32) -> (i64){{$}}
; CHECK-NEXT: i64.trunc_sat_f32_u $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
declare i64 @llvm.fptoui.sat.i64.f32(float)
define i64 @i64_trunc_sat_u_f32(float %x) {
%a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %x)
%a = call i64 @llvm.fptoui.sat.i64.f32(float %x)
ret i64 %a
}
@ -159,9 +159,9 @@ define i64 @i64_trunc_s_f64(double %x) {
; CHECK-NEXT: .functype i64_trunc_sat_s_f64 (f64) -> (i64){{$}}
; CHECK-NEXT: i64.trunc_sat_f64_s $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
declare i64 @llvm.fptosi.sat.i64.f64(double)
define i64 @i64_trunc_sat_s_f64(double %x) {
%a = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %x)
%a = call i64 @llvm.fptosi.sat.i64.f64(double %x)
ret i64 %a
}
@ -178,9 +178,9 @@ define i64 @i64_trunc_u_f64(double %x) {
; CHECK-NEXT: .functype i64_trunc_sat_u_f64 (f64) -> (i64){{$}}
; CHECK-NEXT: i64.trunc_sat_f64_u $push[[NUM:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[NUM]]{{$}}
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
declare i64 @llvm.fptoui.sat.i64.f64(double)
define i64 @i64_trunc_sat_u_f64(double %x) {
%a = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %x)
%a = call i64 @llvm.fptoui.sat.i64.f64(double %x)
ret i64 %a
}
@ -274,7 +274,7 @@ define float @f32_demote_f64(double %x) {
ret float %a
}
; If the high its are unused, LLVM will optimize sext/zext into anyext, which
; If the high bits are unused, LLVM will optimize sext/zext into anyext, which
; we need to patterm-match back to a specific instruction.
; CHECK-LABEL: anyext:
@ -312,3 +312,46 @@ define i64 @bitcast_double_to_i64(double %a) {
%t = bitcast double %a to i64
ret i64 %t
}
; Check that saturating fptoint with unsupported target bit widths is lowered
; correctly.
; CHECK-LABEL: i16_trunc_sat_s_f32:
; CHECK-NEXT: .functype i16_trunc_sat_s_f32 (f32) -> (i32){{$}}
; CHECK: i32.select
; CHECK: return
declare i16 @llvm.fptosi.sat.i16.f32(float)
define i16 @i16_trunc_sat_s_f32(float %x) {
%a = call i16 @llvm.fptosi.sat.i16.f32(float %x)
ret i16 %a
}
; CHECK-LABEL: i16_trunc_sat_u_f32:
; CHECK-NEXT: .functype i16_trunc_sat_u_f32 (f32) -> (i32){{$}}
; CHECK: i32.select
; CHECK: return
declare i16 @llvm.fptoui.sat.i16.f32(float)
define i16 @i16_trunc_sat_u_f32(float %x) {
%a = call i16 @llvm.fptoui.sat.i16.f32(float %x)
ret i16 %a
}
; CHECK-LABEL: i16_trunc_sat_s_f64:
; CHECK-NEXT: .functype i16_trunc_sat_s_f64 (f64) -> (i32){{$}}
; CHECK: i32.select
; CHECK: return
declare i16 @llvm.fptosi.sat.i16.f64(double)
define i16 @i16_trunc_sat_s_f64(double %x) {
%a = call i16 @llvm.fptosi.sat.i16.f64(double %x)
ret i16 %a
}
; CHECK-LABEL: i16_trunc_sat_u_f64:
; CHECK-NEXT: .functype i16_trunc_sat_u_f64 (f64) -> (i32){{$}}
; CHECK: i32.select
; CHECK: return
declare i16 @llvm.fptoui.sat.i16.f64(double)
define i16 @i16_trunc_sat_u_f64(double %x) {
%a = call i16 @llvm.fptoui.sat.i16.f64(double %x)
ret i16 %a
}

View File

@ -513,9 +513,9 @@ define <4 x i32> @bitselect_v4i32(<4 x i32> %v1, <4 x i32> %v2, <4 x i32> %c) {
; CHECK-NEXT: .functype trunc_sat_s_v4i32 (v128) -> (v128){{$}}
; CHECK-NEXT: i32x4.trunc_sat_f32x4_s $push[[R:[0-9]+]]=, $0
; CHECK-NEXT: return $pop[[R]]
declare <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float>)
declare <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float>)
define <4 x i32> @trunc_sat_s_v4i32(<4 x float> %x) {
%a = call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %x)
%a = call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %x)
ret <4 x i32> %a
}
@ -524,30 +524,34 @@ define <4 x i32> @trunc_sat_s_v4i32(<4 x float> %x) {
; CHECK-NEXT: .functype trunc_sat_u_v4i32 (v128) -> (v128){{$}}
; CHECK-NEXT: i32x4.trunc_sat_f32x4_u $push[[R:[0-9]+]]=, $0
; CHECK-NEXT: return $pop[[R]]
declare <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float>)
declare <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float>)
define <4 x i32> @trunc_sat_u_v4i32(<4 x float> %x) {
%a = call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %x)
%a = call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %x)
ret <4 x i32> %a
}
; CHECK-LABEL: trunc_sat_zero_signed_v4i32:
; CHECK-NEXT: .functype trunc_sat_zero_signed_v4i32 (v128) -> (v128){{$}}
; CHECK-LABEL: trunc_sat_zero_s_v4i32:
; CHECK-NEXT: .functype trunc_sat_zero_s_v4i32 (v128) -> (v128){{$}}
; CHECK-NEXT: i32x4.trunc_sat_zero_f64x2_s $push[[R:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[R]]{{$}}
declare <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double>)
define <4 x i32> @trunc_sat_zero_signed_v4i32(<2 x double> %a) {
%v = call <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double> %a)
ret <4 x i32> %v
declare <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double>)
define <4 x i32> @trunc_sat_zero_s_v4i32(<2 x double> %x) {
%v = call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> %x)
%a = shufflevector <2 x i32> %v, <2 x i32> <i32 0, i32 0>,
<4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %a
}
; CHECK-LABEL: trunc_sat_zero_unsigned_v4i32:
; CHECK-NEXT: .functype trunc_sat_zero_unsigned_v4i32 (v128) -> (v128){{$}}
; CHECK-LABEL: trunc_sat_zero_u_v4i32:
; CHECK-NEXT: .functype trunc_sat_zero_u_v4i32 (v128) -> (v128){{$}}
; CHECK-NEXT: i32x4.trunc_sat_zero_f64x2_u $push[[R:[0-9]+]]=, $0{{$}}
; CHECK-NEXT: return $pop[[R]]{{$}}
declare <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double>)
define <4 x i32> @trunc_sat_zero_unsigned_v4i32(<2 x double> %a) {
%v = call <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double> %a)
ret <4 x i32> %v
declare <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double>)
define <4 x i32> @trunc_sat_zero_u_v4i32(<2 x double> %x) {
%v = call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> %x)
%a = shufflevector <2 x i32> %v, <2 x i32> <i32 0, i32 0>,
<4 x i32> <i32 0, i32 1, i32 2, i32 3>
ret <4 x i32> %a
}
; ==============================================================================

View File

@ -1,610 +0,0 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instsimplify -S | FileCheck %s
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-unknown"
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float)
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float)
declare i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double)
declare i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double)
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float)
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float)
declare i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double)
declare i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double)
define void @test_i32_trunc_sat_f32_s(i32* %p) {
; CHECK-LABEL: @test_i32_trunc_sat_f32_s(
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483520, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: ret void
;
%t0 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float +0.0)
store volatile i32 %t0, i32* %p
%t1 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -0.0)
store volatile i32 %t1, i32* %p
%t2 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x36a0000000000000); 0x1p-149
store volatile i32 %t2, i32* %p
%t3 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xb6a0000000000000); -0x1p-149
store volatile i32 %t3, i32* %p
%t4 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 1.0)
store volatile i32 %t4, i32* %p
%t5 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
store volatile i32 %t5, i32* %p
%t6 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 1.5)
store volatile i32 %t6, i32* %p
%t7 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -1.0)
store volatile i32 %t7, i32* %p
%t8 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xbff19999a0000000); -0x1.19999ap+0
store volatile i32 %t8, i32* %p
%t9 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -1.5)
store volatile i32 %t9, i32* %p
%t10 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xbffe666660000000); -1.9
store volatile i32 %t10, i32* %p
%t11 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2.0)
store volatile i32 %t11, i32* %p
%t12 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 2147483520.0)
store volatile i32 %t12, i32* %p
%t13 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2147483648.0)
store volatile i32 %t13, i32* %p
%t14 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 2147483648.0)
store volatile i32 %t14, i32* %p
%t15 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float -2147483904.0)
store volatile i32 %t15, i32* %p
%t16 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ff0000000000000); inf
store volatile i32 %t16, i32* %p
%t17 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfff0000000000000); -inf
store volatile i32 %t17, i32* %p
%t18 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ff8000000000000); nan
store volatile i32 %t18, i32* %p
%t19 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0x7ffa000000000000); nan:0x200000
store volatile i32 %t19, i32* %p
%t20 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfff8000000000000); -nan
store volatile i32 %t20, i32* %p
%t21 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float 0xfffa000000000000); -nan:0x200000
store volatile i32 %t21, i32* %p
ret void
}
define void @test_i32_trunc_sat_f32_u(i32* %p) {
; CHECK-LABEL: @test_i32_trunc_sat_f32_u(
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -256, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: ret void
;
%t0 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float +0.0)
store volatile i32 %t0, i32* %p
%t1 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float -0.0)
store volatile i32 %t1, i32* %p
%t2 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x36a0000000000000); 0x1p-149
store volatile i32 %t2, i32* %p
%t3 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xb6a0000000000000); -0x1p-149
store volatile i32 %t3, i32* %p
%t4 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 1.0)
store volatile i32 %t4, i32* %p
%t5 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
store volatile i32 %t5, i32* %p
%t6 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 1.5)
store volatile i32 %t6, i32* %p
%t7 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x3ffe666660000000); 1.9
store volatile i32 %t7, i32* %p
%t8 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 2.0)
store volatile i32 %t8, i32* %p
%t9 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 2147483648.0)
store volatile i32 %t9, i32* %p
%t10 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 4294967040.0)
store volatile i32 %t10, i32* %p
%t11 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
store volatile i32 %t11, i32* %p
%t12 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
store volatile i32 %t12, i32* %p
%t13 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 4294967296.0)
store volatile i32 %t13, i32* %p
%t14 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float -1.0)
store volatile i32 %t14, i32* %p
%t15 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ff0000000000000); inf
store volatile i32 %t15, i32* %p
%t16 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfff0000000000000); -inf
store volatile i32 %t16, i32* %p
%t17 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ff8000000000000); nan
store volatile i32 %t17, i32* %p
%t18 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0x7ffa000000000000); nan:0x200000
store volatile i32 %t18, i32* %p
%t19 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfff8000000000000); -nan
store volatile i32 %t19, i32* %p
%t20 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float 0xfffa000000000000); -nan:0x200000
store volatile i32 %t20, i32* %p
ret void
}
define void @test_i32_trunc_sat_f64_s(i32* %p) {
; CHECK-LABEL: @test_i32_trunc_sat_f64_s(
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2147483647, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: ret void
;
%t0 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double +0.0)
store volatile i32 %t0, i32* %p
%t1 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -0.0)
store volatile i32 %t1, i32* %p
%t2 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
store volatile i32 %t2, i32* %p
%t3 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
store volatile i32 %t3, i32* %p
%t4 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 1.0)
store volatile i32 %t4, i32* %p
%t5 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
store volatile i32 %t5, i32* %p
%t6 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 1.5)
store volatile i32 %t6, i32* %p
%t7 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -1.0)
store volatile i32 %t7, i32* %p
%t8 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
store volatile i32 %t8, i32* %p
%t9 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -1.5)
store volatile i32 %t9, i32* %p
%t10 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xbffe666666666666); -1.9
store volatile i32 %t10, i32* %p
%t11 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2.0)
store volatile i32 %t11, i32* %p
%t12 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 2147483647.0)
store volatile i32 %t12, i32* %p
%t13 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2147483648.0)
store volatile i32 %t13, i32* %p
%t14 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 2147483648.0)
store volatile i32 %t14, i32* %p
%t15 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double -2147483649.0)
store volatile i32 %t15, i32* %p
%t16 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff0000000000000); inf
store volatile i32 %t16, i32* %p
%t17 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xfff0000000000000); -inf
store volatile i32 %t17, i32* %p
%t18 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff8000000000000); nan
store volatile i32 %t18, i32* %p
%t19 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
store volatile i32 %t19, i32* %p
%t20 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0xfff8000000000000); -nan
store volatile i32 %t20, i32* %p
%t21 = call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double 0x7ff4000000000000); -nan:0x4000000000000
store volatile i32 %t21, i32* %p
ret void
}
define void @test_i32_trunc_sat_f64_u(i32* %p) {
; CHECK-LABEL: @test_i32_trunc_sat_f64_u(
; CHECK-NEXT: store volatile i32 0, i32* [[P:%.*]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 2, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -2147483648, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 100000000, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 -1, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: store volatile i32 0, i32* [[P]], align 4
; CHECK-NEXT: ret void
;
%t0 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double +0.0)
store volatile i32 %t0, i32* %p
%t1 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double -0.0)
store volatile i32 %t1, i32* %p
%t2 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
store volatile i32 %t2, i32* %p
%t3 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
store volatile i32 %t3, i32* %p
%t4 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1.0)
store volatile i32 %t4, i32* %p
%t5 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
store volatile i32 %t5, i32* %p
%t6 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1.5)
store volatile i32 %t6, i32* %p
%t7 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x3ffe666666666666); 1.9
store volatile i32 %t7, i32* %p
%t8 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 2.0)
store volatile i32 %t8, i32* %p
%t9 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 2147483648.0)
store volatile i32 %t9, i32* %p
%t10 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 4294967295.0)
store volatile i32 %t10, i32* %p
%t11 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
store volatile i32 %t11, i32* %p
%t12 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
store volatile i32 %t12, i32* %p
%t13 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 100000000.0); 1e8
store volatile i32 %t13, i32* %p
%t14 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 4294967296.0)
store volatile i32 %t14, i32* %p
%t15 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double -1.0)
store volatile i32 %t15, i32* %p
%t16 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 10000000000000000.0); 1e16
store volatile i32 %t16, i32* %p
%t17 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 1000000000000000000000000000000.0); 1e30
store volatile i32 %t17, i32* %p
%t18 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 9223372036854775808.0)
store volatile i32 %t18, i32* %p
%t19 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff0000000000000); inf
store volatile i32 %t19, i32* %p
%t20 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff0000000000000); -inf
store volatile i32 %t20, i32* %p
%t21 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff8000000000000); nan
store volatile i32 %t21, i32* %p
%t22 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
store volatile i32 %t22, i32* %p
%t23 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff8000000000000); -nan
store volatile i32 %t23, i32* %p
%t24 = call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double 0xfff4000000000000); -nan:0x4000000000000
store volatile i32 %t24, i32* %p
ret void
}
define void @test_i64_trunc_sat_f32_s(i64* %p) {
; CHECK-LABEL: @test_i64_trunc_sat_f32_s(
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -2, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223371487098961920, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: ret void
;
%t0 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float +0.0)
store volatile i64 %t0, i64* %p
%t1 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -0.0)
store volatile i64 %t1, i64* %p
%t2 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x36a0000000000000); 0x1p-149
store volatile i64 %t2, i64* %p
%t3 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xb6a0000000000000); -0x1p-149
store volatile i64 %t3, i64* %p
%t4 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 1.0)
store volatile i64 %t4, i64* %p
%t5 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
store volatile i64 %t5, i64* %p
%t6 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 1.5)
store volatile i64 %t6, i64* %p
%t7 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -1.0)
store volatile i64 %t7, i64* %p
%t8 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xbff19999a0000000); -0x1.19999ap+0
store volatile i64 %t8, i64* %p
%t9 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -1.5)
store volatile i64 %t9, i64* %p
%t10 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xbffe666660000000); -1.9
store volatile i64 %t10, i64* %p
%t11 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -2.0)
store volatile i64 %t11, i64* %p
%t12 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 4294967296.0)
store volatile i64 %t12, i64* %p
%t13 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -4294967296.0)
store volatile i64 %t13, i64* %p
%t14 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 9223371487098961920.0)
store volatile i64 %t14, i64* %p
%t15 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -9223372036854775808.0)
store volatile i64 %t15, i64* %p
%t16 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 9223372036854775808.0)
store volatile i64 %t16, i64* %p
%t17 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float -9223373136366403584.0)
store volatile i64 %t17, i64* %p
%t18 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ff0000000000000); inf
store volatile i64 %t18, i64* %p
%t19 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfff0000000000000); -inf
store volatile i64 %t19, i64* %p
%t20 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ff8000000000000); nan
store volatile i64 %t20, i64* %p
%t21 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0x7ffa000000000000); nan:0x200000
store volatile i64 %t21, i64* %p
%t22 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfff8000000000000); -nan
store volatile i64 %t22, i64* %p
%t23 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float 0xfffa000000000000); -nan:0x200000
store volatile i64 %t23, i64* %p
ret void
}
define void @test_i64_trunc_sat_f32_u(i64* %p) {
; CHECK-LABEL: @test_i64_trunc_sat_f32_u(
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1099511627776, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: ret void
;
%t0 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float +0.0)
store volatile i64 %t0, i64* %p
%t1 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float -0.0)
store volatile i64 %t1, i64* %p
%t2 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x36a0000000000000); 0x1p-149
store volatile i64 %t2, i64* %p
%t3 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xb6a0000000000000); -0x1p-149
store volatile i64 %t3, i64* %p
%t4 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 1.0)
store volatile i64 %t4, i64* %p
%t5 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
store volatile i64 %t5, i64* %p
%t6 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 1.5)
store volatile i64 %t6, i64* %p
%t7 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 4294967296.0)
store volatile i64 %t7, i64* %p
%t8 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 18446742974197923840.0)
store volatile i64 %t8, i64* %p
%t9 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
store volatile i64 %t9, i64* %p
%t10 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
store volatile i64 %t10, i64* %p
%t11 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 18446744073709551616.0)
store volatile i64 %t11, i64* %p
%t12 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float -1.0)
store volatile i64 %t12, i64* %p
%t13 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ff0000000000000); inf
store volatile i64 %t13, i64* %p
%t14 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfff0000000000000); -inf
store volatile i64 %t14, i64* %p
%t15 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ff8000000000000); nan
store volatile i64 %t15, i64* %p
%t16 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0x7ffa000000000000); nan:0x200000
store volatile i64 %t16, i64* %p
%t17 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfff8000000000000); -nan
store volatile i64 %t17, i64* %p
%t18 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float 0xfffa000000000000); -nan:0x200000
store volatile i64 %t18, i64* %p
ret void
}
define void @test_i64_trunc_sat_f64_s(i64* %p) {
; CHECK-LABEL: @test_i64_trunc_sat_f64_s(
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -2, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223372036854774784, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 9223372036854775807, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: ret void
;
%t0 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double +0.0)
store volatile i64 %t0, i64* %p
%t1 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -0.0)
store volatile i64 %t1, i64* %p
%t2 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
store volatile i64 %t2, i64* %p
%t3 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
store volatile i64 %t3, i64* %p
%t4 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 1.0)
store volatile i64 %t4, i64* %p
%t5 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
store volatile i64 %t5, i64* %p
%t6 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 1.5)
store volatile i64 %t6, i64* %p
%t7 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -1.0)
store volatile i64 %t7, i64* %p
%t8 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
store volatile i64 %t8, i64* %p
%t9 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -1.5)
store volatile i64 %t9, i64* %p
%t10 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xbffe666666666666); -1.9
store volatile i64 %t10, i64* %p
%t11 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -2.0)
store volatile i64 %t11, i64* %p
%t12 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 4294967296.0)
store volatile i64 %t12, i64* %p
%t13 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -4294967296.0)
store volatile i64 %t13, i64* %p
%t14 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 9223372036854774784.0)
store volatile i64 %t14, i64* %p
%t15 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -9223372036854775808.0)
store volatile i64 %t15, i64* %p
%t16 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 9223372036854775808.0)
store volatile i64 %t16, i64* %p
%t17 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double -9223372036854777856.0)
store volatile i64 %t17, i64* %p
%t18 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff0000000000000); inf
store volatile i64 %t18, i64* %p
%t19 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xfff0000000000000); -inf
store volatile i64 %t19, i64* %p
%t20 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff8000000000000); nan
store volatile i64 %t20, i64* %p
%t21 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
store volatile i64 %t21, i64* %p
%t22 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0xfff8000000000000); -nan
store volatile i64 %t22, i64* %p
%t23 = call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double 0x7ff4000000000000); -nan:0x4000000000000
store volatile i64 %t23, i64* %p
ret void
}
define void @test_i64_trunc_sat_f64_u(i64* %p) {
; CHECK-LABEL: @test_i64_trunc_sat_f64_u(
; CHECK-NEXT: store volatile i64 0, i64* [[P:%.*]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 4294967295, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 4294967296, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -2048, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 100000000, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 10000000000000000, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -9223372036854775808, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 -1, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: store volatile i64 0, i64* [[P]], align 8
; CHECK-NEXT: ret void
;
%t0 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double +0.0)
store volatile i64 %t0, i64* %p
%t1 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double -0.0)
store volatile i64 %t1, i64* %p
%t2 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
store volatile i64 %t2, i64* %p
%t3 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
store volatile i64 %t3, i64* %p
%t4 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 1.0)
store volatile i64 %t4, i64* %p
%t5 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
store volatile i64 %t5, i64* %p
%t6 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 1.5)
store volatile i64 %t6, i64* %p
%t7 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 4294967295.0)
store volatile i64 %t7, i64* %p
%t8 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 4294967296.0)
store volatile i64 %t8, i64* %p
%t9 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 18446744073709549568.0)
store volatile i64 %t9, i64* %p
%t10 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
store volatile i64 %t10, i64* %p
%t11 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
store volatile i64 %t11, i64* %p
%t12 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 100000000.0); 1e8
store volatile i64 %t12, i64* %p
%t13 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 10000000000000000.0); 1e16
store volatile i64 %t13, i64* %p
%t14 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 9223372036854775808.0);
store volatile i64 %t14, i64* %p
%t15 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 18446744073709551616.0)
store volatile i64 %t15, i64* %p
%t16 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double -1.0)
store volatile i64 %t16, i64* %p
%t17 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff0000000000000); inf
store volatile i64 %t17, i64* %p
%t18 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff0000000000000); -inf
store volatile i64 %t18, i64* %p
%t19 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff8000000000000); nan
store volatile i64 %t19, i64* %p
%t20 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
store volatile i64 %t20, i64* %p
%t21 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff8000000000000); -nan
store volatile i64 %t21, i64* %p
%t22 = call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double 0xfff4000000000000); -nan:0x4000000000000
store volatile i64 %t22, i64* %p
ret void
}