diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -17073,8 +17073,8 @@ case WebAssembly::BI__builtin_wasm_trunc_saturate_s_i32x4_f32x4: { Value *Src = EmitScalarExpr(E->getArg(0)); llvm::Type *ResT = ConvertType(E->getType()); - Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_signed, - {ResT, Src->getType()}); + Function *Callee = + CGM.getIntrinsic(Intrinsic::fptosi_sat, {ResT, Src->getType()}); return Builder.CreateCall(Callee, {Src}); } case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32_f32: @@ -17084,8 +17084,8 @@ case WebAssembly::BI__builtin_wasm_trunc_saturate_u_i32x4_f32x4: { Value *Src = EmitScalarExpr(E->getArg(0)); llvm::Type *ResT = ConvertType(E->getType()); - Function *Callee = CGM.getIntrinsic(Intrinsic::wasm_trunc_saturate_unsigned, - {ResT, Src->getType()}); + Function *Callee = + CGM.getIntrinsic(Intrinsic::fptoui_sat, {ResT, Src->getType()}); return Builder.CreateCall(Callee, {Src}); } case WebAssembly::BI__builtin_wasm_min_f32: @@ -17481,16 +17481,24 @@ unsigned IntNo; switch (BuiltinID) { case WebAssembly::BI__builtin_wasm_trunc_sat_zero_s_f64x2_i32x4: - IntNo = Intrinsic::wasm_trunc_sat_zero_signed; + IntNo = Intrinsic::fptosi_sat; break; case WebAssembly::BI__builtin_wasm_trunc_sat_zero_u_f64x2_i32x4: - IntNo = Intrinsic::wasm_trunc_sat_zero_unsigned; + IntNo = Intrinsic::fptoui_sat; break; default: llvm_unreachable("unexpected builtin ID"); } - Function *Callee = CGM.getIntrinsic(IntNo); - return Builder.CreateCall(Callee, Vec); + llvm::Type *SrcT = Vec->getType(); + llvm::Type *TruncT = + SrcT->getWithNewType(llvm::IntegerType::get(getLLVMContext(), 32)); + Function *Callee = CGM.getIntrinsic(IntNo, {TruncT, SrcT}); + Value *Trunc = Builder.CreateCall(Callee, Vec); + Value *Splat = Builder.CreateVectorSplat(2, Builder.getInt32(0)); + Value *ConcatMask = + llvm::ConstantVector::get({Builder.getInt32(0), Builder.getInt32(1), + Builder.getInt32(2), Builder.getInt32(3)}); + return Builder.CreateShuffleVector(Trunc, Splat, ConcatMask); } case WebAssembly::BI__builtin_wasm_demote_zero_f64x2_f32x4: { Value *Vec = EmitScalarExpr(E->getArg(0)); diff --git a/clang/test/CodeGen/builtins-wasm.c b/clang/test/CodeGen/builtins-wasm.c --- a/clang/test/CodeGen/builtins-wasm.c +++ b/clang/test/CodeGen/builtins-wasm.c @@ -123,49 +123,49 @@ int trunc_saturate_s_i32_f32(float f) { return __builtin_wasm_trunc_saturate_s_i32_f32(f); - // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f32(float %f) + // WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f32(float %f) // WEBASSEMBLY-NEXT: ret } int trunc_saturate_u_i32_f32(float f) { return __builtin_wasm_trunc_saturate_u_i32_f32(f); - // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f32(float %f) + // WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f32(float %f) // WEBASSEMBLY-NEXT: ret } int trunc_saturate_s_i32_f64(double f) { return __builtin_wasm_trunc_saturate_s_i32_f64(f); - // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.signed.i32.f64(double %f) + // WEBASSEMBLY: call i32 @llvm.fptosi.sat.i32.f64(double %f) // WEBASSEMBLY-NEXT: ret } int trunc_saturate_u_i32_f64(double f) { return __builtin_wasm_trunc_saturate_u_i32_f64(f); - // WEBASSEMBLY: call i32 @llvm.wasm.trunc.saturate.unsigned.i32.f64(double %f) + // WEBASSEMBLY: call i32 @llvm.fptoui.sat.i32.f64(double %f) // WEBASSEMBLY-NEXT: ret } long long trunc_saturate_s_i64_f32(float f) { return __builtin_wasm_trunc_saturate_s_i64_f32(f); - // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f32(float %f) + // WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f32(float %f) // WEBASSEMBLY-NEXT: ret } long long trunc_saturate_u_i64_f32(float f) { return __builtin_wasm_trunc_saturate_u_i64_f32(f); - // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f32(float %f) + // WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f32(float %f) // WEBASSEMBLY-NEXT: ret } long long trunc_saturate_s_i64_f64(double f) { return __builtin_wasm_trunc_saturate_s_i64_f64(f); - // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.signed.i64.f64(double %f) + // WEBASSEMBLY: call i64 @llvm.fptosi.sat.i64.f64(double %f) // WEBASSEMBLY-NEXT: ret } long long trunc_saturate_u_i64_f64(double f) { return __builtin_wasm_trunc_saturate_u_i64_f64(f); - // WEBASSEMBLY: call i64 @llvm.wasm.trunc.saturate.unsigned.i64.f64(double %f) + // WEBASSEMBLY: call i64 @llvm.fptoui.sat.i64.f64(double %f) // WEBASSEMBLY-NEXT: ret } @@ -852,13 +852,13 @@ i32x4 trunc_saturate_s_i32x4_f32x4(f32x4 f) { return __builtin_wasm_trunc_saturate_s_i32x4_f32x4(f); - // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.signed.v4i32.v4f32(<4 x float> %f) + // WEBASSEMBLY: call <4 x i32> @llvm.fptosi.sat.v4i32.v4f32(<4 x float> %f) // WEBASSEMBLY-NEXT: ret } i32x4 trunc_saturate_u_i32x4_f32x4(f32x4 f) { return __builtin_wasm_trunc_saturate_u_i32x4_f32x4(f); - // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.saturate.unsigned.v4i32.v4f32(<4 x float> %f) + // WEBASSEMBLY: call <4 x i32> @llvm.fptoui.sat.v4i32.v4f32(<4 x float> %f) // WEBASSEMBLY-NEXT: ret } @@ -892,14 +892,16 @@ i32x4 trunc_sat_zero_s_f64x2_i32x4(f64x2 x) { return __builtin_wasm_trunc_sat_zero_s_f64x2_i32x4(x); - // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.signed(<2 x double> %x) - // WEBASSEMBLY: ret + // WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptosi.sat.v2i32.v2f64(<2 x double> %x) + // WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> + // WEBASSEMBLY: ret <4 x i32> %1 } u32x4 trunc_sat_zero_u_f64x2_i32x4(f64x2 x) { return __builtin_wasm_trunc_sat_zero_u_f64x2_i32x4(x); - // WEBASSEMBLY: call <4 x i32> @llvm.wasm.trunc.sat.zero.unsigned(<2 x double> %x) - // WEBASSEMBLY: ret + // WEBASSEMBLY: %0 = tail call <2 x i32> @llvm.fptoui.sat.v2i32.v2f64(<2 x double> %x) + // WEBASSEMBLY: %1 = shufflevector <2 x i32> %0, <2 x i32> zeroinitializer, <4 x i32> + // WEBASSEMBLY: ret <4 x i32> %1 } f32x4 wasm_demote_zero_f64x2_f32x4(f64x2 x) { diff --git a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td --- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td +++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td @@ -264,12 +264,6 @@ [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]>; diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1493,8 +1493,6 @@ // 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 @@ 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 @@ 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 || diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def --- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -35,6 +35,8 @@ 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) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h @@ -119,6 +119,7 @@ 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 diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -121,6 +121,11 @@ 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 @@ 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 @@ {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 @@ 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 @@ 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 @@ if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR) return SDValue(); auto Source = Extract.getOperand(0); + if (Source.getValueType() != MVT::v4i32) + return SDValue(); auto *IndexNode = dyn_cast(Extract.getOperand(1)); if (IndexNode == nullptr) return SDValue(); @@ -2062,6 +2094,49 @@ 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(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 @@ case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: return performVectorConvertLowCombine(N, DCI); + case ISD::CONCAT_VECTORS: + return performVectorTruncSatLowCombine(N, DCI); } } diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td @@ -96,23 +96,15 @@ "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. diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -1091,11 +1091,21 @@ defm "" : SIMDConvert; defm "" : SIMDConvert; -// 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; +defm "" : SIMDConvert; // Integer to floating point: convert def convert_low_t : SDTypeProfile<1, 1, [SDTCisVec<0>, SDTCisVec<1>]>; @@ -1248,10 +1258,6 @@ "demote_zero_f64x2", 0x5e>; defm "" : SIMDConvert; -defm "" : SIMDConvert; -defm "" : SIMDConvert; //===----------------------------------------------------------------------===// // Saturating Rounding Q-Format Multiplication diff --git a/llvm/test/CodeGen/WebAssembly/conv.ll b/llvm/test/CodeGen/WebAssembly/conv.ll --- a/llvm/test/CodeGen/WebAssembly/conv.ll +++ b/llvm/test/CodeGen/WebAssembly/conv.ll @@ -45,9 +45,9 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ ; 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 @@ 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 @@ %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 +} diff --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll --- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll @@ -513,9 +513,9 @@ ; 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 @@ ; 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> , + <4 x i32> + 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> , + <4 x i32> + ret <4 x i32> %a } ; ============================================================================== diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/trunc_saturate.ll b/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/trunc_saturate.ll deleted file mode 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/trunc_saturate.ll +++ /dev/null @@ -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 -}