summaryrefslogtreecommitdiffstats
path: root/test/Frontend
diff options
context:
space:
mode:
authorJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
committerJordan Rupprecht <rupprecht@google.com>2019-05-14 21:58:59 +0000
commitb35a2aa71f76a334a9c98c0a3c3995b5d902d2b9 (patch)
treecdff4a5d1a715d4ad622fd8f190128b54bebe440 /test/Frontend
parent3748d41833787fcbf59cc5624e8d2b042a8991bc (diff)
parent741e05796da92b46d4f7bcbee00702ff37df6489 (diff)
Creating branches/google/stable and tags/google/stable/2019-05-14 from r360103upstream/google/stable
git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/google/stable@360714 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Frontend')
-rw-r--r--test/Frontend/fixed_point_add.c433
-rw-r--r--test/Frontend/fixed_point_comparisons.c378
-rw-r--r--test/Frontend/fixed_point_conversions.c540
-rw-r--r--test/Frontend/fixed_point_errors.c18
-rw-r--r--test/Frontend/fixed_point_sub.c390
-rw-r--r--test/Frontend/fixed_point_unknown_conversions.c9
-rw-r--r--test/Frontend/optimization-remark-with-hotness.c2
-rw-r--r--test/Frontend/optimization-remark.c3
-rw-r--r--test/Frontend/output-failures.c4
-rw-r--r--test/Frontend/stats-file.c2
-rw-r--r--test/Frontend/verify-marker.c22
-rw-r--r--test/Frontend/verify-marker.h1
-rw-r--r--test/Frontend/warning-mapping-2.c6
-rw-r--r--test/Frontend/warning-mapping-4.c4
-rw-r--r--test/Frontend/warning-mapping-5.c5
-rw-r--r--test/Frontend/warning-mapping-6.c9
-rw-r--r--test/Frontend/x86-target-cpu.c1
17 files changed, 1640 insertions, 187 deletions
diff --git a/test/Frontend/fixed_point_add.c b/test/Frontend/fixed_point_add.c
new file mode 100644
index 0000000000..be3d5a8f5e
--- /dev/null
+++ b/test/Frontend/fixed_point_add.c
@@ -0,0 +1,433 @@
+// 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 -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
+
+// Addition between different fixed point types
+short _Accum sa_const = 1.0hk + 2.0hk; // CHECK-DAG: @sa_const = {{.*}}global i16 384, align 2
+_Accum a_const = 1.0hk + 2.0k; // CHECK-DAG: @a_const = {{.*}}global i32 98304, align 4
+long _Accum la_const = 1.0hk + 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 6442450944, align 8
+short _Accum sa_const2 = 0.5hr + 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 320, align 2
+short _Accum sa_const3 = 0.5r + 2.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 320, align 2
+short _Accum sa_const4 = 0.5lr + 2.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 320, align 2
+
+// Unsigned addition
+unsigned short _Accum usa_const = 1.0uhk + 2.0uhk;
+// CHECK-SIGNED-DAG: @usa_const = {{.*}}global i16 768, align 2
+// CHECK-UNSIGNED-DAG: @usa_const = {{.*}}global i16 384, align 2
+
+// Unsigned + signed
+short _Accum sa_const5 = 1.0uhk + 2.0hk;
+// CHECK-DAG: @sa_const5 = {{.*}}global i16 384, align 2
+
+// Addition with negative number
+short _Accum sa_const6 = 0.5hr + (-2.0hk);
+// CHECK-DAG: @sa_const6 = {{.*}}global i16 -192, align 2
+
+// Int addition
+unsigned short _Accum usa_const2 = 2 + 0.5uhk;
+// CHECK-SIGNED-DAG: @usa_const2 = {{.*}}global i16 640, align 2
+// CHECK-UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 320, align 2
+short _Accum sa_const7 = 2 + (-0.5hk); // CHECK-DAG: @sa_const7 = {{.*}}global i16 192, align 2
+short _Accum sa_const8 = 257 + (-2.0hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 32640, align 2
+long _Fract lf_const = -0.5lr + 1; // CHECK-DAG: @lf_const = {{.*}}global i32 1073741824, align 4
+
+// Saturated addition
+_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk + 128.0hk;
+// CHECK-DAG: @sat_sa_const = {{.*}}global i16 32767, align 2
+_Sat unsigned short _Accum sat_usa_const = (_Sat unsigned short _Accum)128.0uhk + 128.0uhk;
+// CHECK-SIGNED-DAG: @sat_usa_const = {{.*}}global i16 65535, align 2
+// CHECK-UNSIGNED-DAG: @sat_usa_const = {{.*}}global i16 32767, align 2
+_Sat short _Accum sat_sa_const2 = (_Sat short _Accum)128.0hk + 128;
+// CHECK-DAG: @sat_sa_const2 = {{.*}}global i16 32767, align 2
+_Sat unsigned short _Accum sat_usa_const2 = (_Sat unsigned short _Accum)128.0uhk + 128;
+// CHECK-SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 65535, align 2
+// CHECK-UNSIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 32767, align 2
+_Sat unsigned short _Accum sat_usa_const3 = (_Sat unsigned short _Accum)0.5uhk + (-2);
+// CHECK-DAG: @sat_usa_const3 = {{.*}}global i16 0, align 2
+
+void SignedAddition() {
+ // CHECK-LABEL: SignedAddition
+ short _Accum sa;
+ _Accum a, b, c, d;
+ long _Accum la;
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ short _Fract sf;
+ _Fract f;
+ long _Fract lf;
+ unsigned short _Fract usf;
+ unsigned _Fract uf;
+ unsigned long _Fract ulf;
+
+ // Same type
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SA2:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[SA2]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa + sa;
+
+ // To larger scale and larger width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
+ // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[SA]], [[A]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = sa + a;
+
+ // To same scale and smaller width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
+ // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i16
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[EXT_SF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa + sf;
+
+ // To smaller scale and same width.
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[F:%[0-9]+]] = load i16, i16* %f, align 2
+ // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i24
+ // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i24 [[EXT_SA]], 8
+ // CHECK-NEXT: [[EXT_F:%[a-z0-9]+]] = sext i16 [[F]] to i24
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[SA]], [[EXT_F]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8
+ // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[TRUNC_RES]], i16* %sa, align 2
+ sa = sa + f;
+
+ // To smaller scale and smaller width
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
+ // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i32
+ // CHECK-NEXT: [[SF:%[a-z0-9]+]] = shl i32 [[EXT_SF]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[A]], [[SF]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = a + sf;
+
+ // To larger scale and same width
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
+ // CHECK-NEXT: [[EXT_A:%[a-z0-9]+]] = sext i32 [[A]] to i48
+ // CHECK-NEXT: [[A:%[a-z0-9]+]] = shl i48 [[EXT_A]], 16
+ // CHECK-NEXT: [[EXT_LF:%[a-z0-9]+]] = sext i32 [[LF]] to i48
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i48 [[A]], [[EXT_LF]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i48 [[SUM]], 16
+ // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i48 [[RES]] to i32
+ // CHECK-NEXT: store i32 [[TRUNC_RES]], i32* %a, align 4
+ a = a + lf;
+
+ // With corresponding unsigned type
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i17
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i17 [[SA]], [[USA_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[USA]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa + usa;
+
+ // With unsigned of larger scale
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i33
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i33 [[SA_EXT]], 9
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i32 [[USA]] to i33
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i33 [[SA]], [[USA_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i33 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i33 [[RESULT]] to i32
+ // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
+ // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i32 [[SA]], [[USA]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = sa + ua;
+
+ // With unsigned of smaller width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
+ // SIGNED-NEXT: [[USF_EXT:%[a-z0-9]+]] = zext i8 [[USF]] to i17
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i17 [[SA]], [[USF_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i16 [[SA]], [[EXT_USF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa + usf;
+
+ // With unsigned of larger width and smaller scale
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[ULF:%[0-9]+]] = load i32, i32* %ulf, align 4
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i41
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i41 [[SA_EXT]], 25
+ // SIGNED-NEXT: [[ULF_EXT:%[a-z0-9]+]] = zext i32 [[ULF]] to i41
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i41 [[SA]], [[ULF_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i41 [[SUM]], 25
+ // SIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i41 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i40
+ // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i40 [[EXT_SA]], 24
+ // UNSIGNED-NEXT: [[EXT_ULF:%[a-z0-9]+]] = zext i32 [[ULF]] to i40
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[SA]], [[EXT_ULF]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i40 [[SUM]], 24
+ // UNSIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i40 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %sa, align 2
+ sa = sa + ulf;
+
+ // Chained additions of the same signed type should result in the same
+ // semantics width.
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[B:%[0-9]+]] = load i32, i32* %b, align 4
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[A]], [[B]]
+ // CHECK-NEXT: [[C:%[0-9]+]] = load i32, i32* %c, align 4
+ // CHECK-NEXT: [[SUM2:%[0-9]+]] = add i32 [[SUM]], [[C]]
+ // CHECK-NEXT: [[D:%[0-9]+]] = load i32, i32* %d, align 4
+ // CHECK-NEXT: [[SUM3:%[0-9]+]] = add i32 [[SUM2]], [[D]]
+ // CHECK-NEXT: store i32 [[SUM3]], i32* %a, align 4
+ a = a + b + c + d;
+}
+
+void UnsignedAddition() {
+ // CHECK-LABEL: UnsignedAddition
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ unsigned short _Fract usf;
+ unsigned _Fract uf;
+ unsigned long _Fract ulf;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USA2:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[USA]], [[USA2]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
+ usa = usa + usa;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[EXT_USA:%[a-z0-9]+]] = zext i16 [[USA]] to i32
+ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[EXT_USA]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i32 [[USA]], [[UA]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %ua, align 4
+ ua = usa + ua;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
+ // CHECK-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i16 [[USA]], [[EXT_USF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
+ usa = usa + usf;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[UF:%[0-9]+]] = load i16, i16* %uf, align 2
+ // CHECK-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i24
+ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8
+ // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i24 [[USA]], [[UF_EXT]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+ // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2
+ usa = usa + uf;
+}
+
+void IntAddition() {
+ // CHECK-LABEL: IntAddition
+ short _Accum sa;
+ _Accum a;
+ unsigned short _Accum usa;
+ _Sat short _Accum sa_sat;
+ int i;
+ unsigned int ui;
+ long _Fract lf;
+ _Bool b;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i39
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i39 [[SA_EXT]], [[I]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
+ sa = sa + i;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i40
+ // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i40
+ // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i40 [[UI_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i40 [[SA_EXT]], [[UI]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
+ sa = sa + ui;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
+ usa = usa + i;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = add i40 [[USA_EXT]], [[I]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = add i39 [[USA_EXT]], [[I]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
+ usa = usa + ui;
+
+ // CHECK: [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
+ // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[LF_EXT:%[a-z0-9]+]] = sext i32 [[LF]] to i64
+ // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i64
+ // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i64 [[UI_EXT]], 31
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i64 [[LF_EXT]], [[UI]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i64 [[SUM]] to i32
+ // CHECK-NEXT: store i32 [[RES]], i32* %lf, align 4
+ lf = lf + ui;
+
+ // CHECK: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[BOOL:%[0-9]+]] = load i8, i8* %b, align 1
+ // CHECK-NEXT: [[AS_BOOL:%[a-z0-9]+]] = trunc i8 [[BOOL]] to i1
+ // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = zext i1 [[AS_BOOL]] to i32
+ // CHECK-NEXT: [[ACCUM_EXT:%[a-z0-9]+]] = sext i32 [[ACCUM]] to i47
+ // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = sext i32 [[BOOL_EXT]] to i47
+ // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = shl i47 [[BOOL]], 15
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = add i47 [[ACCUM_EXT]], [[BOOL_EXT]]
+ // CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i47 [[SUM]] to i32
+ // CHECK-NEXT: store i32 [[RESULT]], i32* %a, align 4
+ a = a + b;
+}
+
+void SaturatedAddition() {
+ // CHECK-LABEL: SaturatedAddition
+ short _Accum sa;
+ _Accum a;
+ long _Accum la;
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ _Sat short _Accum sa_sat;
+ _Sat _Accum a_sat;
+ _Sat long _Accum la_sat;
+ _Sat unsigned short _Accum usa_sat;
+ _Sat unsigned _Accum ua_sat;
+ _Sat unsigned long _Accum ula_sat;
+ _Sat unsigned _Fract uf_sat;
+
+ int i;
+ unsigned int ui;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.sadd.sat.i16(i16 [[SA]], i16
+ // [[SA_SAT]])
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa_sat, align 2
+ sa_sat = sa + sa_sat;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
+ // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
+ // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
+ // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
+ // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+ usa_sat = usa + usa_sat;
+
+ // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32
+ // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.uadd.sat.i32(i32 [[UA]], i32 [[USA]])
+ // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
+ // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
+ // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.uadd.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
+ // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+ ua_sat = ua + usa_sat;
+
+ // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i39
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.sadd.sat.i39(i39 [[SA_SAT_EXT]], i39 [[I]])
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RES]], -32768
+ // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 -32768, i39 [[RES]]
+ // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i39 [[RES2]] to i16
+ // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
+ sa_sat = sa_sat + i;
+
+ // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i40
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.sadd.sat.i40(i40 [[SA_SAT_EXT]], i40 [[I]])
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 32767
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 32767, i40 [[SUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RES]], -32768
+ // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 -32768, i40 [[RES]]
+ // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i40 [[RES2]] to i16
+ // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
+ sa_sat = sa_sat + ui;
+
+ // CHECK: [[UF_SAT:%[0-9]+]] = load i16, i16* %uf_sat, align 2
+ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.uadd.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
+ // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
+ // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
+ // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.uadd.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
+ // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+ uf_sat = uf_sat + uf_sat;
+
+ // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // SIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i40
+ // SIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i40 [[I_RESIZE]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.uadd.sat.i40(i40 [[USA_SAT_RESIZE]], i40 [[I_UPSCALE]])
+ // SIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 65535
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 65535, i40 [[SUM]]
+ // SIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RESULT]], 0
+ // SIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 0, i40 [[RESULT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i40 [[RESULT2]] to i16
+ // UNSIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i39
+ // UNSIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i39 [[I_RESIZE]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.uadd.sat.i39(i39 [[USA_SAT_RESIZE]], i39 [[I_UPSCALE]])
+ // UNSIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
+ // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
+ // UNSIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RESULT]], 0
+ // UNSIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 0, i39 [[RESULT]]
+ // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i39 [[RESULT2]] to i16
+ // CHECK-NEXT: store i16 [[RESULT]], i16* %usa_sat, align 2
+ usa_sat = usa_sat + i;
+}
diff --git a/test/Frontend/fixed_point_comparisons.c b/test/Frontend/fixed_point_comparisons.c
new file mode 100644
index 0000000000..385d0c1352
--- /dev/null
+++ b/test/Frontend/fixed_point_comparisons.c
@@ -0,0 +1,378 @@
+// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNPADDED
+// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,PADDED
+
+// Fixed point against other fixed point
+_Bool b_eq_true = 2.5hk == 2.5uhk; // CHECK-DAG: @b_eq_true = {{.*}}global i8 1, align 1
+_Bool b_eq_false = 2.5hk == 2.4uhk; // CHECK-DAG: @b_eq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ne_true = 2.5hk != 2.4uhk; // CHECK-DAG: @b_ne_true = {{.*}}global i8 1, align 1
+_Bool b_ne_false = 2.5hk != 2.5uhk; // CHECK-DAG: @b_ne_false = {{.*}}global i8 0, align 1
+
+_Bool b_lt_true = 2.5hk < 2.75uhk; // CHECK-DAG: @b_lt_true = {{.*}}global i8 1, align 1
+_Bool b_lt_false = 2.5hk < 2.5uhk; // CHECK-DAG: @b_lt_false = {{.*}}global i8 0, align 1
+
+_Bool b_le_true = 2.5hk <= 2.75uhk; // CHECK-DAG: @b_le_true = {{.*}}global i8 1, align 1
+_Bool b_le_true2 = 2.5hk <= 2.5uhk; // CHECK-DAG: @b_le_true2 = {{.*}}global i8 1, align 1
+_Bool b_le_false = 2.5hk <= 2.4uhk; // CHECK-DAG: @b_le_false = {{.*}}global i8 0, align 1
+
+_Bool b_gt_true = 2.75hk > 2.5uhk; // CHECK-DAG: @b_gt_true = {{.*}}global i8 1, align 1
+_Bool b_gt_false = 2.75hk > 2.75uhk; // CHECK-DAG: @b_gt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ge_true = 2.75hk >= 2.5uhk; // CHECK-DAG: @b_ge_true = {{.*}}global i8 1, align 1
+_Bool b_ge_true2 = 2.75hk >= 2.75uhk; // CHECK-DAG: @b_ge_true2 = {{.*}}global i8 1, align 1
+_Bool b_ge_false = 2.5hk >= 2.75uhk; // CHECK-DAG: @b_ge_false = {{.*}}global i8 0, align 1
+
+// Fixed point against int
+_Bool b_ieq_true = 2.0hk == 2; // CHECK-DAG: @b_ieq_true = {{.*}}global i8 1, align 1
+_Bool b_ieq_false = 2.0hk == 3; // CHECK-DAG: @b_ieq_false = {{.*}}global i8 0, align 1
+
+_Bool b_ine_true = 2.0hk != 3; // CHECK-DAG: @b_ine_true = {{.*}}global i8 1, align 1
+_Bool b_ine_false = 2.0hk != 2; // CHECK-DAG: @b_ine_false = {{.*}}global i8 0, align 1
+
+_Bool b_ilt_true = 2.0hk < 3; // CHECK-DAG: @b_ilt_true = {{.*}}global i8 1, align 1
+_Bool b_ilt_false = 2.0hk < 2; // CHECK-DAG: @b_ilt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ile_true = 2.0hk <= 3; // CHECK-DAG: @b_ile_true = {{.*}}global i8 1, align 1
+_Bool b_ile_true2 = 2.0hk <= 2; // CHECK-DAG: @b_ile_true2 = {{.*}}global i8 1, align 1
+_Bool b_ile_false = 2.0hk <= 1; // CHECK-DAG: @b_ile_false = {{.*}}global i8 0, align 1
+
+_Bool b_igt_true = 2.0hk > 1; // CHECK-DAG: @b_igt_true = {{.*}}global i8 1, align 1
+_Bool b_igt_false = 2.0hk > 2; // CHECK-DAG: @b_igt_false = {{.*}}global i8 0, align 1
+
+_Bool b_ige_true = 2.0hk >= 1; // CHECK-DAG: @b_ige_true = {{.*}}global i8 1, align 1
+_Bool b_ige_true2 = 2.0hk >= 2; // CHECK-DAG: @b_ige_true2 = {{.*}}global i8 1, align 1
+_Bool b_ige_false = 2.0hk >= 3; // CHECK-DAG: @b_ige_false = {{.*}}global i8 0, align 1
+
+// Different signage
+// Since we can have different precisions, non powers of 2 fractions may have
+// different actual values when being compared.
+_Bool b_sne_true = 2.6hk != 2.6uhk;
+// UNPADDED-DAG: @b_sne_true = {{.*}}global i8 1, align 1
+// PADDED-DAG: @b_sne_true = {{.*}}global i8 0, align 1
+
+_Bool b_seq_true = 2.0hk == 2u; // CHECK-DAG: @b_seq_true = {{.*}}global i8 1, align 1
+_Bool b_seq_true2 = 2.0uhk == 2; // CHECK-DAG: @b_seq_true2 = {{.*}}global i8 1, align 1
+
+void TestComparisons() {
+ short _Accum sa;
+ _Accum a;
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+
+ // Each of these should be a fixed point conversion followed by the actual
+ // comparison operation.
+ sa == a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+ sa != a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp ne i32 [[UPSCALE_A]], [[A2]]
+
+ sa > a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp sgt i32 [[UPSCALE_A]], [[A2]]
+
+ sa >= a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp sge i32 [[UPSCALE_A]], [[A2]]
+
+ sa < a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp slt i32 [[UPSCALE_A]], [[A2]]
+
+ sa <= a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp sle i32 [[UPSCALE_A]], [[A2]]
+
+ usa > ua;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp ugt i32 [[UPSCALE_A]], [[A2]]
+
+ usa >= ua;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp uge i32 [[UPSCALE_A]], [[A2]]
+
+ usa < ua;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp ult i32 [[UPSCALE_A]], [[A2]]
+
+ usa <= ua;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp ule i32 [[UPSCALE_A]], [[A2]]
+}
+
+void TestIntComparisons() {
+ short _Accum sa;
+ unsigned short _Accum usa;
+
+ int i;
+ unsigned int ui;
+ _Bool b;
+ char c;
+ short s;
+ enum E {
+ A = 2
+ } e;
+
+ // These comparisons shouldn't be that different from comparing against fixed
+ // point types with other fixed point types.
+ sa == i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ sa != i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp ne i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ sa > i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp sgt i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ sa >= i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp sge i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ sa < i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp slt i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ sa <= i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp sle i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ usa > ui;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp ugt i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp ugt i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ usa >= ui;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp uge i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp uge i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ usa < ui;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp ult i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp ult i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ usa <= ui;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp ule i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp ule i39 [[RESIZE_A]], [[UPSCALE_I]]
+
+ // Allow for comparisons with other int like types. These are no different
+ // from comparing to an int other than varying sizes. The integer types are
+ // still converted to ints or unsigned ints from UsualUnaryConversions().
+ sa == b;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[B:%[0-9]+]] = load i8, i8* %b, align 1
+ // CHECK-NEXT: %tobool = trunc i8 [[B]] to i1
+ // CHECK-NEXT: [[CONV_B:%[a-z0-9]+]] = zext i1 %tobool to i32
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_B:%[a-z0-9]+]] = sext i32 [[CONV_B]] to i39
+ // CHECK-NEXT: [[UPSCALE_B:%[a-z0-9]+]] = shl i39 [[RESIZE_B]], 7
+ // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_B]]
+
+ sa == c;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[C:%[0-9]+]] = load i8, i8* %c, align 1
+ // CHECK-NEXT: [[CONV_C:%[a-z0-9]+]] = sext i8 [[C]] to i32
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_C:%[a-z0-9]+]] = sext i32 [[CONV_C]] to i39
+ // CHECK-NEXT: [[UPSCALE_C:%[a-z0-9]+]] = shl i39 [[RESIZE_C]], 7
+ // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_C]]
+
+ sa == s;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[S:%[0-9]+]] = load i16, i16* %s, align 2
+ // CHECK-NEXT: [[CONV_S:%[a-z0-9]+]] = sext i16 [[S]] to i32
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i39
+ // CHECK-NEXT: [[RESIZE_S:%[a-z0-9]+]] = sext i32 [[CONV_S]] to i39
+ // CHECK-NEXT: [[UPSCALE_S:%[a-z0-9]+]] = shl i39 [[RESIZE_S]], 7
+ // CHECK-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_S]]
+
+ // An enum value is IntegralCast to an unsigned int.
+ usa == e;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %e, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
+}
+
+void TestComparisonSignage() {
+ short _Accum sa;
+ unsigned short _Accum usa;
+ int i;
+ unsigned int ui;
+
+ // Signed vs unsigned fixed point comparison
+ sa == usa;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %usa, align 2
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
+ // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
+ // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
+ // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
+ // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
+
+ // Signed int vs unsigned fixed point
+ sa == ui;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i40
+ // CHECK-NEXT: [[RESIZE_I:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // CHECK-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 7
+ // CHECK-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
+
+ // Signed fixed point vs unsigned int
+ usa == i;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i40
+ // UNPADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // UNPADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i40 [[RESIZE_I]], 8
+ // UNPADDED-NEXT: {{.*}} = icmp eq i40 [[RESIZE_A]], [[UPSCALE_I]]
+ // PADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = zext i16 [[A]] to i39
+ // PADDED-NEXT: [[RESIZE_I:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // PADDED-NEXT: [[UPSCALE_I:%[a-z0-9]+]] = shl i39 [[RESIZE_I]], 7
+ // PADDED-NEXT: {{.*}} = icmp eq i39 [[RESIZE_A]], [[UPSCALE_I]]
+}
+
+void TestSaturationComparisons() {
+ short _Accum sa;
+ _Accum a;
+ _Sat short _Accum sat_sa;
+ _Sat _Accum sat_a;
+ _Sat unsigned short _Accum sat_usa;
+
+ // These are effectively the same as conversions with their non-saturating
+ // counterparts since when comparing, we convert both operands to a common
+ // type that should be able to hold both values.
+ sat_sa == sat_a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %sat_a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+ sat_sa == a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: {{.*}} = icmp eq i32 [[UPSCALE_A]], [[A2]]
+
+ sat_sa == sat_usa;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sat_sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i16, i16* %sat_usa, align 2
+ // UNPADDED-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i17
+ // UNPADDED-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i17 [[RESIZE_A]], 1
+ // UNPADDED-NEXT: [[RESIZE_A2:%[a-z0-9]+]] = zext i16 [[A2]] to i17
+ // UNPADDED-NEXT: {{.*}} = icmp eq i17 [[UPSCALE_A]], [[RESIZE_A2]]
+ // PADDED-NEXT: {{.*}} = icmp eq i16 [[A]], [[A2]]
+}
+
+void StoreBooleanResult() {
+ short _Accum sa;
+ _Accum a;
+ int res;
+
+ // Check that the result can properly be stored as an int.
+ res = sa == a;
+ // CHECK: [[A:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A2:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[RESIZE_A:%[a-z0-9]+]] = sext i16 [[A]] to i32
+ // CHECK-NEXT: [[UPSCALE_A:%[a-z0-9]+]] = shl i32 [[RESIZE_A]], 8
+ // CHECK-NEXT: [[RES:%[0-9]+]] = icmp eq i32 [[UPSCALE_A]], [[A2]]
+ // CHECK-NEXT: %conv = zext i1 [[RES]] to i32
+ // CHECK-NEXT: store i32 %conv, i32* %res, align 4
+}
diff --git a/test/Frontend/fixed_point_conversions.c b/test/Frontend/fixed_point_conversions.c
index 7e98fb1e13..86a687bdef 100644
--- a/test/Frontend/fixed_point_conversions.c
+++ b/test/Frontend/fixed_point_conversions.c
@@ -1,108 +1,179 @@
-// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s -check-prefix=DEFAULT
-// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - -fpadding-on-unsigned-fixed-point | FileCheck %s -check-prefix=SAME
+// 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
+
+// Between different fixed point types
+short _Accum sa_const = 2.5hk; // CHECK-DAG: @sa_const = {{.*}}global i16 320, align 2
+_Accum a_const = 2.5hk; // CHECK-DAG: @a_const = {{.*}}global i32 81920, align 4
+short _Accum sa_const2 = 2.5k; // CHECK-DAG: @sa_const2 = {{.*}}global i16 320, align 2
+
+short _Accum sa_from_f_const = 0.5r; // CHECK-DAG: sa_from_f_const = {{.*}}global i16 64, align 2
+_Fract f_from_sa_const = 0.5hk; // CHECK-DAG: f_from_sa_const = {{.*}}global i16 16384, align 2
+
+unsigned short _Accum usa_const = 2.5uk;
+unsigned _Accum ua_const = 2.5uhk;
+// SIGNED-DAG: @usa_const = {{.*}}global i16 640, align 2
+// SIGNED-DAG: @ua_const = {{.*}}global i32 163840, align 4
+// UNSIGNED-DAG: @usa_const = {{.*}}global i16 320, align 2
+// UNSIGNED-DAG: @ua_const = {{.*}}global i32 81920, align 4
+
+// FixedPoint to integer
+int i_const = -128.0hk; // CHECK-DAG: @i_const = {{.*}}global i32 -128, align 4
+int i_const2 = 128.0hk; // CHECK-DAG: @i_const2 = {{.*}}global i32 128, align 4
+int i_const3 = -128.0k; // CHECK-DAG: @i_const3 = {{.*}}global i32 -128, align 4
+int i_const4 = 128.0k; // CHECK-DAG: @i_const4 = {{.*}}global i32 128, align 4
+short s_const = -128.0k; // CHECK-DAG: @s_const = {{.*}}global i16 -128, align 2
+short s_const2 = 128.0k; // CHECK-DAG: @s_const2 = {{.*}}global i16 128, align 2
+
+// Integer to fixed point
+short _Accum sa_const5 = 2; // CHECK-DAG: @sa_const5 = {{.*}}global i16 256, align 2
+short _Accum sa_const6 = -2; // CHECK-DAG: @sa_const6 = {{.*}}global i16 -256, align 2
+short _Accum sa_const7 = -256; // CHECK-DAG: @sa_const7 = {{.*}}global i16 -32768, align 2
+
+// Signedness
+unsigned short _Accum usa_const2 = 2.5hk;
+// SIGNED-DAG: @usa_const2 = {{.*}}global i16 640, align 2
+// UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 320, align 2
+short _Accum sa_const3 = 2.5hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 320, align 2
+
+int i_const5 = 128.0uhk;
+unsigned int ui_const = 128.0hk;
+// CHECK-DAG: @i_const5 = {{.*}}global i32 128, align 4
+// CHECK-DAG: @ui_const = {{.*}}global i32 128, align 4
+
+short _Accum sa_const9 = 2u; // CHECK-DAG: @sa_const9 = {{.*}}global i16 256, align 2
+unsigned short _Accum usa_const3 = 2;
+// SIGNED-DAG: @usa_const3 = {{.*}}global i16 512, align 2
+// UNSIGNED-DAG: @usa_const3 = {{.*}}global i16 256, align 2
+
+// Overflow (this is undefined but allowed)
+short _Accum sa_const4 = 256.0k;
+unsigned int ui_const2 = -2.5hk;
+short _Accum sa_const8 = 256;
+unsigned short _Accum usa_const4 = -2;
+
+// Saturation
+_Sat short _Accum sat_sa_const = 2.5hk; // CHECK-DAG: @sat_sa_const = {{.*}}global i16 320, align 2
+_Sat short _Accum sat_sa_const2 = 256.0k; // CHECK-DAG: @sat_sa_const2 = {{.*}}global i16 32767, align 2
+_Sat unsigned short _Accum sat_usa_const = -1.0hk;
+// CHECK-DAG: @sat_usa_const = {{.*}}global i16 0, align 2
+_Sat unsigned short _Accum sat_usa_const2 = 256.0k;
+// SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 -1, align 2
+// UNSIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 32767, align 2
+
+_Sat short _Accum sat_sa_const3 = 256; // CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 32767, align 2
+_Sat short _Accum sat_sa_const4 = -257; // CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
+_Sat unsigned short _Accum sat_usa_const3 = -1;
+// CHECK-DAG: @sat_usa_const3 = {{.*}}global i16 0, align 2
+_Sat unsigned short _Accum sat_usa_const4 = 256;
+// SIGNED-DAG: @sat_usa_const4 = {{.*}}global i16 -1, align 2
+// UNSIGNED-DAG: @sat_usa_const4 = {{.*}}global i16 32767, align 2
void TestFixedPointCastSameType() {
_Accum a = 2.5k;
_Accum a2 = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
a2 = (_Accum)a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a2, align 4
}
void TestFixedPointCastDown() {
long _Accum la = 2.5lk;
_Accum a = la;
- // DEFAULT: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
- // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
+ // CHECK-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
a = (_Accum)la;
- // DEFAULT: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
- // DEFAULT-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[LACCUM:%[0-9a-z]+]] = load i64, i64* %la, align 8
+ // CHECK-NEXT: [[ACCUM_AS_I64:%[0-9a-z]+]] = ashr i64 [[LACCUM]], 16
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i64 [[ACCUM_AS_I64]] to i32
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
short _Accum sa = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
- // DEFAULT-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
- // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // CHECK-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+ // CHECK-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
sa = (short _Accum)a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
- // DEFAULT-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
- // DEFAULT-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[SACCUM_AS_I32:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // CHECK-NEXT: [[SACCUM:%[0-9a-z]+]] = trunc i32 [[SACCUM_AS_I32]] to i16
+ // CHECK-NEXT: store i16 [[SACCUM]], i16* %sa, align 2
}
void TestFixedPointCastUp() {
short _Accum sa = 2.5hk;
_Accum a = sa;
- // DEFAULT: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
- // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
long _Accum la = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
- // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
- // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // CHECK-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
+ // CHECK-NEXT: store i64 [[LACCUM]], i64* %la, align 8
a = (_Accum)sa;
- // DEFAULT: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
- // DEFAULT-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[SACCUM:%[0-9a-z]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SACCUM_BUFF:%[0-9a-z]+]] = sext i16 [[SACCUM]] to i32
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[SACCUM_BUFF]], 8
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
la = (long _Accum)a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
- // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
- // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %la, align 8
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[ACCUM_BUFF:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // CHECK-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_BUFF]], 16
+ // CHECK-NEXT: store i64 [[LACCUM]], i64* %la, align 8
}
void TestFixedPointCastSignedness() {
_Accum a = 2.5k;
unsigned _Accum ua = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
- // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
- // SAME: TestFixedPointCastSignedness
- // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
+ // SIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // SIGNED-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
+ // SIGNED-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
+ // UNSIGNED: TestFixedPointCastSignedness
+ // UNSIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // UNSIGNED-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
a = ua;
- // DEFAULT: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
- // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
- // SAME-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // SIGNED: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // SIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
+ // SIGNED-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // UNSIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // UNSIGNED-NEXT: store i32 [[ACCUM]], i32* %a, align 4
ua = (unsigned _Accum)a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
- // DEFAULT-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
+ // SIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // SIGNED-NEXT: [[UACCUM:%[0-9a-z]+]] = shl i32 [[ACCUM]], 1
+ // SIGNED-NEXT: store i32 [[UACCUM]], i32* %ua, align 4
+ // UNSIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // UNSIGNED-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
a = (_Accum)ua;
- // DEFAULT: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // SIGNED: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // SIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = lshr i32 [[UACCUM]], 1
+ // SIGNED-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // UNSIGNED: [[UACCUM:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // UNSIGNED-NEXT: store i32 [[UACCUM]], i32* %a, align 4
_Accum a2;
unsigned long _Accum ula = a2;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
- // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
- // DEFAULT-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 17
- // DEFAULT-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
- // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
- // SAME-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
- // SAME-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 16
- // SAME-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
+ // SIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
+ // SIGNED-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // SIGNED-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 17
+ // SIGNED-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
+ // UNSIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a2, align 4
+ // UNSIGNED-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[ACCUM]] to i64
+ // UNSIGNED-NEXT: [[LACCUM:%[0-9a-z]+]] = shl i64 [[ACCUM_EXT]], 16
+ // UNSIGNED-NEXT: store i64 [[LACCUM]], i64* %ula, align 8
}
void TestFixedPointCastSaturation() {
@@ -119,114 +190,112 @@ void TestFixedPointCastSaturation() {
// Casting down between types
sat_sa = sat_a;
- // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
- // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
- // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_sa, align 2
+ // CHECK: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // CHECK-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // CHECK-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
+ // CHECK-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
+ // CHECK-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // CHECK-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_sa, align 2
// Accum to Fract, decreasing scale
sat_sf = sat_a;
- // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
- // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[FRACT]], 127
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 127, i32 [[FRACT]]
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -128
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -128, i32 [[RESULT]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i8
- // DEFAULT-NEXT: store i8 [[RESULT_TRUNC]], i8* %sat_sf, align 1
+ // CHECK: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // CHECK-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // CHECK-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[FRACT]], 127
+ // CHECK-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 127, i32 [[FRACT]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -128
+ // CHECK-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -128, i32 [[RESULT]]
+ // CHECK-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i8
+ // CHECK-NEXT: store i8 [[RESULT_TRUNC]], i8* %sat_sf, align 1
// Accum to Fract, same scale
sat_f = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
- // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_f, align 2
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // CHECK-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], -32768
+ // CHECK-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 -32768, i32 [[RESULT]]
+ // CHECK-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // CHECK-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_f, align 2
// Accum to Fract, increasing scale
sat_lf = sat_a;
- // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i48
- // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = shl i48 [[ACCUM]], 16
- // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i48 [[FRACT]], 2147483647
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i48 2147483647, i48 [[FRACT]]
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i48 [[RESULT]], -2147483648
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i48 -2147483648, i48 [[RESULT]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i48 [[RESULT2]] to i32
- // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_lf, align 4
+ // CHECK: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // CHECK-NEXT: [[RESIZE:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i48
+ // CHECK-NEXT: [[FRACT:%[0-9a-z]+]] = shl i48 [[RESIZE]], 16
+ // CHECK-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i48 [[FRACT]], 2147483647
+ // CHECK-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i48 2147483647, i48 [[FRACT]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i48 [[RESULT]], -2147483648
+ // CHECK-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i48 -2147483648, i48 [[RESULT]]
+ // CHECK-NEXT: [[TRUNC:%[0-9a-z]+]] = trunc i48 [[RESULT2]] to i32
+ // CHECK-NEXT: store i32 [[TRUNC]], i32* %sat_lf, align 4
// Signed to unsigned, decreasing scale
_Sat _Accum sat_a2;
sat_usa = sat_a2;
- // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 7
- // DEFAULT-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 65535
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 65535, i32 [[ACCUM]]
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
- // DEFAULT-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
- // SAME: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
- // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
- // SAME-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
- // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
- // SAME-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
- // SAME-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
- // SAME-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
- // SAME-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
+ // SIGNED: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
+ // SIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 7
+ // SIGNED-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 65535
+ // SIGNED-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 65535, i32 [[ACCUM]]
+ // SIGNED-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
+ // SIGNED-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
+ // SIGNED-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // SIGNED-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
+ // UNSIGNED: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a2, align 4
+ // UNSIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = ashr i32 [[OLD_ACCUM]], 8
+ // UNSIGNED-NEXT: [[USE_MAX:%[0-9a-z]+]] = icmp sgt i32 [[ACCUM]], 32767
+ // UNSIGNED-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MAX]], i32 32767, i32 [[ACCUM]]
+ // UNSIGNED-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[RESULT]], 0
+ // UNSIGNED-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[RESULT]]
+ // UNSIGNED-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i32 [[RESULT2]] to i16
+ // UNSIGNED-NEXT: store i16 [[RESULT_TRUNC]], i16* %sat_usa, align 2
// Signed to unsigned, increasing scale
sat_ua = sat_a;
- // DEFAULT: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // DEFAULT-NEXT: [[ACCUM_EXT:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i33
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i33 [[ACCUM_EXT]], 1
- // DEFAULT-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i33 [[ACCUM]], 0
- // DEFAULT-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i33 0, i33 [[ACCUM]]
- // DEFAULT-NEXT: [[RESULT_TRUNC:%[0-9a-z]+]] = trunc i33 [[RESULT2]] to i32
- // DEFAULT-NEXT: store i32 [[RESULT_TRUNC]], i32* %sat_ua, align 4
- // SAME: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // SAME-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0
- // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]]
- // SAME-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
+ // SIGNED: [[OLD_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // SIGNED-NEXT: [[RESIZE:%[0-9a-z]+]] = sext i32 [[OLD_ACCUM]] to i33
+ // SIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i33 [[RESIZE]], 1
+ // SIGNED-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i33 [[ACCUM]], 0
+ // SIGNED-NEXT: [[RESULT2:%[0-9a-z]+]] = select i1 [[USE_MIN]], i33 0, i33 [[ACCUM]]
+ // SIGNED-NEXT: [[TRUNC:%[0-9a-z]+]] = trunc i33 [[RESULT2]] to i32
+ // SIGNED-NEXT: store i32 [[TRUNC]], i32* %sat_ua, align 4
+ // UNSIGNED: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // UNSIGNED-NEXT: [[USE_MIN:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0
+ // UNSIGNED-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[USE_MIN]], i32 0, i32 [[ACCUM]]
+ // UNSIGNED-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
// Nothing when saturating to the same type and size
sat_a = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %sat_a, align 4
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %sat_a, align 4
// Nothing when assigning back
a = sat_a;
- // DEFAULT: [[SAT_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
- // DEFAULT-NEXT: store i32 [[SAT_ACCUM]], i32* %a, align 4
+ // CHECK: [[SAT_ACCUM:%[0-9a-z]+]] = load i32, i32* %sat_a, align 4
+ // CHECK-NEXT: store i32 [[SAT_ACCUM]], i32* %a, align 4
// No overflow when casting from fract to signed accum
sat_a = sat_f;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %sat_f, align 2
- // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
- // DEFAULT-NEXT: store i32 [[FRACT_EXT]], i32* %sat_a, align 4
+ // CHECK: [[FRACT:%[0-9a-z]+]] = load i16, i16* %sat_f, align 2
+ // CHECK-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
+ // CHECK-NEXT: store i32 [[FRACT_EXT]], i32* %sat_a, align 4
// Only get overflow checking if signed fract to unsigned accum
sat_ua = sat_sf;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
- // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i17
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i17 [[FRACT_EXT]], 9
- // DEFAULT-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i17 [[ACCUM]], 0
- // DEFAULT-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i17 0, i17 [[ACCUM]]
- // DEFAULT-NEXT: [[RESULT_EXT:%[0-9a-z]+]] = sext i17 [[RESULT]] to i32
- // DEFAULT-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
- // SAME: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
- // SAME-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i16
- // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i16 [[FRACT_EXT]], 8
- // SAME-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i16 [[ACCUM]], 0
- // SAME-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i16 0, i16 [[ACCUM]]
- // SAME-NEXT: [[RESULT_EXT:%[0-9a-z]+]] = sext i16 [[RESULT]] to i32
- // SAME-NEXT: store i32 [[RESULT_EXT]], i32* %sat_ua, align 4
+ // SIGNED: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
+ // SIGNED-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i32
+ // SIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[FRACT_EXT]], 9
+ // SIGNED-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0
+ // SIGNED-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i32 0, i32 [[ACCUM]]
+ // SIGNED-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
+ // UNSIGNED: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sat_sf, align 1
+ // UNSIGNED-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i32
+ // UNSIGNED-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[FRACT_EXT]], 8
+ // UNSIGNED-NEXT: [[IS_NEG:%[0-9a-z]+]] = icmp slt i32 [[ACCUM]], 0
+ // UNSIGNED-NEXT: [[RESULT:%[0-9a-z]+]] = select i1 [[IS_NEG]], i32 0, i32 [[ACCUM]]
+ // UNSIGNED-NEXT: store i32 [[RESULT]], i32* %sat_ua, align 4
}
void TestFixedPointCastBetFractAccum() {
@@ -241,43 +310,176 @@ void TestFixedPointCastBetFractAccum() {
// To lower scale
sf = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
- // DEFAULT-NEXT: [[FRACT_TRUNC:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i8
- // DEFAULT-NEXT: store i8 [[FRACT_TRUNC]], i8* %sf, align 1
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[FRACT:%[0-9a-z]+]] = ashr i32 [[ACCUM]], 8
+ // CHECK-NEXT: [[FRACT_TRUNC:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i8
+ // CHECK-NEXT: store i8 [[FRACT_TRUNC]], i8* %sf, align 1
// To higher scale
a = sf;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sf, align 1
- // DEFAULT-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i32
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[FRACT_EXT]], 8
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[FRACT:%[0-9a-z]+]] = load i8, i8* %sf, align 1
+ // CHECK-NEXT: [[FRACT_EXT:%[0-9a-z]+]] = sext i8 [[FRACT]] to i32
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = shl i32 [[FRACT_EXT]], 8
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
// To same scale
f = a;
- // DEFAULT: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
- // DEFAULT-NEXT: [[FRACT:%[0-9a-z]+]] = trunc i32 [[ACCUM]] to i16
- // DEFAULT-NEXT: store i16 [[FRACT]], i16* %f, align 2
+ // CHECK: [[ACCUM:%[0-9a-z]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[FRACT:%[0-9a-z]+]] = trunc i32 [[ACCUM]] to i16
+ // CHECK-NEXT: store i16 [[FRACT]], i16* %f, align 2
a = f;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %f, align 2
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %a, align 4
+ // CHECK: [[FRACT:%[0-9a-z]+]] = load i16, i16* %f, align 2
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = sext i16 [[FRACT]] to i32
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %a, align 4
// To unsigned
ua = uf;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i16, i16* %uf, align 2
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = zext i16 [[FRACT]] to i32
- // DEFAULT-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
- // SAME: [[FRACT:%[0-9a-z]+]] = load i16, i16* %uf, align 2
- // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = zext i16 [[FRACT]] to i32
- // SAME-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
+ // CHECK: [[FRACT:%[0-9a-z]+]] = load i16, i16* %uf, align 2
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = zext i16 [[FRACT]] to i32
+ // CHECK-NEXT: store i32 [[ACCUM]], i32* %ua, align 4
uf = ua;
- // DEFAULT: [[FRACT:%[0-9a-z]+]] = load i32, i32* %ua, align 4
- // DEFAULT-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i16
- // DEFAULT-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
- // SAME: [[FRACT:%[0-9a-z]+]] = load i32, i32* %ua, align 4
- // SAME-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i16
- // SAME-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
+ // CHECK: [[FRACT:%[0-9a-z]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[ACCUM:%[0-9a-z]+]] = trunc i32 [[FRACT]] to i16
+ // CHECK-NEXT: store i16 [[ACCUM]], i16* %uf, align 2
+}
+
+void TestFixedPointToInt() {
+ int i;
+ short _Accum sa;
+ unsigned short _Accum usa;
+
+ // Will need to check for negative values
+ i = sa;
+ // CHECK: [[FX:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[NEG:%[0-9]+]] = icmp slt i16 [[FX]], 0
+ // CHECK-NEXT: [[ROUNDED:%[0-9]+]] = add i16 [[FX]], 127
+ // CHECK-NEXT: [[VAL:%[0-9]+]] = select i1 [[NEG]], i16 [[ROUNDED]], i16 [[FX]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i16 [[VAL]], 7
+ // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = sext i16 [[RES]] to i32
+ // CHECK-NEXT: store i32 [[RES2]], i32* %i, align 4
+
+ // No check needed for unsigned fixed points. Can just right shift.
+ i = usa;
+ // SIGNED: [[FX:%[0-9]+]] = load i16, i16* %usa, align 2
+ // SIGNED-NEXT: [[INT:%[a-z0-9]+]] = lshr i16 [[FX]], 8
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = zext i16 [[INT]] to i32
+ // SIGNED-NEXT: store i32 [[RES]], i32* %i, align 4
+ // UNSIGNED: [[FX:%[0-9]+]] = load i16, i16* %usa, align 2
+ // UNSIGNED-NEXT: [[INT:%[a-z0-9]+]] = lshr i16 [[FX]], 7
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = zext i16 [[INT]] to i32
+ // UNSIGNED-NEXT: store i32 [[RES]], i32* %i, align 4
+}
+
+void TestIntToFixedPoint() {
+ short s;
+ int i, i2;
+ unsigned int ui;
+ short _Accum sa;
+ long _Accum la;
+ unsigned short _Accum usa;
+ _Sat short _Accum sat_sa;
+ _Sat unsigned short _Accum sat_usa;
+
+ sa = i;
+ // CHECK: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // CHECK-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 7
+ // CHECK-NEXT: store i16 [[FX]], i16* %sa, align 2
+
+ sa = ui;
+ // CHECK: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // CHECK-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 7
+ // CHECK-NEXT: store i16 [[FX]], i16* %sa, align 2
+
+ usa = i2;
+ // SIGNED: [[I:%[0-9]+]] = load i32, i32* %i2, align 4
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // SIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 8
+ // SIGNED-NEXT: store i16 [[FX]], i16* %usa, align 2
+ // UNSIGNED: [[I:%[0-9]+]] = load i32, i32* %i2, align 4
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // UNSIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 7
+ // UNSIGNED-NEXT: store i16 [[FX]], i16* %usa, align 2
+
+ usa = ui;
+ // SIGNED: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // SIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 8
+ // SIGNED-NEXT: store i16 [[FX]], i16* %usa, align 2
+ // UNSIGNED: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = trunc i32 [[I]] to i16
+ // UNSIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i16 [[I_EXT]], 7
+ // UNSIGNED-NEXT: store i16 [[FX]], i16* %usa, align 2
+
+ la = s;
+ // CHECK: [[I:%[0-9]+]] = load i16, i16* %s, align 2
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i16 [[I]] to i64
+ // CHECK-NEXT: [[FX:%[a-z0-9]+]] = shl i64 [[I_EXT]], 31
+ // CHECK-NEXT: store i64 [[FX]], i64* %la, align 8
+}
+
+void TestIntToSatFixedPoint() {
+ int i, i2;
+ unsigned int ui;
+ _Sat short _Accum sat_sa;
+ _Sat unsigned short _Accum sat_usa;
+
+ sat_sa = i;
+ // CHECK: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[FX:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[FX]], 32767
+ // CHECK-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[FX]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[SATMAX]], -32768
+ // CHECK-NEXT: [[SATMIN:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 -32768, i39 [[SATMAX]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SATMIN]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sat_sa, align 2
+
+ sat_sa = ui;
+ // CHECK: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // CHECK-NEXT: [[FX:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp ugt i39 [[FX]], 32767
+ // CHECK-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[FX]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SATMAX]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sat_sa, align 2
+
+ sat_usa = i2;
+ // SIGNED: [[I:%[0-9]+]] = load i32, i32* %i2, align 4
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // SIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[FX]], 65535
+ // SIGNED-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 65535, i40 [[FX]]
+ // SIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[SATMAX]], 0
+ // SIGNED-NEXT: [[SATMIN:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 0, i40 [[SATMAX]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SATMIN]] to i16
+ // SIGNED-NEXT: store i16 [[RES]], i16* %sat_usa, align 2
+ // UNSIGNED: [[I:%[0-9]+]] = load i32, i32* %i2, align 4
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[FX]], 32767
+ // UNSIGNED-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[FX]]
+ // UNSIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[SATMAX]], 0
+ // UNSIGNED-NEXT: [[SATMIN:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 0, i39 [[SATMAX]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SATMIN]] to i16
+ // UNSIGNED-NEXT: store i16 [[RES]], i16* %sat_usa, align 2
+
+ sat_usa = ui;
+ // SIGNED: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // SIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp ugt i40 [[FX]], 65535
+ // SIGNED-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 65535, i40 [[FX]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SATMAX]] to i16
+ // SIGNED-NEXT: store i16 [[RES]], i16* %sat_usa, align 2
+ // UNSIGNED: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[FX:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp ugt i39 [[FX]], 32767
+ // UNSIGNED-NEXT: [[SATMAX:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[FX]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SATMAX]] to i16
+ // UNSIGNED-NEXT: store i16 [[RES]], i16* %sat_usa, align 2
}
diff --git a/test/Frontend/fixed_point_errors.c b/test/Frontend/fixed_point_errors.c
index 41427e3431..db15bd874b 100644
--- a/test/Frontend/fixed_point_errors.c
+++ b/test/Frontend/fixed_point_errors.c
@@ -232,3 +232,21 @@ void CheckSuffixOnIntegerLiterals() {
auto auto_accum = 0k; // expected-error{{invalid suffix 'k' on integer constant}}
// expected-warning@-1{{type specifier missing, defaults to 'int'}}
}
+
+// Ok conversions
+int i_const = -2.5hk;
+_Sat short _Accum sat_sa_const2 = 256.0k;
+_Sat unsigned short _Accum sat_usa_const = -1.0hk;
+short _Accum sa_const3 = 2;
+short _Accum sa_const4 = -2;
+
+// Overflow
+short _Accum sa_const = 256.0k; // expected-warning{{implicit conversion from 256.0 cannot fit within the range of values for 'short _Accum'}}
+short _Fract sf_const = 1.0hk; // expected-warning{{implicit conversion from 1.0 cannot fit within the range of values for 'short _Fract'}}
+unsigned _Accum ua_const = -1.0k; // expected-warning{{implicit conversion from -1.0 cannot fit within the range of values for 'unsigned _Accum'}}
+short _Accum sa_const2 = 128.0k + 128.0k; // expected-warning{{implicit conversion from 256.0 cannot fit within the range of values for 'short _Accum'}}
+short s_const = 65536.0lk; // expected-warning{{implicit conversion from 65536.0 cannot fit within the range of values for 'short'}}
+unsigned u_const = -2.5hk; // expected-warning{{implicit conversion from -2.5 cannot fit within the range of values for 'unsigned int'}}
+char c_const = 256.0uk; // expected-warning{{implicit conversion from 256.0 cannot fit within the range of values for 'char'}}
+short _Accum sa_const5 = 256; // expected-warning{{implicit conversion from 256 cannot fit within the range of values for 'short _Accum'}}
+unsigned short _Accum usa_const2 = -2; // expected-warning{{implicit conversion from -2 cannot fit within the range of values for 'unsigned short _Accum'}}
diff --git a/test/Frontend/fixed_point_sub.c b/test/Frontend/fixed_point_sub.c
new file mode 100644
index 0000000000..59b2e0a43a
--- /dev/null
+++ b/test/Frontend/fixed_point_sub.c
@@ -0,0 +1,390 @@
+// RUN: %clang_cc1 -ffixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
+// RUN: %clang_cc1 -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
+
+void SignedSubtraction() {
+ // CHECK-LABEL: SignedSubtraction
+ short _Accum sa;
+ _Accum a, b, c, d;
+ long _Accum la;
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ short _Fract sf;
+ _Fract f;
+ long _Fract lf;
+ unsigned short _Fract usf;
+ unsigned _Fract uf;
+ unsigned long _Fract ulf;
+
+ // Same type
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SA2:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i16 [[SA]], [[SA2]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa - sa;
+
+ // To larger scale and larger width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
+ // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i32 [[SA]], [[A]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = sa - a;
+
+ // To same scale and smaller width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
+ // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i16
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i16 [[SA]], [[EXT_SF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa - sf;
+
+ // To smaller scale and same width.
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[F:%[0-9]+]] = load i16, i16* %f, align 2
+ // CHECK-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i24
+ // CHECK-NEXT: [[SA:%[a-z0-9]+]] = shl i24 [[EXT_SA]], 8
+ // CHECK-NEXT: [[EXT_F:%[a-z0-9]+]] = sext i16 [[F]] to i24
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i24 [[SA]], [[EXT_F]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i24 [[SUM]], 8
+ // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[TRUNC_RES]], i16* %sa, align 2
+ sa = sa - f;
+
+ // To smaller scale and smaller width
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[SF:%[0-9]+]] = load i8, i8* %sf, align 1
+ // CHECK-NEXT: [[EXT_SF:%[a-z0-9]+]] = sext i8 [[SF]] to i32
+ // CHECK-NEXT: [[SF:%[a-z0-9]+]] = shl i32 [[EXT_SF]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i32 [[A]], [[SF]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = a - sf;
+
+ // To larger scale and same width
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
+ // CHECK-NEXT: [[EXT_A:%[a-z0-9]+]] = sext i32 [[A]] to i48
+ // CHECK-NEXT: [[A:%[a-z0-9]+]] = shl i48 [[EXT_A]], 16
+ // CHECK-NEXT: [[EXT_LF:%[a-z0-9]+]] = sext i32 [[LF]] to i48
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i48 [[A]], [[EXT_LF]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = ashr i48 [[SUM]], 16
+ // CHECK-NEXT: [[TRUNC_RES:%[a-z0-9]+]] = trunc i48 [[RES]] to i32
+ // CHECK-NEXT: store i32 [[TRUNC_RES]], i32* %a, align 4
+ a = a - lf;
+
+ // With corresponding unsigned type
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i17
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i17 [[SA]], [[USA_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i16 [[SA]], [[USA]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa - usa;
+
+ // With unsigned of larger scale
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i33
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i33 [[SA_EXT]], 9
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i32 [[USA]] to i33
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i33 [[SA]], [[USA_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i33 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i33 [[RESULT]] to i32
+ // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i32
+ // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i32 [[EXT_SA]], 8
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i32 [[SA]], [[USA]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %a, align 4
+ a = sa - ua;
+
+ // With unsigned of smaller width
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i17
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i17 [[SA_EXT]], 1
+ // SIGNED-NEXT: [[USF_EXT:%[a-z0-9]+]] = zext i8 [[USF]] to i17
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i17 [[SA]], [[USF_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i17 [[SUM]], 1
+ // SIGNED-NEXT: [[SUM:%[a-z0-9]+]] = trunc i17 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i16 [[SA]], [[EXT_USF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa, align 2
+ sa = sa - usf;
+
+ // With unsigned of larger width and smaller scale
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[ULF:%[0-9]+]] = load i32, i32* %ulf, align 4
+ // SIGNED-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i41
+ // SIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i41 [[SA_EXT]], 25
+ // SIGNED-NEXT: [[ULF_EXT:%[a-z0-9]+]] = zext i32 [[ULF]] to i41
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i41 [[SA]], [[ULF_EXT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = ashr i41 [[SUM]], 25
+ // SIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i41 [[RESULT]] to i16
+ // UNSIGNED-NEXT: [[EXT_SA:%[a-z0-9]+]] = sext i16 [[SA]] to i40
+ // UNSIGNED-NEXT: [[SA:%[a-z0-9]+]] = shl i40 [[EXT_SA]], 24
+ // UNSIGNED-NEXT: [[EXT_ULF:%[a-z0-9]+]] = zext i32 [[ULF]] to i40
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[SA]], [[EXT_ULF]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = ashr i40 [[SUM]], 24
+ // UNSIGNED-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i40 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %sa, align 2
+ sa = sa - ulf;
+
+ // Chained additions of the same signed type should result in the same
+ // semantics width.
+ // CHECK: [[A:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[B:%[0-9]+]] = load i32, i32* %b, align 4
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i32 [[A]], [[B]]
+ // CHECK-NEXT: [[C:%[0-9]+]] = load i32, i32* %c, align 4
+ // CHECK-NEXT: [[SUM2:%[0-9]+]] = sub i32 [[SUM]], [[C]]
+ // CHECK-NEXT: [[D:%[0-9]+]] = load i32, i32* %d, align 4
+ // CHECK-NEXT: [[SUM3:%[0-9]+]] = sub i32 [[SUM2]], [[D]]
+ // CHECK-NEXT: store i32 [[SUM3]], i32* %a, align 4
+ a = a - b - c - d;
+}
+
+void UnsignedSubtraction() {
+ // CHECK-LABEL: UnsignedSubtraction
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ unsigned short _Fract usf;
+ unsigned _Fract uf;
+ unsigned long _Fract ulf;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USA2:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i16 [[USA]], [[USA2]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
+ usa = usa - usa;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[EXT_USA:%[a-z0-9]+]] = zext i16 [[USA]] to i32
+ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[EXT_USA]], 8
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i32 [[USA]], [[UA]]
+ // CHECK-NEXT: store i32 [[SUM]], i32* %ua, align 4
+ ua = usa - ua;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USF:%[0-9]+]] = load i8, i8* %usf, align 1
+ // CHECK-NEXT: [[EXT_USF:%[a-z0-9]+]] = zext i8 [[USF]] to i16
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i16 [[USA]], [[EXT_USF]]
+ // CHECK-NEXT: store i16 [[SUM]], i16* %usa, align 2
+ usa = usa - usf;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[UF:%[0-9]+]] = load i16, i16* %uf, align 2
+ // CHECK-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i24
+ // CHECK-NEXT: [[USA:%[a-z0-9]+]] = shl i24 [[USA_EXT]], 8
+ // CHECK-NEXT: [[UF_EXT:%[a-z0-9]+]] = zext i16 [[UF]] to i24
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i24 [[USA]], [[UF_EXT]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = lshr i24 [[SUM]], 8
+ // CHECK-NEXT: [[RES_TRUNC:%[a-z0-9]+]] = trunc i24 [[RES]] to i16
+ // CHECK-NEXT: store i16 [[RES_TRUNC]], i16* %usa, align 2
+ usa = usa - uf;
+}
+
+void IntSubtraction() {
+ // CHECK-LABEL: IntSubtraction
+ short _Accum sa;
+ _Accum a;
+ unsigned short _Accum usa;
+ _Sat short _Accum sa_sat;
+ int i;
+ unsigned int ui;
+ long _Fract lf;
+ _Bool b;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i39
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i39 [[SA_EXT]], [[I]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
+ sa = sa - i;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[SA_EXT:%[a-z0-9]+]] = sext i16 [[SA]] to i40
+ // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i40
+ // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i40 [[UI_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i40 [[SA_EXT]], [[UI]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %sa, align 2
+ sa = sa - ui;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i39 [[USA_EXT]], [[I]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
+ usa = usa - i;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i40
+ // SIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = sub i40 [[USA_EXT]], [[I]]
+ // SIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i40 [[SUM]] to i16
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i39
+ // UNSIGNED-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = sub i39 [[USA_EXT]], [[I]]
+ // UNSIGNED-NEXT: [[RES:%[a-z0-9]+]] = trunc i39 [[SUM]] to i16
+ // CHECK-NEXT: store i16 [[RES]], i16* %usa, align 2
+ usa = usa - ui;
+
+ // CHECK: [[LF:%[0-9]+]] = load i32, i32* %lf, align 4
+ // CHECK-NEXT: [[UI:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[LF_EXT:%[a-z0-9]+]] = sext i32 [[LF]] to i64
+ // CHECK-NEXT: [[UI_EXT:%[a-z0-9]+]] = zext i32 [[UI]] to i64
+ // CHECK-NEXT: [[UI:%[a-z0-9]+]] = shl i64 [[UI_EXT]], 31
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i64 [[LF_EXT]], [[UI]]
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = trunc i64 [[SUM]] to i32
+ // CHECK-NEXT: store i32 [[RES]], i32* %lf, align 4
+ lf = lf - ui;
+
+ // CHECK: [[ACCUM:%[0-9]+]] = load i32, i32* %a, align 4
+ // CHECK-NEXT: [[BOOL:%[0-9]+]] = load i8, i8* %b, align 1
+ // CHECK-NEXT: [[AS_BOOL:%[a-z0-9]+]] = trunc i8 [[BOOL]] to i1
+ // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = zext i1 [[AS_BOOL]] to i32
+ // CHECK-NEXT: [[ACCUM_EXT:%[a-z0-9]+]] = sext i32 [[ACCUM]] to i47
+ // CHECK-NEXT: [[BOOL:%[a-z0-9]+]] = sext i32 [[BOOL_EXT]] to i47
+ // CHECK-NEXT: [[BOOL_EXT:%[a-z0-9]+]] = shl i47 [[BOOL]], 15
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = sub i47 [[ACCUM_EXT]], [[BOOL_EXT]]
+ // CHECK-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i47 [[SUM]] to i32
+ // CHECK-NEXT: store i32 [[RESULT]], i32* %a, align 4
+ a = a - b;
+}
+
+void SaturatedSubtraction() {
+ // CHECK-LABEL: SaturatedSubtraction
+ short _Accum sa;
+ _Accum a;
+ long _Accum la;
+ unsigned short _Accum usa;
+ unsigned _Accum ua;
+ unsigned long _Accum ula;
+
+ _Sat short _Accum sa_sat;
+ _Sat _Accum a_sat;
+ _Sat long _Accum la_sat;
+ _Sat unsigned short _Accum usa_sat;
+ _Sat unsigned _Accum ua_sat;
+ _Sat unsigned long _Accum ula_sat;
+ _Sat unsigned _Fract uf_sat;
+
+ int i;
+ unsigned int ui;
+
+ // CHECK: [[SA:%[0-9]+]] = load i16, i16* %sa, align 2
+ // CHECK-NEXT: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.ssub.sat.i16(i16 [[SA]], i16
+ // [[SA_SAT]])
+ // CHECK-NEXT: store i16 [[SUM]], i16* %sa_sat, align 2
+ sa_sat = sa - sa_sat;
+
+ // CHECK: [[USA:%[0-9]+]] = load i16, i16* %usa, align 2
+ // CHECK-NEXT: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[USA]], i16 [[USA_SAT]])
+ // SIGNED-NEXT: store i16 [[SUM]], i16* %usa_sat, align 2
+ // UNSIGNED-NEXT: [[USA_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA]] to i15
+ // UNSIGNED-NEXT: [[USA_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[USA_SAT]] to i15
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
+ // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+ usa_sat = usa - usa_sat;
+
+ // CHECK: [[UA:%[0-9]+]] = load i32, i32* %ua, align 4
+ // CHECK-NEXT: [[USA:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // SIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i32
+ // SIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i32 [[USA_EXT]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i32 @llvm.usub.sat.i32(i32 [[UA]], i32 [[USA]])
+ // SIGNED-NEXT: store i32 [[SUM]], i32* %ua_sat, align 4
+ // UNSIGNED-NEXT: [[UA_TRUNC:%[a-z0-9]+]] = trunc i32 [[UA]] to i31
+ // UNSIGNED-NEXT: [[USA_EXT:%[a-z0-9]+]] = zext i16 [[USA]] to i31
+ // UNSIGNED-NEXT: [[USA:%[a-z0-9]+]] = shl i31 [[USA_EXT]], 8
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i31 @llvm.usub.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
+ // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+ ua_sat = ua - usa_sat;
+
+ // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i39
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i39 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.ssub.sat.i39(i39 [[SA_SAT_EXT]], i39 [[I]])
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RES]], -32768
+ // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 -32768, i39 [[RES]]
+ // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i39 [[RES2]] to i16
+ // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
+ sa_sat = sa_sat - i;
+
+ // CHECK: [[SA_SAT:%[0-9]+]] = load i16, i16* %sa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %ui, align 4
+ // CHECK-NEXT: [[SA_SAT_EXT:%[a-z0-9]+]] = sext i16 [[SA_SAT]] to i40
+ // CHECK-NEXT: [[I_EXT:%[a-z0-9]+]] = zext i32 [[I]] to i40
+ // CHECK-NEXT: [[I:%[a-z0-9]+]] = shl i40 [[I_EXT]], 7
+ // CHECK-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.ssub.sat.i40(i40 [[SA_SAT_EXT]], i40 [[I]])
+ // CHECK-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 32767
+ // CHECK-NEXT: [[RES:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 32767, i40 [[SUM]]
+ // CHECK-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RES]], -32768
+ // CHECK-NEXT: [[RES2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 -32768, i40 [[RES]]
+ // CHECK-NEXT: [[RES3:%[a-z0-9]+]] = trunc i40 [[RES2]] to i16
+ // CHECK-NEXT: store i16 [[RES3]], i16* %sa_sat, align 2
+ sa_sat = sa_sat - ui;
+
+ // CHECK: [[UF_SAT:%[0-9]+]] = load i16, i16* %uf_sat, align 2
+ // CHECK-NEXT: [[UF_SAT2:%[0-9]+]] = load i16, i16* %uf_sat, align 2
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i16 @llvm.usub.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]])
+ // SIGNED-NEXT: store i16 [[SUM]], i16* %uf_sat, align 2
+ // UNSIGNED-NEXT: [[UF_SAT_TRUNC:%[a-z0-9]+]] = trunc i16 [[UF_SAT]] to i15
+ // UNSIGNED-NEXT: [[UF_SAT_TRUNC2:%[a-z0-9]+]] = trunc i16 [[UF_SAT2]] to i15
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i15 @llvm.usub.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]])
+ // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
+ // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+ uf_sat = uf_sat - uf_sat;
+
+ // CHECK: [[USA_SAT:%[0-9]+]] = load i16, i16* %usa_sat, align 2
+ // CHECK-NEXT: [[I:%[0-9]+]] = load i32, i32* %i, align 4
+ // SIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i40
+ // SIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i40
+ // SIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i40 [[I_RESIZE]], 8
+ // SIGNED-NEXT: [[SUM:%[0-9]+]] = call i40 @llvm.usub.sat.i40(i40 [[USA_SAT_RESIZE]], i40 [[I_UPSCALE]])
+ // SIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i40 [[SUM]], 65535
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i40 65535, i40 [[SUM]]
+ // SIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i40 [[RESULT]], 0
+ // SIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i40 0, i40 [[RESULT]]
+ // SIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i40 [[RESULT2]] to i16
+ // UNSIGNED-NEXT: [[USA_SAT_RESIZE:%[a-z0-9]+]] = zext i16 [[USA_SAT]] to i39
+ // UNSIGNED-NEXT: [[I_RESIZE:%[a-z0-9]+]] = sext i32 [[I]] to i39
+ // UNSIGNED-NEXT: [[I_UPSCALE:%[a-z0-9]+]] = shl i39 [[I_RESIZE]], 7
+ // UNSIGNED-NEXT: [[SUM:%[0-9]+]] = call i39 @llvm.usub.sat.i39(i39 [[USA_SAT_RESIZE]], i39 [[I_UPSCALE]])
+ // UNSIGNED-NEXT: [[USE_MAX:%[0-9]+]] = icmp sgt i39 [[SUM]], 32767
+ // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = select i1 [[USE_MAX]], i39 32767, i39 [[SUM]]
+ // UNSIGNED-NEXT: [[USE_MIN:%[0-9]+]] = icmp slt i39 [[RESULT]], 0
+ // UNSIGNED-NEXT: [[RESULT2:%[a-z0-9]+]] = select i1 [[USE_MIN]], i39 0, i39 [[RESULT]]
+ // UNSIGNED-NEXT: [[RESULT:%[a-z0-9]+]] = trunc i39 [[RESULT2]] to i16
+ // CHECK-NEXT: store i16 [[RESULT]], i16* %usa_sat, align 2
+ usa_sat = usa_sat - i;
+}
diff --git a/test/Frontend/fixed_point_unknown_conversions.c b/test/Frontend/fixed_point_unknown_conversions.c
index 0cd3d046ca..c6a02e9038 100644
--- a/test/Frontend/fixed_point_unknown_conversions.c
+++ b/test/Frontend/fixed_point_unknown_conversions.c
@@ -22,28 +22,19 @@ void func() {
_Fract fract = accum; // ok
_Accum *accum_ptr;
- accum = b; // expected-error{{conversion between fixed point and '_Bool' is not yet supported}}
- accum = i; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
- accum = i; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
accum = f; // expected-error{{conversion between fixed point and 'float' is not yet supported}}
accum = d; // expected-error{{conversion between fixed point and 'double' is not yet supported}}
accum = dc; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
accum = ic; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
accum = s; // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}}
- accum = e; // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}}
accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}}
- accum = i2; // expected-error{{conversion between fixed point and 'int_t' (aka 'int') is not yet supported}}
- c = accum; // expected-error{{conversion between fixed point and 'char' is not yet supported}}
- i = accum; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
f = accum; // expected-error{{conversion between fixed point and 'float' is not yet supported}}
d = accum; // expected-error{{conversion between fixed point and 'double' is not yet supported}}
dc = accum; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}}
ic = accum; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}}
s = accum; // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}
- e = accum; // expected-error{{conversion between fixed point and 'enum E' is not yet supported}}
ptr = accum; // expected-error{{assigning to 'int *' from incompatible type '_Accum'}}
ptr = accum_ptr; // expected-warning{{incompatible pointer types assigning to 'int *' from '_Accum *'}}
- i2 = accum; // expected-error{{conversion between fixed point and 'int' is not yet supported}}
}
diff --git a/test/Frontend/optimization-remark-with-hotness.c b/test/Frontend/optimization-remark-with-hotness.c
index 150b7324da..5f4c83b46c 100644
--- a/test/Frontend/optimization-remark-with-hotness.c
+++ b/test/Frontend/optimization-remark-with-hotness.c
@@ -66,7 +66,7 @@ void bar(int x) {
int main(int argc, const char *argv[]) {
for (int i = 0; i < 30; i++)
- // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never): always inliner (hotness:}}
+ // expected-remark@+1 {{bar not inlined into main because it should never be inlined (cost=never): no alwaysinline attribute (hotness:}}
bar(argc);
return sum;
}
diff --git a/test/Frontend/optimization-remark.c b/test/Frontend/optimization-remark.c
index 29eaa03243..234958d9ea 100644
--- a/test/Frontend/optimization-remark.c
+++ b/test/Frontend/optimization-remark.c
@@ -13,6 +13,9 @@
// RUN: %clang_cc1 %s -Rpass=inline -Rno-everything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-NO-REMARKS
// RUN: %clang_cc1 %s -Rpass=inline -Rno-everything -Reverything -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
//
+// Check that -w doesn't disable remarks.
+// RUN: %clang_cc1 %s -Rpass=inline -w -emit-llvm -o - 2>&1 | FileCheck %s --check-prefix=CHECK-REMARKS
+//
// FIXME: -Reverything should imply -Rpass=.*.
// RUN: %clang_cc1 %s -Reverything -emit-llvm -o - 2>/dev/null | FileCheck %s --check-prefix=CHECK-NO-REMARKS
//
diff --git a/test/Frontend/output-failures.c b/test/Frontend/output-failures.c
index 362deb5e46..0e9ea63f80 100644
--- a/test/Frontend/output-failures.c
+++ b/test/Frontend/output-failures.c
@@ -1,4 +1,4 @@
-// RUN: not %clang_cc1 -emit-llvm -o %S/doesnotexist/somename %s 2> %t
+// RUN: not %clang_cc1 -emit-llvm -o %t.doesnotexist/somename %s 2> %t
// RUN: FileCheck -check-prefix=OUTPUTFAIL -input-file=%t %s
-// OUTPUTFAIL: error: unable to open output file '{{.*}}{{[/\\]}}test{{[/\\]}}Frontend{{[/\\]}}doesnotexist{{[/\\]}}somename': '{{[nN]}}o such file or directory'
+// OUTPUTFAIL: error: unable to open output file '{{.*}}doesnotexist{{.}}somename': '{{[nN]}}o such file or directory'
diff --git a/test/Frontend/stats-file.c b/test/Frontend/stats-file.c
index 1869eb3f76..53b264534c 100644
--- a/test/Frontend/stats-file.c
+++ b/test/Frontend/stats-file.c
@@ -4,5 +4,5 @@
// ... here come some json values ...
// CHECK: }
-// RUN: %clang_cc1 -emit-llvm -o %t -stats-file=%S/doesnotexist/bla %s 2>&1 | FileCheck -check-prefix=OUTPUTFAIL %s
+// RUN: %clang_cc1 -emit-llvm -o %t -stats-file=%t.doesnotexist/bla %s 2>&1 | FileCheck -check-prefix=OUTPUTFAIL %s
// OUTPUTFAIL: warning: unable to open statistics output file '{{.*}}doesnotexist{{.}}bla': '{{[Nn]}}o such file or directory'
diff --git a/test/Frontend/verify-marker.c b/test/Frontend/verify-marker.c
new file mode 100644
index 0000000000..7beee97324
--- /dev/null
+++ b/test/Frontend/verify-marker.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 -verify %s
+
+#include "verify-marker.h" // expected-error@#1 {{unknown type name 'unknown_type'}}
+
+int x = 1; // #a
+int x = 2; // #b
+// expected-error@#b {{redefinition of 'x'}}
+// expected-note@#a {{previous}}
+
+// expected-error@#unknown {{}} expected-error {{use of undefined marker '#unknown'}}
+
+// This is OK: there's no problem with a source file containing what looks like
+// a duplicate definition of a marker if that marker is never used.
+// #foo
+// #foo
+
+// #bar expected-note {{ambiguous marker '#bar' is defined here}}
+// #bar expected-note {{ambiguous marker '#bar' is defined here}}
+// expected-error@#bar 0-1{{oops}} expected-error{{reference to marker '#bar' is ambiguous}}
+
+// expected-error@#forward_ref {{undeclared identifier 'future'}}
+int y = future; // #forward_ref
diff --git a/test/Frontend/verify-marker.h b/test/Frontend/verify-marker.h
new file mode 100644
index 0000000000..04bd388497
--- /dev/null
+++ b/test/Frontend/verify-marker.h
@@ -0,0 +1 @@
+unknown_type x; // #1
diff --git a/test/Frontend/warning-mapping-2.c b/test/Frontend/warning-mapping-2.c
index 39ba4997a4..4f7f1ee760 100644
--- a/test/Frontend/warning-mapping-2.c
+++ b/test/Frontend/warning-mapping-2.c
@@ -1,5 +1,7 @@
-// Check that -w has lower priority than -pedantic-errors.
+// Check that -w takes precedence over -pedantic-errors.
// RUN: %clang_cc1 -verify -pedantic-errors -w %s
-void f0() { f1(); } // expected-error {{implicit declaration of function}}
+// Expect *not* to see a diagnostic for "implicit declaration of function"
+// expected-no-diagnostics
+void f0() { f1(); }
diff --git a/test/Frontend/warning-mapping-4.c b/test/Frontend/warning-mapping-4.c
index 6644042e24..a98136386e 100644
--- a/test/Frontend/warning-mapping-4.c
+++ b/test/Frontend/warning-mapping-4.c
@@ -1,5 +1,9 @@
+// Verify that various combinations of flags properly keep the sign-compare
+// warning disabled.
+
// RUN: %clang_cc1 -verify -Wno-error=sign-compare %s
// RUN: %clang_cc1 -verify -Wsign-compare -w -Wno-error=sign-compare %s
+// RUN: %clang_cc1 -verify -w -Werror=sign-compare %s
// expected-no-diagnostics
int f0(int x, unsigned y) {
diff --git a/test/Frontend/warning-mapping-5.c b/test/Frontend/warning-mapping-5.c
index 27d53dc189..84efd8010d 100644
--- a/test/Frontend/warning-mapping-5.c
+++ b/test/Frontend/warning-mapping-5.c
@@ -1,6 +1,5 @@
-// Check that #pragma diagnostic warning overrides -Werror. This matches GCC's
-// original documentation, but not its earlier implementations.
-//
+// Check that #pragma diagnostic warning overrides -Werror.
+//
// RUN: %clang_cc1 -verify -Werror %s
#pragma clang diagnostic warning "-Wsign-compare"
diff --git a/test/Frontend/warning-mapping-6.c b/test/Frontend/warning-mapping-6.c
new file mode 100644
index 0000000000..ea22f72cc9
--- /dev/null
+++ b/test/Frontend/warning-mapping-6.c
@@ -0,0 +1,9 @@
+// Check that "#pragma diagnostic error" is suppressed by -w.
+//
+// RUN: %clang_cc1 -verify -Werror -w %s
+
+// expected-no-diagnostics
+#pragma gcc diagnostic error "-Wsign-compare"
+int f0(int x, unsigned y) {
+ return x < y;
+}
diff --git a/test/Frontend/x86-target-cpu.c b/test/Frontend/x86-target-cpu.c
index 0ec301f442..05b28f0f68 100644
--- a/test/Frontend/x86-target-cpu.c
+++ b/test/Frontend/x86-target-cpu.c
@@ -35,5 +35,6 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu btver1 -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu btver2 -verify %s
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu znver1 -verify %s
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -target-cpu znver2 -verify %s
//
// expected-no-diagnostics