[llvm] 514445e - [WebAssembly][ConstantFolding] Fold fp-to-int truncation intrinsics

Thomas Lively via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 10 12:40:15 PDT 2020


Author: Thomas Lively
Date: 2020-08-10T12:40:05-07:00
New Revision: 514445e0353e82fa0bd59eeea437499500e232cd

URL: https://github.com/llvm/llvm-project/commit/514445e0353e82fa0bd59eeea437499500e232cd
DIFF: https://github.com/llvm/llvm-project/commit/514445e0353e82fa0bd59eeea437499500e232cd.diff

LOG: [WebAssembly][ConstantFolding] Fold fp-to-int truncation intrinsics

Constant fold both the trapping and saturating versions of the
WebAssembly truncation intrinsics. The tests are adapted from the
WebAssembly spec tests for the corresponding instructions.

Requested in PR46982.

Differential Revision: https://reviews.llvm.org/D85392

Added: 
    llvm/test/Analysis/ConstantFolding/WebAssembly/trunc.ll
    llvm/test/Analysis/ConstantFolding/WebAssembly/trunc_saturate.ll

Modified: 
    llvm/lib/Analysis/ConstantFolding.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index 28a30090a009..aaab600bfc6b 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
@@ -42,6 +43,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/IntrinsicsAMDGPU.h"
 #include "llvm/IR/IntrinsicsARM.h"
+#include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/IntrinsicsX86.h"
 #include "llvm/IR/Operator.h"
 #include "llvm/IR/Type.h"
@@ -1469,6 +1471,11 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) {
   case Intrinsic::arm_mve_vctp16:
   case Intrinsic::arm_mve_vctp32:
   case Intrinsic::arm_mve_vctp64:
+  // 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
@@ -1861,11 +1868,45 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
       return ConstantInt::get(Ty->getContext(), Val.bitcastToAPInt());
     }
 
+    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;
+
+      if (U.isNaN())
+        return Saturating ? ConstantInt::get(Ty, 0) : nullptr;
+
+      unsigned Width = Ty->getIntegerBitWidth();
+      APSInt Int(Width, !Signed);
+      bool IsExact = false;
+      APFloat::opStatus Status =
+          U.convertToInteger(Int, APFloat::rmTowardZero, &IsExact);
+
+      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));
+    }
+
     if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
       return nullptr;
 
     // Use internal versions of these intrinsics.
-    APFloat U = Op->getValueAPF();
 
     if (IntrinsicID == Intrinsic::nearbyint || IntrinsicID == Intrinsic::rint) {
       U.roundToIntegral(APFloat::rmNearestTiesToEven);

diff  --git a/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc.ll b/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc.ll
new file mode 100644
index 000000000000..adaab5e64811
--- /dev/null
+++ b/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc.ll
@@ -0,0 +1,686 @@
+; 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.signed.i32.f32(float)
+declare i32 @llvm.wasm.trunc.unsigned.i32.f32(float)
+declare i32 @llvm.wasm.trunc.signed.i32.f64(double)
+declare i32 @llvm.wasm.trunc.unsigned.i32.f64(double)
+declare i64 @llvm.wasm.trunc.signed.i64.f32(float)
+declare i64 @llvm.wasm.trunc.unsigned.i64.f32(float)
+declare i64 @llvm.wasm.trunc.signed.i64.f64(double)
+declare i64 @llvm.wasm.trunc.unsigned.i64.f64(double)
+
+define void @test_i32_trunc_f32_s(i32* %p) {
+; CHECK-LABEL: @test_i32_trunc_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:    [[T14:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x41E0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T14]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T15:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xC1E0000020000000)
+; CHECK-NEXT:    store volatile i32 [[T15]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T16:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T16]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T17:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T17]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T18:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T18]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T19:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7FFA000000000000)
+; CHECK-NEXT:    store volatile i32 [[T19]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T20:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T20]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T21:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xFFFA000000000000)
+; CHECK-NEXT:    store volatile i32 [[T21]], i32* [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i32 @llvm.wasm.trunc.signed.i32.f32(float +0.0)
+  store volatile i32 %t0, i32* %p
+  %t1 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -0.0)
+  store volatile i32 %t1, i32* %p
+  %t2 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x36a0000000000000); 0x1p-149
+  store volatile i32 %t2, i32* %p
+  %t3 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xb6a0000000000000); -0x1p-149
+  store volatile i32 %t3, i32* %p
+  %t4 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 1.0)
+  store volatile i32 %t4, i32* %p
+  %t5 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
+  store volatile i32 %t5, i32* %p
+  %t6 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 1.5)
+  store volatile i32 %t6, i32* %p
+  %t7 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -1.0)
+  store volatile i32 %t7, i32* %p
+  %t8 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xbff19999a0000000); -0x1.19999ap+0
+  store volatile i32 %t8, i32* %p
+  %t9 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -1.5)
+  store volatile i32 %t9, i32* %p
+  %t10 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xbffe666660000000); -1.9
+  store volatile i32 %t10, i32* %p
+  %t11 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -2.0)
+  store volatile i32 %t11, i32* %p
+  %t12 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 2147483520.0)
+  store volatile i32 %t12, i32* %p
+  %t13 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -2147483648.0)
+  store volatile i32 %t13, i32* %p
+  %t14 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 2147483648.0)
+  store volatile i32 %t14, i32* %p
+  %t15 = call i32 @llvm.wasm.trunc.signed.i32.f32(float -2147483904.0)
+  store volatile i32 %t15, i32* %p
+  %t16 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7ff0000000000000); inf
+  store volatile i32 %t16, i32* %p
+  %t17 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xfff0000000000000); -inf
+  store volatile i32 %t17, i32* %p
+  %t18 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7ff8000000000000); nan
+  store volatile i32 %t18, i32* %p
+  %t19 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0x7ffa000000000000); nan:0x200000
+  store volatile i32 %t19, i32* %p
+  %t20 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xfff8000000000000); -nan
+  store volatile i32 %t20, i32* %p
+  %t21 = call i32 @llvm.wasm.trunc.signed.i32.f32(float 0xfffa000000000000); -nan:0x200000
+  store volatile i32 %t21, i32* %p
+  ret void
+}
+
+define void @test_i32_trunc_f32_u(i32* %p) {
+; CHECK-LABEL: @test_i32_trunc_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:    [[T13:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x41F0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T13]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T14:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float -1.000000e+00)
+; CHECK-NEXT:    store volatile i32 [[T14]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T15:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T15]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T16:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T16]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T17:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T17]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T18:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7FFA000000000000)
+; CHECK-NEXT:    store volatile i32 [[T18]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T19:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T19]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T20:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xFFFA000000000000)
+; CHECK-NEXT:    store volatile i32 [[T20]], i32* [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float +0.0)
+  store volatile i32 %t0, i32* %p
+  %t1 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float -0.0)
+  store volatile i32 %t1, i32* %p
+  %t2 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x36a0000000000000); 0x1p-149
+  store volatile i32 %t2, i32* %p
+  %t3 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xb6a0000000000000); -0x1p-149
+  store volatile i32 %t3, i32* %p
+  %t4 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 1.0)
+  store volatile i32 %t4, i32* %p
+  %t5 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
+  store volatile i32 %t5, i32* %p
+  %t6 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 1.5)
+  store volatile i32 %t6, i32* %p
+  %t7 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x3ffe666660000000); 1.9
+  store volatile i32 %t7, i32* %p
+  %t8 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 2.0)
+  store volatile i32 %t8, i32* %p
+  %t9 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 2147483648.0)
+  store volatile i32 %t9, i32* %p
+  %t10 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 4294967040.0)
+  store volatile i32 %t10, i32* %p
+  %t11 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
+  store volatile i32 %t11, i32* %p
+  %t12 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
+  store volatile i32 %t12, i32* %p
+  %t13 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 4294967296.0)
+  store volatile i32 %t13, i32* %p
+  %t14 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float -1.0)
+  store volatile i32 %t14, i32* %p
+  %t15 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7ff0000000000000); inf
+  store volatile i32 %t15, i32* %p
+  %t16 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xfff0000000000000); -inf
+  store volatile i32 %t16, i32* %p
+  %t17 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7ff8000000000000); nan
+  store volatile i32 %t17, i32* %p
+  %t18 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0x7ffa000000000000); nan:0x200000
+  store volatile i32 %t18, i32* %p
+  %t19 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xfff8000000000000); -nan
+  store volatile i32 %t19, i32* %p
+  %t20 = call i32 @llvm.wasm.trunc.unsigned.i32.f32(float 0xfffa000000000000); -nan:0x200000
+  store volatile i32 %t20, i32* %p
+  ret void
+}
+
+define void @test_i32_trunc_f64_s(i32* %p) {
+; CHECK-LABEL: @test_i32_trunc_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 -2147483648, i32* [[P]], align 4
+; CHECK-NEXT:    store volatile i32 2147483647, i32* [[P]], align 4
+; CHECK-NEXT:    [[T16:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x41E0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T16]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T17:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xC1E0000000200000)
+; CHECK-NEXT:    store volatile i32 [[T17]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T18:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T18]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T19:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T19]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T20:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T20]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T21:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i32 [[T21]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T22:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T22]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T23:%.*]] = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i32 [[T23]], i32* [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i32 @llvm.wasm.trunc.signed.i32.f64(double +0.0)
+  store volatile i32 %t0, i32* %p
+  %t1 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -0.0)
+  store volatile i32 %t1, i32* %p
+  %t2 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
+  store volatile i32 %t2, i32* %p
+  %t3 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
+  store volatile i32 %t3, i32* %p
+  %t4 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 1.0)
+  store volatile i32 %t4, i32* %p
+  %t5 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
+  store volatile i32 %t5, i32* %p
+  %t6 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 1.5)
+  store volatile i32 %t6, i32* %p
+  %t7 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -1.0)
+  store volatile i32 %t7, i32* %p
+  %t8 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
+  store volatile i32 %t8, i32* %p
+  %t9 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -1.5)
+  store volatile i32 %t9, i32* %p
+  %t10 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xbffe666666666666); -1.9
+  store volatile i32 %t10, i32* %p
+  %t11 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -2.0)
+  store volatile i32 %t11, i32* %p
+  %t12 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 2147483647.0)
+  store volatile i32 %t12, i32* %p
+  %t13 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -2147483648.0)
+  store volatile i32 %t13, i32* %p
+  %t14 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -2147483648.9)
+  store volatile i32 %t14, i32* %p
+  %t15 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 2147483647.9)
+  store volatile i32 %t15, i32* %p
+  %t16 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 2147483648.0)
+  store volatile i32 %t16, i32* %p
+  %t17 = call i32 @llvm.wasm.trunc.signed.i32.f64(double -2147483649.0)
+  store volatile i32 %t17, i32* %p
+  %t18 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7ff0000000000000); inf
+  store volatile i32 %t18, i32* %p
+  %t19 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xfff0000000000000); -inf
+  store volatile i32 %t19, i32* %p
+  %t20 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7ff8000000000000); nan
+  store volatile i32 %t20, i32* %p
+  %t21 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
+  store volatile i32 %t21, i32* %p
+  %t22 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0xfff8000000000000); -nan
+  store volatile i32 %t22, i32* %p
+  %t23 = call i32 @llvm.wasm.trunc.signed.i32.f64(double 0x7ff4000000000000); -nan:0x4000000000000
+  store volatile i32 %t23, i32* %p
+  ret void
+}
+
+define void @test_i32_trunc_f64_u(i32* %p) {
+; CHECK-LABEL: @test_i32_trunc_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:    [[T15:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x41F0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T15]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T16:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double -1.000000e+00)
+; CHECK-NEXT:    store volatile i32 [[T16]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T17:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 1.000000e+16)
+; CHECK-NEXT:    store volatile i32 [[T17]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T18:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 1.000000e+30)
+; CHECK-NEXT:    store volatile i32 [[T18]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T19:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x43E0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T19]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T20:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T20]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T21:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i32 [[T21]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T22:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T22]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T23:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i32 [[T23]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T24:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i32 [[T24]], i32* [[P]], align 4
+; CHECK-NEXT:    [[T25:%.*]] = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xFFF4000000000000)
+; CHECK-NEXT:    store volatile i32 [[T25]], i32* [[P]], align 4
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double +0.0)
+  store volatile i32 %t0, i32* %p
+  %t1 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double -0.0)
+  store volatile i32 %t1, i32* %p
+  %t2 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
+  store volatile i32 %t2, i32* %p
+  %t3 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
+  store volatile i32 %t3, i32* %p
+  %t4 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 1.0)
+  store volatile i32 %t4, i32* %p
+  %t5 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
+  store volatile i32 %t5, i32* %p
+  %t6 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 1.5)
+  store volatile i32 %t6, i32* %p
+  %t7 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x3ffe666666666666); 1.9
+  store volatile i32 %t7, i32* %p
+  %t8 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 2.0)
+  store volatile i32 %t8, i32* %p
+  %t9 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 2147483648.0)
+  store volatile i32 %t9, i32* %p
+  %t10 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 4294967295.0)
+  store volatile i32 %t10, i32* %p
+  %t11 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
+  store volatile i32 %t11, i32* %p
+  %t12 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
+  store volatile i32 %t12, i32* %p
+  %t13 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 100000000.0)
+  store volatile i32 %t13, i32* %p
+  %t14 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 4294967295.9)
+  store volatile i32 %t14, i32* %p
+  %t15 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 4294967296.0)
+  store volatile i32 %t15, i32* %p
+  %t16 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double -1.0)
+  store volatile i32 %t16, i32* %p
+  %t17 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 10000000000000000.0); 1e16
+  store volatile i32 %t17, i32* %p
+  %t18 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 1000000000000000000000000000000.0); 1e30
+  store volatile i32 %t18, i32* %p
+  %t19 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 9223372036854775808.0)
+  store volatile i32 %t19, i32* %p
+  %t20 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7ff0000000000000); inf
+  store volatile i32 %t20, i32* %p
+  %t21 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xfff0000000000000); -inf
+  store volatile i32 %t21, i32* %p
+  %t22 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7ff8000000000000); nan
+  store volatile i32 %t22, i32* %p
+  %t23 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0x7ff4000000000000); nan:0x4000000000000
+  store volatile i32 %t23, i32* %p
+  %t24 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xfff8000000000000); -nan
+  store volatile i32 %t24, i32* %p
+  %t25 = call i32 @llvm.wasm.trunc.unsigned.i32.f64(double 0xfff4000000000000); -nan:0x4000000000000
+  store volatile i32 %t25, i32* %p
+  ret void
+}
+
+define void @test_i64_trunc_f32_s(i64* %p) {
+; CHECK-LABEL: @test_i64_trunc_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:    [[T16:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x43E0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T16]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T17:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xC3E0000020000000)
+; CHECK-NEXT:    store volatile i64 [[T17]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T18:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T18]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T19:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T19]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T20:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T20]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T21:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7FFA000000000000)
+; CHECK-NEXT:    store volatile i64 [[T21]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T22:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T22]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T23:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xFFFA000000000000)
+; CHECK-NEXT:    store volatile i64 [[T23]], i64* [[P]], align 8
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i64 @llvm.wasm.trunc.signed.i64.f32(float +0.0)
+  store volatile i64 %t0, i64* %p
+  %t1 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -0.0)
+  store volatile i64 %t1, i64* %p
+  %t2 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x36a0000000000000); 0x1p-149
+  store volatile i64 %t2, i64* %p
+  %t3 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xb6a0000000000000); -0x1p-149
+  store volatile i64 %t3, i64* %p
+  %t4 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 1.0)
+  store volatile i64 %t4, i64* %p
+  %t5 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
+  store volatile i64 %t5, i64* %p
+  %t6 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 1.5)
+  store volatile i64 %t6, i64* %p
+  %t7 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -1.0)
+  store volatile i64 %t7, i64* %p
+  %t8 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xbff19999a0000000); -0x1.19999ap+0
+  store volatile i64 %t8, i64* %p
+  %t9 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -1.5)
+  store volatile i64 %t9, i64* %p
+  %t10 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xbffe666660000000); -1.9
+  store volatile i64 %t10, i64* %p
+  %t11 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -2.0)
+  store volatile i64 %t11, i64* %p
+  %t12 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 4294967296.0)
+  store volatile i64 %t12, i64* %p
+  %t13 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -4294967296.0)
+  store volatile i64 %t13, i64* %p
+  %t14 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 9223371487098961920.0)
+  store volatile i64 %t14, i64* %p
+  %t15 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -9223372036854775808.0)
+  store volatile i64 %t15, i64* %p
+  %t16 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 9223372036854775808.0)
+  store volatile i64 %t16, i64* %p
+  %t17 = call i64 @llvm.wasm.trunc.signed.i64.f32(float -9223373136366403584.0)
+  store volatile i64 %t17, i64* %p
+  %t18 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7ff0000000000000); inf
+  store volatile i64 %t18, i64* %p
+  %t19 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xfff0000000000000); -inf
+  store volatile i64 %t19, i64* %p
+  %t20 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7ff8000000000000); nan
+  store volatile i64 %t20, i64* %p
+  %t21 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0x7ffa000000000000); nan:0x200000
+  store volatile i64 %t21, i64* %p
+  %t22 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xfff8000000000000); -nan
+  store volatile i64 %t22, i64* %p
+  %t23 = call i64 @llvm.wasm.trunc.signed.i64.f32(float 0xfffa000000000000); -nan:0x200000
+  store volatile i64 %t23, i64* %p
+  ret void
+}
+
+define void @test_i64_trunc_f32_u(i64* %p) {
+; CHECK-LABEL: @test_i64_trunc_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:    [[T11:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x43F0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T11]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T12:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float -1.000000e+00)
+; CHECK-NEXT:    store volatile i64 [[T12]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T13:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T13]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T14:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T14]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T15:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T15]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T16:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7FFA000000000000)
+; CHECK-NEXT:    store volatile i64 [[T16]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T17:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T17]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T18:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xFFFA000000000000)
+; CHECK-NEXT:    store volatile i64 [[T18]], i64* [[P]], align 8
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float +0.0)
+  store volatile i64 %t0, i64* %p
+  %t1 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float -0.0)
+  store volatile i64 %t1, i64* %p
+  %t2 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x36a0000000000000); 0x1p-149
+  store volatile i64 %t2, i64* %p
+  %t3 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xb6a0000000000000); -0x1p-149
+  store volatile i64 %t3, i64* %p
+  %t4 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 1.0)
+  store volatile i64 %t4, i64* %p
+  %t5 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x3ff19999a0000000); 0x1.19999ap+0
+  store volatile i64 %t5, i64* %p
+  %t6 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 1.5)
+  store volatile i64 %t6, i64* %p
+  %t7 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 4294967296.0)
+  store volatile i64 %t7, i64* %p
+  %t8 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 18446742974197923840.0)
+  store volatile i64 %t8, i64* %p
+  %t9 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xbfecccccc0000000); -0x1.ccccccp-1
+  store volatile i64 %t9, i64* %p
+  %t10 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xbfefffffe0000000); -0x1.fffffep-1
+  store volatile i64 %t10, i64* %p
+  %t11 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 18446744073709551616.0)
+  store volatile i64 %t11, i64* %p
+  %t12 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float -1.0)
+  store volatile i64 %t12, i64* %p
+  %t13 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7ff0000000000000); inf
+  store volatile i64 %t13, i64* %p
+  %t14 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xfff0000000000000); -inf
+  store volatile i64 %t14, i64* %p
+  %t15 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7ff8000000000000); nan
+  store volatile i64 %t15, i64* %p
+  %t16 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0x7ffa000000000000); nan:0x200000
+  store volatile i64 %t16, i64* %p
+  %t17 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xfff8000000000000); -nan
+  store volatile i64 %t17, i64* %p
+  %t18 = call i64 @llvm.wasm.trunc.unsigned.i64.f32(float 0xfffa000000000000); -nan:0x200000
+  store volatile i64 %t18, i64* %p
+  ret void
+}
+
+define void @test_i64_trunc_f64_s(i64* %p) {
+; CHECK-LABEL: @test_i64_trunc_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:    [[T16:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x43E0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T16]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T17:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xC3E0000000000001)
+; CHECK-NEXT:    store volatile i64 [[T17]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T18:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T18]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T19:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T19]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T20:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T20]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T21:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i64 [[T21]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T22:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T22]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T23:%.*]] = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i64 [[T23]], i64* [[P]], align 8
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i64 @llvm.wasm.trunc.signed.i64.f64(double +0.0)
+  store volatile i64 %t0, i64* %p
+  %t1 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -0.0)
+  store volatile i64 %t1, i64* %p
+  %t2 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
+  store volatile i64 %t2, i64* %p
+  %t3 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x8010000000000001); -0x1.0000000000001p-1022
+  store volatile i64 %t3, i64* %p
+  %t4 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 1.0)
+  store volatile i64 %t4, i64* %p
+  %t5 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
+  store volatile i64 %t5, i64* %p
+  %t6 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 1.5)
+  store volatile i64 %t6, i64* %p
+  %t7 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -1.0)
+  store volatile i64 %t7, i64* %p
+  %t8 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xbff199999999999a); -0x1.199999999999ap+0
+  store volatile i64 %t8, i64* %p
+  %t9 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -1.5)
+  store volatile i64 %t9, i64* %p
+  %t10 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xbffe666666666666); -1.9
+  store volatile i64 %t10, i64* %p
+  %t11 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -2.0)
+  store volatile i64 %t11, i64* %p
+  %t12 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 4294967296.0)
+  store volatile i64 %t12, i64* %p
+  %t13 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -4294967296.0)
+  store volatile i64 %t13, i64* %p
+  %t14 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 9223372036854774784.0)
+  store volatile i64 %t14, i64* %p
+  %t15 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -9223372036854775808.0)
+  store volatile i64 %t15, i64* %p
+  %t16 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 9223372036854775808.0)
+  store volatile i64 %t16, i64* %p
+  %t17 = call i64 @llvm.wasm.trunc.signed.i64.f64(double -9223372036854777856.0)
+  store volatile i64 %t17, i64* %p
+  %t18 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7ff0000000000000); inf
+  store volatile i64 %t18, i64* %p
+  %t19 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xfff0000000000000); -inf
+  store volatile i64 %t19, i64* %p
+  %t20 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7ff8000000000000); nan
+  store volatile i64 %t20, i64* %p
+  %t21 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
+  store volatile i64 %t21, i64* %p
+  %t22 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0xfff8000000000000); -nan
+  store volatile i64 %t22, i64* %p
+  %t23 = call i64 @llvm.wasm.trunc.signed.i64.f64(double 0x7ff4000000000000); -nan:0x4000000000000
+  store volatile i64 %t23, i64* %p
+  ret void
+}
+
+define void @test_i64_trunc_f64_u(i64* %p) {
+; CHECK-LABEL: @test_i64_trunc_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:    [[T15:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x43F0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T15]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T16:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double -1.000000e+00)
+; CHECK-NEXT:    store volatile i64 [[T16]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T17:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7FF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T17]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T18:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xFFF0000000000000)
+; CHECK-NEXT:    store volatile i64 [[T18]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T19:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7FF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T19]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T20:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7FF4000000000000)
+; CHECK-NEXT:    store volatile i64 [[T20]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T21:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xFFF8000000000000)
+; CHECK-NEXT:    store volatile i64 [[T21]], i64* [[P]], align 8
+; CHECK-NEXT:    [[T22:%.*]] = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xFFF4000000000000)
+; CHECK-NEXT:    store volatile i64 [[T22]], i64* [[P]], align 8
+; CHECK-NEXT:    ret void
+;
+  %t0 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double +0.0)
+  store volatile i64 %t0, i64* %p
+  %t1 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double -0.0)
+  store volatile i64 %t1, i64* %p
+  %t2 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x0010000000000001); 0x0.0000000000001p-1022
+  store volatile i64 %t2, i64* %p
+  %t3 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x8010000000000001); -0x0.0000000000001p-1022
+  store volatile i64 %t3, i64* %p
+  %t4 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 1.0)
+  store volatile i64 %t4, i64* %p
+  %t5 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x3ff199999999999a); 0x1.199999999999ap+0
+  store volatile i64 %t5, i64* %p
+  %t6 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 1.5)
+  store volatile i64 %t6, i64* %p
+  %t7 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 4294967295.0)
+  store volatile i64 %t7, i64* %p
+  %t8 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 4294967296.0)
+  store volatile i64 %t8, i64* %p
+  %t9 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 18446744073709549568.0)
+  store volatile i64 %t9, i64* %p
+  %t10 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xbfeccccccccccccd); -0x1.ccccccccccccdp-1
+  store volatile i64 %t10, i64* %p
+  %t11 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xbfefffffffffffff); -0x1.fffffffffffffp-1
+  store volatile i64 %t11, i64* %p
+  %t12 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 100000000.0); 1e8
+  store volatile i64 %t12, i64* %p
+  %t13 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 10000000000000000.0); 1e16
+  store volatile i64 %t13, i64* %p
+  %t14 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 9223372036854775808.0);
+  store volatile i64 %t14, i64* %p
+  %t15 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 18446744073709551616.0)
+  store volatile i64 %t15, i64* %p
+  %t16 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double -1.0)
+  store volatile i64 %t16, i64* %p
+  %t17 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7ff0000000000000); inf
+  store volatile i64 %t17, i64* %p
+  %t18 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xfff0000000000000); -inf
+  store volatile i64 %t18, i64* %p
+  %t19 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7ff8000000000000); nan
+  store volatile i64 %t19, i64* %p
+  %t20 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0x7ff4000000000000); nan:0x4000000000000
+  store volatile i64 %t20, i64* %p
+  %t21 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xfff8000000000000); -nan
+  store volatile i64 %t21, i64* %p
+  %t22 = call i64 @llvm.wasm.trunc.unsigned.i64.f64(double 0xfff4000000000000); -nan:0x4000000000000
+  store volatile i64 %t22, i64* %p
+  ret void
+}

diff  --git a/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc_saturate.ll b/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc_saturate.ll
new file mode 100644
index 000000000000..a7cd6066785a
--- /dev/null
+++ b/llvm/test/Analysis/ConstantFolding/WebAssembly/trunc_saturate.ll
@@ -0,0 +1,610 @@
+; 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