[clang] [clang] Ensure fixed point conversions work in C++ (PR #68344)

via cfe-commits cfe-commits at lists.llvm.org
Thu Oct 5 12:23:21 PDT 2023


https://github.com/PiJoules created https://github.com/llvm/llvm-project/pull/68344

None

>From 631458f0a988062666d04e7be99989e2a5635289 Mon Sep 17 00:00:00 2001
From: Leonard Chan <leonardchan at google.com>
Date: Thu, 5 Oct 2023 19:19:47 +0000
Subject: [PATCH] [clang] Ensure fixed point conversions work in C++

---
 clang/include/clang/Sema/Overload.h           |   3 +
 clang/lib/Sema/SemaDecl.cpp                   |   3 +
 clang/lib/Sema/SemaExprCXX.cpp                |  30 +
 clang/lib/Sema/SemaOverload.cpp               |  10 +-
 clang/test/Frontend/fixed_point_conversions.c | 691 +++++++++++++++++-
 5 files changed, 733 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h
index a97968dc7b20967..333309a3686a1f9 100644
--- a/clang/include/clang/Sema/Overload.h
+++ b/clang/include/clang/Sema/Overload.h
@@ -192,6 +192,9 @@ class Sema;
     /// C-only conversion between pointers with incompatible types
     ICK_Incompatible_Pointer_Conversion,
 
+    /// Fixed point type conversions according to N1169.
+    ICK_Fixed_Point_Conversion,
+
     /// The number of conversion kinds
     ICK_Num_Conversion_Kinds,
   };
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6ac02df193976a9..52cbd5c7593d9ce 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -148,6 +148,9 @@ bool Sema::isSimpleTypeSpecifier(tok::TokenKind Kind) const {
   case tok::kw___ibm128:
   case tok::kw_wchar_t:
   case tok::kw_bool:
+  case tok::kw__Accum:
+  case tok::kw__Fract:
+  case tok::kw__Sat:
 #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
 #include "clang/Basic/TransformTypeTraits.def"
   case tok::kw___auto_type:
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 1153049496d129f..e15d8e01f934bd6 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -4478,6 +4478,36 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
                  .get();
     break;
 
+  case ICK_Fixed_Point_Conversion:
+    assert((FromType->isFixedPointType() || ToType->isFixedPointType()) &&
+           "Attempting implicit fixed point conversion without a fixed "
+           "point operand");
+    if (FromType->isFloatingType())
+      From = ImpCastExprToType(From, ToType, CK_FloatingToFixedPoint,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    else if (ToType->isFloatingType())
+      From = ImpCastExprToType(From, ToType, CK_FixedPointToFloating,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    else if (FromType->isIntegralType(Context))
+      From = ImpCastExprToType(From, ToType, CK_IntegralToFixedPoint,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    else if (ToType->isIntegralType(Context))
+      From = ImpCastExprToType(From, ToType, CK_FixedPointToIntegral,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    else if (ToType->isBooleanType())
+      From = ImpCastExprToType(From, ToType, CK_FixedPointToBoolean,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    else
+      From = ImpCastExprToType(From, ToType, CK_FixedPointCast,
+                               VK_PRValue,
+                               /*BasePath=*/nullptr, CCK).get();
+    break;
+
   case ICK_Compatible_Conversion:
     From = ImpCastExprToType(From, ToType, CK_NoOp, From->getValueKind(),
                              /*BasePath=*/nullptr, CCK).get();
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index ce78994e6553814..f5cc8a6ee6e3b9f 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -156,7 +156,8 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) {
                      // it was omitted by the patch that added
                      // ICK_Zero_Queue_Conversion
     ICR_C_Conversion,
-    ICR_C_Conversion_Extension
+    ICR_C_Conversion_Extension,
+    ICR_C_Conversion_Extension,
   };
   static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds);
   return Rank[(int)Kind];
@@ -195,7 +196,8 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) {
     "OpenCL Zero Event Conversion",
     "OpenCL Zero Queue Conversion",
     "C specific type conversion",
-    "Incompatible pointer conversion"
+    "Incompatible pointer conversion",
+    "Fixed point conversion",
   };
   static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds);
   return Name[Kind];
@@ -2192,6 +2194,9 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType,
              From->isIntegerConstantExpr(S.getASTContext())) {
     SCS.Second = ICK_Compatible_Conversion;
     FromType = ToType;
+  } else if (ToType->isFixedPointType() || FromType->isFixedPointType()) {
+    SCS.Second = ICK_Fixed_Point_Conversion;
+    FromType = ToType;
   } else {
     // No second conversion required.
     SCS.Second = ICK_Identity;
@@ -5950,6 +5955,7 @@ static bool CheckConvertedConstantConversions(Sema &S,
   case ICK_Zero_Event_Conversion:
   case ICK_C_Only_Conversion:
   case ICK_Incompatible_Pointer_Conversion:
+  case ICK_Fixed_Point_Conversion:
     return false;
 
   case ICK_Lvalue_To_Rvalue:
diff --git a/clang/test/Frontend/fixed_point_conversions.c b/clang/test/Frontend/fixed_point_conversions.c
index ebd1d7e521df43b..87fa1ac2d49890c 100644
--- a/clang/test/Frontend/fixed_point_conversions.c
+++ b/clang/test/Frontend/fixed_point_conversions.c
@@ -1,6 +1,8 @@
 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
-// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
-// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK,UNSIGNED
+// RUN: %clang_cc1 -x c -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
+// RUN: %clang_cc1 -x c -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK,UNSIGNED
+// RUN: %clang_cc1 -x c++ -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK-CXX,SIGNED-CXX
+// RUN: %clang_cc1 -x c++ -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s --check-prefixes=CHECK-CXX,UNSIGNED-CXX
 
 short _Accum sa;
 _Accum a, a2;
@@ -41,6 +43,12 @@ double d;
 // CHECK-NEXT:    store i32 [[TMP0]], ptr @a2, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z9fix_same1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    store i32 [[TMP0]], ptr @a2, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_same1(void) {
   a2 = a;
 }
@@ -51,6 +59,12 @@ void fix_same1(void) {
 // CHECK-NEXT:    store i32 [[TMP0]], ptr @a2, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z9fix_same2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    store i32 [[TMP0]], ptr @a2, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_same2(void) {
   a2 = (_Accum)a;
 }
@@ -64,6 +78,14 @@ void fix_same2(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z13fix_castdown1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i64, ptr @la, align 8
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i64 [[TMP0]], 16
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castdown1(void) {
   a = la;
 }
@@ -76,6 +98,14 @@ void fix_castdown1(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z13fix_castdown2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i64, ptr @la, align 8
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i64 [[TMP0]], 16
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castdown2(void) {
   a = (_Accum)la;
 }
@@ -88,6 +118,14 @@ void fix_castdown2(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z13fix_castdown3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[DOWNSCALE]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castdown3(void) {
   sa = a;
 }
@@ -100,6 +138,14 @@ void fix_castdown3(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z13fix_castdown4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[DOWNSCALE]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castdown4(void) {
   sa = a;
 }
@@ -113,6 +159,14 @@ void fix_castdown4(void) {
 // CHECK-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z11fix_castup1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @sa, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-CXX-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castup1(void) {
   a = sa;
 }
@@ -125,6 +179,14 @@ void fix_castup1(void) {
 // CHECK-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z11fix_castup2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @sa, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-CXX-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castup2(void) {
   a = (_Accum)sa;
 }
@@ -137,6 +199,14 @@ void fix_castup2(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z11fix_castup3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i64, ptr @la, align 8
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i64 [[TMP0]], 16
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castup3(void) {
   a = la;
 }
@@ -149,6 +219,14 @@ void fix_castup3(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z11fix_castup4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i64, ptr @la, align 8
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i64 [[TMP0]], 16
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_castup4(void) {
   a = (long _Accum)la;
 }
@@ -167,6 +245,19 @@ void fix_castup4(void) {
 // UNSIGNED-NEXT:    store i32 [[TMP0]], ptr @ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sign1v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[TMP0]], 1
+// SIGNED-CXX-NEXT:    store i32 [[UPSCALE]], ptr @ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sign1v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// UNSIGNED-CXX-NEXT:    store i32 [[TMP0]], ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sign1(void) {
   ua = a;
 }
@@ -184,6 +275,19 @@ void fix_sign1(void) {
 // UNSIGNED-NEXT:    store i32 [[TMP0]], ptr @a, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sign2v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// SIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = lshr i32 [[TMP0]], 1
+// SIGNED-CXX-NEXT:    store i32 [[DOWNSCALE]], ptr @a, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sign2v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    store i32 [[TMP0]], ptr @a, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sign2(void) {
   a = ua;
 }
@@ -201,6 +305,19 @@ void fix_sign2(void) {
 // UNSIGNED-NEXT:    store i32 [[TMP0]], ptr @ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sign3v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[TMP0]], 1
+// SIGNED-CXX-NEXT:    store i32 [[UPSCALE]], ptr @ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sign3v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// UNSIGNED-CXX-NEXT:    store i32 [[TMP0]], ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sign3(void) {
   ua = (unsigned _Accum)a;
 }
@@ -218,6 +335,19 @@ void fix_sign3(void) {
 // UNSIGNED-NEXT:    store i32 [[TMP0]], ptr @a, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sign4v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// SIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = lshr i32 [[TMP0]], 1
+// SIGNED-CXX-NEXT:    store i32 [[DOWNSCALE]], ptr @a, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sign4v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    store i32 [[TMP0]], ptr @a, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sign4(void) {
   a = (_Accum)ua;
 }
@@ -238,6 +368,22 @@ void fix_sign4(void) {
 // UNSIGNED-NEXT:    store i64 [[UPSCALE]], ptr @ula, align 8
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sign5v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 17
+// SIGNED-CXX-NEXT:    store i64 [[UPSCALE]], ptr @ula, align 8
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sign5v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 16
+// UNSIGNED-CXX-NEXT:    store i64 [[UPSCALE]], ptr @ula, align 8
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sign5(void) {
   ula = a;
 }
@@ -255,6 +401,18 @@ void fix_sign5(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @sat_sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[DOWNSCALE]], 32767
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i32 32767, i32 [[DOWNSCALE]]
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[SATMAX]], -32768
+// CHECK-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i32 -32768, i32 [[SATMAX]]
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[SATMIN]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @sat_sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat1(void) {
   // Casting down between types
   sat_sa = sat_a;
@@ -272,6 +430,18 @@ void fix_sat1(void) {
 // CHECK-NEXT:    store i8 [[RESIZE]], ptr @sat_sf, align 1
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[DOWNSCALE]], 127
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i32 127, i32 [[DOWNSCALE]]
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[SATMAX]], -128
+// CHECK-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i32 -128, i32 [[SATMAX]]
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[SATMIN]] to i8
+// CHECK-CXX-NEXT:    store i8 [[RESIZE]], ptr @sat_sf, align 1
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat2(void) {
   // Accum to Fract, decreasing scale
   sat_sf = sat_a;
@@ -288,6 +458,17 @@ void fix_sat2(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @sat_f, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[TMP0]], 32767
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i32 32767, i32 [[TMP0]]
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[SATMAX]], -32768
+// CHECK-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i32 -32768, i32 [[SATMAX]]
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[SATMIN]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @sat_f, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat3(void) {
   // Accum to Fract, same scale
   sat_f = a;
@@ -306,6 +487,19 @@ void fix_sat3(void) {
 // CHECK-NEXT:    store i32 [[RESIZE1]], ptr @sat_lf, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i48 [[UPSCALE]], 2147483647
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i48 2147483647, i48 [[UPSCALE]]
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i48 [[SATMAX]], -2147483648
+// CHECK-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i48 -2147483648, i48 [[SATMAX]]
+// CHECK-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i48 [[SATMIN]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE1]], ptr @sat_lf, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat4(void) {
   // Accum to Fract, increasing scale
   sat_lf = sat_a;
@@ -335,6 +529,30 @@ void fix_sat4(void) {
 // UNSIGNED-NEXT:    store i16 [[RESIZE]], ptr @sat_usa, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8fix_sat5v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// SIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 7
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[DOWNSCALE]], 65535
+// SIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i32 65535, i32 [[DOWNSCALE]]
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[SATMAX]], 0
+// SIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i32 0, i32 [[SATMAX]]
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[SATMIN]] to i16
+// SIGNED-CXX-NEXT:    store i16 [[RESIZE]], ptr @sat_usa, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8fix_sat5v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// UNSIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[DOWNSCALE]], 32767
+// UNSIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i32 32767, i32 [[DOWNSCALE]]
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[SATMAX]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i32 0, i32 [[SATMAX]]
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[SATMIN]] to i16
+// UNSIGNED-CXX-NEXT:    store i16 [[RESIZE]], ptr @sat_usa, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sat5(void) {
   // Signed to unsigned, decreasing scale
   sat_usa = sat_a;
@@ -359,6 +577,25 @@ void fix_sat5(void) {
 // UNSIGNED-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8fix_sat6v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i33
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp slt i33 [[UPSCALE]], 0
+// SIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP1]], i33 0, i33 [[UPSCALE]]
+// SIGNED-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i33 [[SATMIN]] to i32
+// SIGNED-CXX-NEXT:    store i32 [[RESIZE1]], ptr @sat_ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8fix_sat6v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[TMP0]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP1]], i32 0, i32 [[TMP0]]
+// UNSIGNED-CXX-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sat6(void) {
   // Signed to unsigned, increasing scale
   sat_ua = sat_a;
@@ -370,6 +607,12 @@ void fix_sat6(void) {
 // CHECK-NEXT:    store i32 [[TMP0]], ptr @sat_a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat7v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    store i32 [[TMP0]], ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat7(void) {
   // Nothing when saturating to the same type and size
   sat_a = a;
@@ -381,6 +624,12 @@ void fix_sat7(void) {
 // CHECK-NEXT:    store i32 [[TMP0]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat8v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    store i32 [[TMP0]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat8(void) {
   // Nothing when assigning back
   a = sat_a;
@@ -393,6 +642,13 @@ void fix_sat8(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @sat_a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_sat9v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @sat_f, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_sat9(void) {
   // No overflow when casting from fract to signed accum
   sat_a = sat_f;
@@ -418,6 +674,26 @@ void fix_sat9(void) {
 // UNSIGNED-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z9fix_sat10v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i8, ptr @sat_sf, align 1
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i32
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 9
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[UPSCALE]], 0
+// SIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP1]], i32 0, i32 [[UPSCALE]]
+// SIGNED-CXX-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z9fix_sat10v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i8, ptr @sat_sf, align 1
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i32
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp slt i32 [[UPSCALE]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP1]], i32 0, i32 [[UPSCALE]]
+// UNSIGNED-CXX-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_sat10(void) {
   // Only get overflow checking if signed fract to unsigned accum
   sat_ua = sat_sf;
@@ -432,6 +708,14 @@ void fix_sat10(void) {
 // CHECK-NEXT:    store i8 [[RESIZE]], ptr @sf, align 1
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i32 [[TMP0]], 8
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-CXX-NEXT:    store i8 [[RESIZE]], ptr @sf, align 1
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract1(void) {
   // To lower scale
   sf = a;
@@ -445,6 +729,14 @@ void fix_fract1(void) {
 // CHECK-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i8, ptr @sf, align 1
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i8 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-CXX-NEXT:    store i32 [[UPSCALE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract2(void) {
   // To higher scale
   a = sf;
@@ -457,6 +749,13 @@ void fix_fract2(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @f, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @f, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract3(void) {
   // To same scale
   f = a;
@@ -469,6 +768,13 @@ void fix_fract3(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @f, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract4(void) {
   a = f;
 }
@@ -480,6 +786,13 @@ void fix_fract4(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @ua, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract5v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @uf, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @ua, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract5(void) {
   // To unsigned
   ua = uf;
@@ -492,6 +805,13 @@ void fix_fract5(void) {
 // CHECK-NEXT:    store i16 [[RESIZE]], ptr @uf, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_fract6v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE]], ptr @uf, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_fract6(void) {
   uf = ua;
 }
@@ -508,6 +828,17 @@ void fix_fract6(void) {
 // CHECK-NEXT:    store i32 [[RESIZE]], ptr @i, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8fix_int1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @sa, align 2
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp slt i16 [[TMP0]], 0
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = add i16 [[TMP0]], 127
+// CHECK-CXX-NEXT:    [[TMP3:%.*]] = select i1 [[TMP1]], i16 [[TMP2]], i16 [[TMP0]]
+// CHECK-CXX-NEXT:    [[DOWNSCALE:%.*]] = ashr i16 [[TMP3]], 7
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[DOWNSCALE]] to i32
+// CHECK-CXX-NEXT:    store i32 [[RESIZE]], ptr @i, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_int1(void) {
   // Will need to check for negative values
   i = sa;
@@ -529,6 +860,22 @@ void fix_int1(void) {
 // UNSIGNED-NEXT:    store i32 [[RESIZE]], ptr @i, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8fix_int2v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @usa, align 2
+// SIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = lshr i16 [[TMP0]], 8
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = zext i16 [[DOWNSCALE]] to i32
+// SIGNED-CXX-NEXT:    store i32 [[RESIZE]], ptr @i, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8fix_int2v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @usa, align 2
+// UNSIGNED-CXX-NEXT:    [[DOWNSCALE:%.*]] = lshr i16 [[TMP0]], 7
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = zext i16 [[DOWNSCALE]] to i32
+// UNSIGNED-CXX-NEXT:    store i32 [[RESIZE]], ptr @i, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_int2(void) {
   // No check needed for unsigned fixed points. Can just right shift.
   i = usa;
@@ -543,6 +890,14 @@ void fix_int2(void) {
 // CHECK-NEXT:    store i16 [[UPSCALE]], ptr @sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8int_fix1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 7
+// CHECK-CXX-NEXT:    store i16 [[UPSCALE]], ptr @sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void int_fix1(void) {
   sa = i;
 }
@@ -555,6 +910,14 @@ void int_fix1(void) {
 // CHECK-NEXT:    store i16 [[UPSCALE]], ptr @sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8int_fix2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 7
+// CHECK-CXX-NEXT:    store i16 [[UPSCALE]], ptr @sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void int_fix2(void) {
   sa = ui;
 }
@@ -575,6 +938,22 @@ void int_fix2(void) {
 // UNSIGNED-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8int_fix3v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
+// SIGNED-CXX-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8int_fix3v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 7
+// UNSIGNED-CXX-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void int_fix3(void) {
   usa = i;
 }
@@ -595,6 +974,22 @@ void int_fix3(void) {
 // UNSIGNED-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8int_fix4v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
+// SIGNED-CXX-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8int_fix4v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i16
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 7
+// UNSIGNED-CXX-NEXT:    store i16 [[UPSCALE]], ptr @usa, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void int_fix4(void) {
   usa = ui;
 }
@@ -607,6 +1002,14 @@ void int_fix4(void) {
 // CHECK-NEXT:    store i64 [[UPSCALE]], ptr @la, align 8
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8int_fix5v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @s, align 2
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i16 [[TMP0]] to i64
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 31
+// CHECK-CXX-NEXT:    store i64 [[UPSCALE]], ptr @la, align 8
+// CHECK-CXX-NEXT:    ret void
+//
 void int_fix5(void) {
   la = s;
 }
@@ -625,6 +1028,19 @@ void int_fix5(void) {
 // CHECK-NEXT:    store i16 [[RESIZE1]], ptr @sat_sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8int_sat1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i39
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i39 [[UPSCALE]], 32767
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i39 32767, i39 [[UPSCALE]]
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i39 [[SATMAX]], -32768
+// CHECK-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i39 -32768, i39 [[SATMAX]]
+// CHECK-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i39 [[SATMIN]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void int_sat1(void) {
   sat_sa = i;
 }
@@ -640,6 +1056,17 @@ void int_sat1(void) {
 // CHECK-NEXT:    store i16 [[RESIZE1]], ptr @sat_sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z8int_sat2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// CHECK-CXX-NEXT:    [[RESIZE:%.*]] = zext i32 [[TMP0]] to i39
+// CHECK-CXX-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = icmp ugt i39 [[UPSCALE]], 32767
+// CHECK-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i39 32767, i39 [[UPSCALE]]
+// CHECK-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i39 [[SATMAX]] to i16
+// CHECK-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void int_sat2(void) {
   sat_sa = ui;
 }
@@ -670,6 +1097,32 @@ void int_sat2(void) {
 // UNSIGNED-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8int_sat3v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i40
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 8
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i40 [[UPSCALE]], 65535
+// SIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i40 65535, i40 [[UPSCALE]]
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i40 [[SATMAX]], 0
+// SIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i40 0, i40 [[SATMAX]]
+// SIGNED-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i40 [[SATMIN]] to i16
+// SIGNED-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8int_sat3v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @i, align 4
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = sext i32 [[TMP0]] to i39
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp sgt i39 [[UPSCALE]], 32767
+// UNSIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i39 32767, i39 [[UPSCALE]]
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = icmp slt i39 [[SATMAX]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP2]], i39 0, i39 [[SATMAX]]
+// UNSIGNED-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i39 [[SATMIN]] to i16
+// UNSIGNED-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void int_sat3(void) {
   sat_usa = i;
 }
@@ -696,6 +1149,28 @@ void int_sat3(void) {
 // UNSIGNED-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z8int_sat4v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// SIGNED-CXX-NEXT:    [[RESIZE:%.*]] = zext i32 [[TMP0]] to i40
+// SIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 8
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp ugt i40 [[UPSCALE]], 65535
+// SIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i40 65535, i40 [[UPSCALE]]
+// SIGNED-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i40 [[SATMAX]] to i16
+// SIGNED-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z8int_sat4v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ui, align 4
+// UNSIGNED-CXX-NEXT:    [[RESIZE:%.*]] = zext i32 [[TMP0]] to i39
+// UNSIGNED-CXX-NEXT:    [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = icmp ugt i39 [[UPSCALE]], 32767
+// UNSIGNED-CXX-NEXT:    [[SATMAX:%.*]] = select i1 [[TMP1]], i39 32767, i39 [[UPSCALE]]
+// UNSIGNED-CXX-NEXT:    [[RESIZE1:%.*]] = trunc i39 [[SATMAX]] to i16
+// UNSIGNED-CXX-NEXT:    store i16 [[RESIZE1]], ptr @sat_usa, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void int_sat4(void) {
   sat_usa = ui;
 }
@@ -709,6 +1184,14 @@ void int_sat4(void) {
 // CHECK-NEXT:    store i16 [[TMP2]], ptr @sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_fix1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 1.280000e+02
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i16
+// CHECK-CXX-NEXT:    store i16 [[TMP2]], ptr @sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void float_fix1(void) {
   sa = fl;
 }
@@ -721,6 +1204,14 @@ void float_fix1(void) {
 // CHECK-NEXT:    store i32 [[TMP2]], ptr @a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_fix2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i32
+// CHECK-CXX-NEXT:    store i32 [[TMP2]], ptr @a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void float_fix2(void) {
   a = fl;
 }
@@ -733,6 +1224,14 @@ void float_fix2(void) {
 // CHECK-NEXT:    store i64 [[TMP2]], ptr @la, align 8
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_fix3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 0x41E0000000000000
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i64
+// CHECK-CXX-NEXT:    store i64 [[TMP2]], ptr @la, align 8
+// CHECK-CXX-NEXT:    ret void
+//
 void float_fix3(void) {
   la = fl;
 }
@@ -745,6 +1244,14 @@ void float_fix3(void) {
 // CHECK-NEXT:    store i8 [[TMP2]], ptr @sf, align 1
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_fix4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 1.280000e+02
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i8
+// CHECK-CXX-NEXT:    store i8 [[TMP2]], ptr @sf, align 1
+// CHECK-CXX-NEXT:    ret void
+//
 void float_fix4(void) {
   sf = fl;
 }
@@ -757,6 +1264,14 @@ void float_fix4(void) {
 // CHECK-NEXT:    store i32 [[TMP2]], ptr @lf, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_fix5v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 0x41E0000000000000
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i32
+// CHECK-CXX-NEXT:    store i32 [[TMP2]], ptr @lf, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void float_fix5(void) {
   lf = fl;
 }
@@ -777,6 +1292,22 @@ void float_fix5(void) {
 // UNSIGNED-NEXT:    store i32 [[TMP2]], ptr @ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10float_fix6v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 6.553600e+04
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = fptoui float [[TMP1]] to i32
+// SIGNED-CXX-NEXT:    store i32 [[TMP2]], ptr @ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10float_fix6v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i32
+// UNSIGNED-CXX-NEXT:    store i32 [[TMP2]], ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void float_fix6(void) {
   ua = fl;
 }
@@ -797,6 +1328,22 @@ void float_fix6(void) {
 // UNSIGNED-NEXT:    store i16 [[TMP2]], ptr @uf, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10float_fix7v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 6.553600e+04
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = fptoui float [[TMP1]] to i16
+// SIGNED-CXX-NEXT:    store i16 [[TMP2]], ptr @uf, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10float_fix7v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = fptosi float [[TMP1]] to i16
+// UNSIGNED-CXX-NEXT:    store i16 [[TMP2]], ptr @uf, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void float_fix7(void) {
   uf = fl;
 }
@@ -810,6 +1357,14 @@ void float_fix7(void) {
 // CHECK-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_float1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @sa, align 2
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = sitofp i16 [[TMP0]] to float
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 7.812500e-03
+// CHECK-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_float1(void) {
   fl = sa;
 }
@@ -822,6 +1377,14 @@ void fix_float1(void) {
 // CHECK-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_float2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @a, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = sitofp i32 [[TMP0]] to float
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3F00000000000000
+// CHECK-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_float2(void) {
   fl = a;
 }
@@ -834,6 +1397,14 @@ void fix_float2(void) {
 // CHECK-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_float3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i64, ptr @la, align 8
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = sitofp i64 [[TMP0]] to float
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3E00000000000000
+// CHECK-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_float3(void) {
   fl = la;
 }
@@ -846,6 +1417,14 @@ void fix_float3(void) {
 // CHECK-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_float4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i8, ptr @sf, align 1
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = sitofp i8 [[TMP0]] to float
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 7.812500e-03
+// CHECK-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_float4(void) {
   fl = sf;
 }
@@ -858,6 +1437,14 @@ void fix_float4(void) {
 // CHECK-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10fix_float5v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @lf, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = sitofp i32 [[TMP0]] to float
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3E00000000000000
+// CHECK-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void fix_float5(void) {
   fl = lf;
 }
@@ -878,6 +1465,22 @@ void fix_float5(void) {
 // UNSIGNED-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10fix_float6v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = uitofp i32 [[TMP0]] to float
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3EF0000000000000
+// SIGNED-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10fix_float6v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i32, ptr @ua, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = uitofp i32 [[TMP0]] to float
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3F00000000000000
+// UNSIGNED-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_float6(void) {
   fl = ua;
 }
@@ -898,6 +1501,22 @@ void fix_float6(void) {
 // UNSIGNED-NEXT:    store float [[TMP2]], ptr @fl, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10fix_float7v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @uf, align 2
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = uitofp i16 [[TMP0]] to float
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3EF0000000000000
+// SIGNED-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10fix_float7v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load i16, ptr @uf, align 2
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = uitofp i16 [[TMP0]] to float
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = fmul float [[TMP1]], 0x3F00000000000000
+// UNSIGNED-CXX-NEXT:    store float [[TMP2]], ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void fix_float7(void) {
   fl = uf;
 }
@@ -911,6 +1530,14 @@ void fix_float7(void) {
 // CHECK-NEXT:    store i16 [[TMP2]], ptr @sat_sa, align 2
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_sat1v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 1.280000e+02
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = call i16 @llvm.fptosi.sat.i16.f32(float [[TMP1]])
+// CHECK-CXX-NEXT:    store i16 [[TMP2]], ptr @sat_sa, align 2
+// CHECK-CXX-NEXT:    ret void
+//
 void float_sat1(void) {
   sat_sa = fl;
 }
@@ -923,6 +1550,14 @@ void float_sat1(void) {
 // CHECK-NEXT:    store i32 [[TMP2]], ptr @sat_a, align 4
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_sat2v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[TMP1]])
+// CHECK-CXX-NEXT:    store i32 [[TMP2]], ptr @sat_a, align 4
+// CHECK-CXX-NEXT:    ret void
+//
 void float_sat2(void) {
   sat_a = fl;
 }
@@ -935,6 +1570,14 @@ void float_sat2(void) {
 // CHECK-NEXT:    store i64 [[TMP2]], ptr @sat_la, align 8
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_sat3v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 0x41E0000000000000
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = call i64 @llvm.fptosi.sat.i64.f32(float [[TMP1]])
+// CHECK-CXX-NEXT:    store i64 [[TMP2]], ptr @sat_la, align 8
+// CHECK-CXX-NEXT:    ret void
+//
 void float_sat3(void) {
   sat_la = fl;
 }
@@ -947,6 +1590,14 @@ void float_sat3(void) {
 // CHECK-NEXT:    store i8 [[TMP2]], ptr @sat_sf, align 1
 // CHECK-NEXT:    ret void
 //
+// CHECK-CXX-LABEL: @_Z10float_sat4v(
+// CHECK-CXX-NEXT:  entry:
+// CHECK-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// CHECK-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 1.280000e+02
+// CHECK-CXX-NEXT:    [[TMP2:%.*]] = call i8 @llvm.fptosi.sat.i8.f32(float [[TMP1]])
+// CHECK-CXX-NEXT:    store i8 [[TMP2]], ptr @sat_sf, align 1
+// CHECK-CXX-NEXT:    ret void
+//
 void float_sat4(void) {
   sat_sf = fl;
 }
@@ -969,6 +1620,24 @@ void float_sat4(void) {
 // UNSIGNED-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10float_sat5v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 6.553600e+04
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = call i32 @llvm.fptoui.sat.i32.f32(float [[TMP1]])
+// SIGNED-CXX-NEXT:    store i32 [[TMP2]], ptr @sat_ua, align 4
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10float_sat5v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = call i32 @llvm.fptosi.sat.i32.f32(float [[TMP1]])
+// UNSIGNED-CXX-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i32 0, i32 [[TMP2]]
+// UNSIGNED-CXX-NEXT:    store i32 [[SATMIN]], ptr @sat_ua, align 4
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void float_sat5(void) {
   sat_ua = fl;
 }
@@ -991,6 +1660,24 @@ void float_sat5(void) {
 // UNSIGNED-NEXT:    store i16 [[SATMIN]], ptr @sat_uf, align 2
 // UNSIGNED-NEXT:    ret void
 //
+// SIGNED-CXX-LABEL: @_Z10float_sat6v(
+// SIGNED-CXX-NEXT:  entry:
+// SIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// SIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 6.553600e+04
+// SIGNED-CXX-NEXT:    [[TMP2:%.*]] = call i16 @llvm.fptoui.sat.i16.f32(float [[TMP1]])
+// SIGNED-CXX-NEXT:    store i16 [[TMP2]], ptr @sat_uf, align 2
+// SIGNED-CXX-NEXT:    ret void
+//
+// UNSIGNED-CXX-LABEL: @_Z10float_sat6v(
+// UNSIGNED-CXX-NEXT:  entry:
+// UNSIGNED-CXX-NEXT:    [[TMP0:%.*]] = load float, ptr @fl, align 4
+// UNSIGNED-CXX-NEXT:    [[TMP1:%.*]] = fmul float [[TMP0]], 3.276800e+04
+// UNSIGNED-CXX-NEXT:    [[TMP2:%.*]] = call i16 @llvm.fptosi.sat.i16.f32(float [[TMP1]])
+// UNSIGNED-CXX-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[TMP2]], 0
+// UNSIGNED-CXX-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i16 0, i16 [[TMP2]]
+// UNSIGNED-CXX-NEXT:    store i16 [[SATMIN]], ptr @sat_uf, align 2
+// UNSIGNED-CXX-NEXT:    ret void
+//
 void float_sat6(void) {
   sat_uf = fl;
 }



More information about the cfe-commits mailing list