[llvm] 5c72975 - [WebAssembly] Remove saturating fp-to-int target intrinsics

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 16 12:11:30 PDT 2021


Author: Thomas Lively
Date: 2021-04-16T12:11:20-07:00
New Revision: 5c729750a6d75df4eeb3eaad72e0b4e93ea27c0e

URL: https://github.com/llvm/llvm-project/commit/5c729750a6d75df4eeb3eaad72e0b4e93ea27c0e
DIFF: https://github.com/llvm/llvm-project/commit/5c729750a6d75df4eeb3eaad72e0b4e93ea27c0e.diff

LOG: [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

Added: 
    

Modified: 
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/test/CodeGen/builtins-wasm.c
    llvm/include/llvm/IR/IntrinsicsWebAssembly.td
    llvm/lib/Analysis/ConstantFolding.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyISD.def
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
    llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
    llvm/test/CodeGen/WebAssembly/conv.ll
    llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll

Removed: 
    llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/trunc_saturate.ll


################################################################################
diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 860492a281fe0..7e19532322536 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -17073,8 +17073,8 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
   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 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
   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 @@ Value *CodeGenFunction::EmitWebAssemblyBuiltinExpr(unsigned BuiltinID,
     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
index 1a986f03dc498..d20b6a739f94a 100644
--- a/clang/test/CodeGen/builtins-wasm.c
+++ b/clang/test/CodeGen/builtins-wasm.c
@@ -123,49 +123,49 @@ long long trunc_u_i64_f64(double f) {
 
 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 @@ f64x2 sqrt_f64x2(f64x2 x) {
 
 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 @@ u16x8 narrow_u_i16x8_i32x4(u32x4 low, u32x4 high) {
 
 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> <i32 0, i32 1, i32 2, i32 3>
+  // 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> <i32 0, i32 1, i32 2, i32 3>
+  // 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
index 4e2d557f1f083..abeb4c0a19f34 100644
--- a/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
+++ b/llvm/include/llvm/IR/IntrinsicsWebAssembly.td
@@ -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]>;

diff  --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 7f3b909accb80..c1975d0e22e6d 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -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 ||

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
index c73ce43057f85..33fd2ae11154f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def
@@ -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)

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
index acf4f01947585..f4e48883db5d6 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
@@ -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);
   }
 }

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
index f777345c90f6f..2f7195b17c42c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.h
@@ -119,6 +119,7 @@ class WebAssemblyTargetLowering final : public TargetLowering {
   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/WebAssemblyInstrConv.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
index f3d9c5d5032cb..68ef43f6af36d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrConv.td
@@ -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.

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index a1150c0f94500..850351f01c01d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -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

diff  --git a/llvm/test/CodeGen/WebAssembly/conv.ll b/llvm/test/CodeGen/WebAssembly/conv.ll
index 68f941546ce10..5699c7b9adc5b 100644
--- a/llvm/test/CodeGen/WebAssembly/conv.ll
+++ b/llvm/test/CodeGen/WebAssembly/conv.ll
@@ -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
+}

diff  --git a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
index 6e8e5a2fed71b..0fc008d3ef9a3 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-intrinsics.ll
@@ -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
 }
 
 ; ==============================================================================

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
index a7cd6066785aa..0000000000000
--- 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
-}


        


More information about the llvm-commits mailing list