diff options
author | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
---|---|---|
committer | Jordan Rupprecht <rupprecht@google.com> | 2019-05-14 21:58:59 +0000 |
commit | b35a2aa71f76a334a9c98c0a3c3995b5d902d2b9 (patch) | |
tree | cdff4a5d1a715d4ad622fd8f190128b54bebe440 /test/Frontend | |
parent | 3748d41833787fcbf59cc5624e8d2b042a8991bc (diff) | |
parent | 741e05796da92b46d4f7bcbee00702ff37df6489 (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.c | 433 | ||||
-rw-r--r-- | test/Frontend/fixed_point_comparisons.c | 378 | ||||
-rw-r--r-- | test/Frontend/fixed_point_conversions.c | 540 | ||||
-rw-r--r-- | test/Frontend/fixed_point_errors.c | 18 | ||||
-rw-r--r-- | test/Frontend/fixed_point_sub.c | 390 | ||||
-rw-r--r-- | test/Frontend/fixed_point_unknown_conversions.c | 9 | ||||
-rw-r--r-- | test/Frontend/optimization-remark-with-hotness.c | 2 | ||||
-rw-r--r-- | test/Frontend/optimization-remark.c | 3 | ||||
-rw-r--r-- | test/Frontend/output-failures.c | 4 | ||||
-rw-r--r-- | test/Frontend/stats-file.c | 2 | ||||
-rw-r--r-- | test/Frontend/verify-marker.c | 22 | ||||
-rw-r--r-- | test/Frontend/verify-marker.h | 1 | ||||
-rw-r--r-- | test/Frontend/warning-mapping-2.c | 6 | ||||
-rw-r--r-- | test/Frontend/warning-mapping-4.c | 4 | ||||
-rw-r--r-- | test/Frontend/warning-mapping-5.c | 5 | ||||
-rw-r--r-- | test/Frontend/warning-mapping-6.c | 9 | ||||
-rw-r--r-- | test/Frontend/x86-target-cpu.c | 1 |
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 |