+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -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
+short _Accum sa;
+_Accum a, a2, a3, a4;
+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;
+
+_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;
+_Bool b;
+
+// CHECK-LABEL: @sadd_sasasa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sadd_sasasa() {
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
+// CHECK-LABEL: @sadd_asaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[UPSCALE]], [[TMP1]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sadd_asaa() {
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
+// CHECK-LABEL: @sadd_sasasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[RESIZE]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sadd_sasasf() {
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
+// CHECK-LABEL: @sadd_sasaf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = add i24 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sadd_sasaf() {
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
+// CHECK-LABEL: @sadd_aasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[UPSCALE]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sadd_aasf() {
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
+// CHECK-LABEL: @sadd_aalf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i48
+// CHECK-NEXT: [[TMP2:%.*]] = add i48 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i48 [[TMP2]], 16
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i48 [[DOWNSCALE]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sadd_aalf() {
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
+// SIGNED-LABEL: @sadd_sasausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = add i17 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sadd_sasausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[TMP1]]
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sadd_sasausa() {
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
+// SIGNED-LABEL: @sadd_asaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 9
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = add i33 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sadd_asaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i32 [[UPSCALE]], [[TMP1]]
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sadd_asaua() {
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
+// SIGNED-LABEL: @sadd_sasausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = add i17 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sadd_sasausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[RESIZE]]
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sadd_sasausf() {
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
+// SIGNED-LABEL: @sadd_sasaulf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i41
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i41 [[RESIZE]], 25
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i41
+// SIGNED-NEXT: [[TMP2:%.*]] = add i41 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i41 [[TMP2]], 25
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i41 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sadd_sasaulf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 24
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i40 [[UPSCALE]], [[RESIZE1]]
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i40 [[TMP2]], 24
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sadd_sasaulf() {
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;
+// CHECK-LABEL: @sadd_aaaaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a2, align 4
+// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @a3, align 4
+// CHECK-NEXT: [[TMP4:%.*]] = add i32 [[TMP2]], [[TMP3]]
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @a4, align 4
+// CHECK-NEXT: [[TMP6:%.*]] = add i32 [[TMP4]], [[TMP5]]
+// CHECK-NEXT: store i32 [[TMP6]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sadd_aaaaa() {
+ a = a + a2 + a3 + a4;
+}
- 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
+// CHECK-LABEL: @uadd_usausausa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void uadd_usausausa() {
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
+// CHECK-LABEL: @uadd_uausaua(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[UPSCALE]], [[TMP1]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// CHECK-NEXT: ret void
+//
+void uadd_uausaua() {
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
+// CHECK-LABEL: @uadd_usausausf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = add i16 [[TMP0]], [[RESIZE]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void uadd_usausausf() {
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
+// CHECK-LABEL: @uadd_usausauf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = add i24 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void uadd_usausauf() {
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
+
+// CHECK-LABEL: @int_sasai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = add i39 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasai() {
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
+// CHECK-LABEL: @int_sasaui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = add i40 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasaui() {
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
+// SIGNED-LABEL: @int_usausai(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = add i40 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausai(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i39 [[RESIZE]], [[UPSCALE]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausai() {
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
+// SIGNED-LABEL: @int_usausaui(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = add i40 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausaui(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i39 [[RESIZE]], [[UPSCALE]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausaui() {
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
+// CHECK-LABEL: @int_lflfui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i64
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE1]], 31
+// CHECK-NEXT: [[TMP2:%.*]] = add i64 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i64 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void int_lflfui() {
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
+// CHECK-LABEL: @int_aab(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @b, align 1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = add i47 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aab() {
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
+
+// CHECK-LABEL: @sat_sassasas(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasas() {
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
+// SIGNED-LABEL: @sat_usasusausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusausas() {
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
+// SIGNED-LABEL: @sat_uasuausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]])
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua_sat, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_uasuausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i31
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i31 [[RESIZE1]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i31 @llvm.uadd.sat.i31(i31 [[RESIZE]], i31 [[UPSCALE]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i31 [[TMP2]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE2]], i32* @ua_sat, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sat_uasuausas() {
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
+// CHECK-LABEL: @sat_sassasi(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.sadd.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 -32768, i39 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasi() {
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
+// CHECK-LABEL: @sat_sassasui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.sadd.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 32767, i40 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 -32768, i40 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasui() {
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
+// SIGNED-LABEL: @sat_ufsufsufs(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @uf_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_ufsufsufs(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @uf_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_ufsufsufs() {
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.sadd.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.sadd.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
+// SIGNED-LABEL: @sat_usasusasi(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.sadd.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
+// SIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 65535
+// SIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 65535, i40 [[TMP2]]
+// SIGNED-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], 0
+// SIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 0, i40 [[SATMAX]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusasi(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.sadd.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
+// UNSIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// UNSIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// UNSIGNED-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 0, i39 [[SATMAX]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusasi() {
usa_sat = usa_sat + i;
}
--- /dev/null
+// 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;
+// SIGNED-DAG: @usa_const = {{.*}}global i16 768, align 2
+// 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;
+// SIGNED-DAG: @usa_const2 = {{.*}}global i16 640, align 2
+// 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;
+// SIGNED-DAG: @sat_usa_const = {{.*}}global i16 -1, align 2
+// 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;
+// SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 -1, align 2
+// 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
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
signed char c;
-// CHECK-LABEL: @Addition(
-void Addition() {
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-LABEL: @add_shfa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @shf, align 1
// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP2]], 8
// CHECK-NEXT: [[RESIZE1:%.*]] = trunc i32 [[DOWNSCALE]] to i8
// CHECK-NEXT: store i8 [[RESIZE1]], i8* @shf, align 1
+// CHECK-NEXT: ret void
+//
+void add_shfa() {
shf += a;
+}
-// CHECK: [[TMP3:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* @a, align 4
-// SIGNED-NEXT: [[RESIZE2:%.*]] = sext i32 [[TMP4]] to i33
-// SIGNED-NEXT: [[UPSCALE3:%.*]] = shl i33 [[RESIZE2]], 1
-// SIGNED-NEXT: [[RESIZE4:%.*]] = zext i16 [[TMP3]] to i33
-// SIGNED-NEXT: [[TMP5:%.*]] = add i33 [[UPSCALE3]], [[RESIZE4]]
-// SIGNED-NEXT: [[DOWNSCALE5:%.*]] = ashr i33 [[TMP5]], 1
-// SIGNED-NEXT: [[RESIZE6:%.*]] = trunc i33 [[DOWNSCALE5]] to i32
-// SIGNED-NEXT: store i32 [[RESIZE6]], i32* @a, align 4
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i16 [[TMP3]] to i32
-// UNSIGNED-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], [[RESIZE2]]
-// UNSIGNED-NEXT: store i32 [[TMP5]], i32* @a, align 4
+// SIGNED-LABEL: @add_auf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = add i33 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_auf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], [[RESIZE]]
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void add_auf() {
a += uf;
+}
-// CHECK: [[TMP6:%.*]] = load i64, i64* @ula, align 8
-// CHECK-NEXT: [[TMP7:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[RESIZE7:%.*]] = zext i16 [[TMP7]] to i64
-// CHECK-NEXT: [[UPSCALE8:%.*]] = shl i64 [[RESIZE7]], 16
-// CHECK-NEXT: [[TMP8:%.*]] = add i64 [[UPSCALE8]], [[TMP6]]
-// CHECK-NEXT: [[DOWNSCALE9:%.*]] = lshr i64 [[TMP8]], 16
-// CHECK-NEXT: [[RESIZE10:%.*]] = trunc i64 [[DOWNSCALE9]] to i16
-// CHECK-NEXT: store i16 [[RESIZE10]], i16* @uf, align 2
+// CHECK-LABEL: @add_ufula(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* @ula, align 8
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i64
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 16
+// CHECK-NEXT: [[TMP2:%.*]] = add i64 [[UPSCALE]], [[TMP0]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i64 [[TMP2]], 16
+// CHECK-NEXT: [[RESIZE1:%.*]] = trunc i64 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE1]], i16* @uf, align 2
+// CHECK-NEXT: ret void
+//
+void add_ufula() {
uf += ula;
+}
-// CHECK: [[TMP9:%.*]] = load i8, i8* @shf, align 1
-// CHECK-NEXT: [[TMP10:%.*]] = load i64, i64* @ula, align 8
-// SIGNED-NEXT: [[RESIZE11:%.*]] = zext i64 [[TMP10]] to i65
-// SIGNED-NEXT: [[RESIZE12:%.*]] = sext i8 [[TMP9]] to i65
-// SIGNED-NEXT: [[UPSCALE13:%.*]] = shl i65 [[RESIZE12]], 25
-// SIGNED-NEXT: [[TMP11:%.*]] = add i65 [[RESIZE11]], [[UPSCALE13]]
-// SIGNED-NEXT: [[DOWNSCALE14:%.*]] = ashr i65 [[TMP11]], 1
-// SIGNED-NEXT: [[RESIZE15:%.*]] = trunc i65 [[DOWNSCALE14]] to i64
-// SIGNED-NEXT: [[UPSCALE16:%.*]] = shl i64 [[RESIZE15]], 1
-// SIGNED-NEXT: store i64 [[UPSCALE16]], i64* @ula, align 8
-// UNSIGNED-NEXT: [[RESIZE7:%.*]] = sext i8 [[TMP9]] to i64
-// UNSIGNED-NEXT: [[UPSCALE8:%.*]] = shl i64 [[RESIZE7]], 24
-// UNSIGNED-NEXT: [[TMP11:%.*]] = add i64 [[TMP10]], [[UPSCALE8]]
-// UNSIGNED-NEXT: store i64 [[TMP11]], i64* @ula, align 8
+// SIGNED-LABEL: @add_ulashf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i8, i8* @shf, align 1
+// SIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @ula, align 8
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i64 [[TMP1]] to i65
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i8 [[TMP0]] to i65
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i65 [[RESIZE1]], 25
+// SIGNED-NEXT: [[TMP2:%.*]] = add i65 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i65 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i65 [[DOWNSCALE]] to i64
+// SIGNED-NEXT: [[UPSCALE3:%.*]] = shl i64 [[RESIZE2]], 1
+// SIGNED-NEXT: store i64 [[UPSCALE3]], i64* @ula, align 8
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_ulashf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i8, i8* @shf, align 1
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @ula, align 8
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP0]] to i64
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 24
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[UPSCALE]]
+// UNSIGNED-NEXT: store i64 [[TMP2]], i64* @ula, align 8
+// UNSIGNED-NEXT: ret void
+//
+void add_ulashf() {
ula += shf;
+}
-// CHECK: [[TMP12:%.*]] = load i8, i8* @shf, align 1
-// CHECK-NEXT: [[TMP13:%.*]] = load i16, i16* @uf, align 2
-// SIGNED-NEXT: [[RESIZE17:%.*]] = zext i16 [[TMP13]] to i17
-// SIGNED-NEXT: [[RESIZE18:%.*]] = sext i8 [[TMP12]] to i17
-// SIGNED-NEXT: [[UPSCALE19:%.*]] = shl i17 [[RESIZE18]], 9
-// SIGNED-NEXT: [[TMP14:%.*]] = add i17 [[RESIZE17]], [[UPSCALE19]]
-// SIGNED-NEXT: [[DOWNSCALE20:%.*]] = ashr i17 [[TMP14]], 1
-// SIGNED-NEXT: [[RESIZE21:%.*]] = trunc i17 [[DOWNSCALE20]] to i16
-// SIGNED-NEXT: [[UPSCALE22:%.*]] = shl i16 [[RESIZE21]], 1
-// SIGNED-NEXT: store i16 [[UPSCALE22]], i16* @uf, align 2
-// UNSIGNED-NEXT: [[RESIZE9:%.*]] = sext i8 [[TMP12]] to i16
-// UNSIGNED-NEXT: [[UPSCALE10:%.*]] = shl i16 [[RESIZE9]], 8
-// UNSIGNED-NEXT: [[TMP14:%.*]] = add i16 [[TMP13]], [[UPSCALE10]]
-// UNSIGNED-NEXT: store i16 [[TMP14]], i16* @uf, align 2
+// SIGNED-LABEL: @add_ufshf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i8, i8* @shf, align 1
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i17
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i8 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE1]], 9
+// SIGNED-NEXT: [[TMP2:%.*]] = add i17 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: [[UPSCALE3:%.*]] = shl i16 [[RESIZE2]], 1
+// SIGNED-NEXT: store i16 [[UPSCALE3]], i16* @uf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_ufshf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i8, i8* @shf, align 1
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP0]] to i16
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i16 [[TMP1]], [[UPSCALE]]
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @uf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void add_ufshf() {
uf += shf;
+}
-// CHECK: [[TMP15:%.*]] = load i8, i8* @shf, align 1
-// CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE23:%.*]] = sext i8 [[TMP15]] to i32
-// CHECK-NEXT: [[UPSCALE24:%.*]] = shl i32 [[RESIZE23]], 8
-// CHECK-NEXT: [[TMP17:%.*]] = add i32 [[TMP16]], [[UPSCALE24]]
-// CHECK-NEXT: store i32 [[TMP17]], i32* @a, align 4
+// CHECK-LABEL: @add_ashf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* @shf, align 1
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], [[UPSCALE]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void add_ashf() {
a += shf;
+}
-// CHECK: [[TMP18:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP19:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE25:%.*]] = sext i32 [[TMP19]] to i47
-// CHECK-NEXT: [[RESIZE26:%.*]] = sext i32 [[TMP18]] to i47
-// CHECK-NEXT: [[UPSCALE27:%.*]] = shl i47 [[RESIZE26]], 15
-// CHECK-NEXT: [[TMP20:%.*]] = add i47 [[RESIZE25]], [[UPSCALE27]]
-// CHECK-NEXT: [[RESIZE28:%.*]] = trunc i47 [[TMP20]] to i32
-// CHECK-NEXT: store i32 [[RESIZE28]], i32* @a, align 4
+// CHECK-LABEL: @add_ai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = add i47 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void add_ai() {
a += i;
+}
-// CHECK: [[TMP21:%.*]] = load i32, i32* @u, align 4
-// CHECK-NEXT: [[TMP22:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE29:%.*]] = sext i32 [[TMP22]] to i48
-// CHECK-NEXT: [[RESIZE30:%.*]] = zext i32 [[TMP21]] to i48
-// CHECK-NEXT: [[UPSCALE31:%.*]] = shl i48 [[RESIZE30]], 15
-// CHECK-NEXT: [[TMP23:%.*]] = add i48 [[RESIZE29]], [[UPSCALE31]]
-// CHECK-NEXT: [[RESIZE32:%.*]] = trunc i48 [[TMP23]] to i32
-// CHECK-NEXT: store i32 [[RESIZE32]], i32* @a, align 4
+// CHECK-LABEL: @add_au(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @u, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i48
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP0]] to i48
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i48 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = add i48 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i48 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void add_au() {
a += u;
+}
-// CHECK: [[TMP24:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP25:%.*]] = load i64, i64* @ula, align 8
-// SIGNED-NEXT: [[RESIZE33:%.*]] = zext i64 [[TMP25]] to i65
-// SIGNED-NEXT: [[RESIZE34:%.*]] = sext i32 [[TMP24]] to i65
-// SIGNED-NEXT: [[UPSCALE35:%.*]] = shl i65 [[RESIZE34]], 32
-// SIGNED-NEXT: [[TMP26:%.*]] = add i65 [[RESIZE33]], [[UPSCALE35]]
-// SIGNED-NEXT: [[RESIZE36:%.*]] = trunc i65 [[TMP26]] to i64
-// SIGNED-NEXT: store i64 [[RESIZE36]], i64* @ula, align 8
-// UNSIGNED-NEXT: [[RESIZE21:%.*]] = sext i32 [[TMP24]] to i64
-// UNSIGNED-NEXT: [[UPSCALE22:%.*]] = shl i64 [[RESIZE21]], 31
-// UNSIGNED-NEXT: [[TMP26:%.*]] = add i64 [[TMP25]], [[UPSCALE22]]
-// UNSIGNED-NEXT: store i64 [[TMP26]], i64* @ula, align 8
+// SIGNED-LABEL: @add_ulai(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @ula, align 8
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i64 [[TMP1]] to i65
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i65
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i65 [[RESIZE1]], 32
+// SIGNED-NEXT: [[TMP2:%.*]] = add i65 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i65 [[TMP2]] to i64
+// SIGNED-NEXT: store i64 [[RESIZE2]], i64* @ula, align 8
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_ulai(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @ula, align 8
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 31
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], [[UPSCALE]]
+// UNSIGNED-NEXT: store i64 [[TMP2]], i64* @ula, align 8
+// UNSIGNED-NEXT: ret void
+//
+void add_ulai() {
ula += i;
+}
-// CHECK: [[TMP27:%.*]] = load i64, i64* @ula, align 8
-// CHECK-NEXT: [[TMP28:%.*]] = load i32, i32* @i, align 4
-// SIGNED-NEXT: [[RESIZE37:%.*]] = sext i32 [[TMP28]] to i65
-// SIGNED-NEXT: [[UPSCALE38:%.*]] = shl i65 [[RESIZE37]], 32
-// SIGNED-NEXT: [[RESIZE39:%.*]] = zext i64 [[TMP27]] to i65
-// SIGNED-NEXT: [[TMP29:%.*]] = add i65 [[UPSCALE38]], [[RESIZE39]]
-// SIGNED-NEXT: [[RESIZE40:%.*]] = trunc i65 [[TMP29]] to i64
-// SIGNED-NEXT: [[DOWNSCALE41:%.*]] = lshr i64 [[RESIZE40]], 32
-// SIGNED-NEXT: [[RESIZE42:%.*]] = trunc i64 [[DOWNSCALE41]] to i32
-// SIGNED-NEXT: store i32 [[RESIZE42]], i32* @i, align 4
-// UNSIGNED-NEXT: [[RESIZE23:%.*]] = sext i32 [[TMP28]] to i64
-// UNSIGNED-NEXT: [[UPSCALE24:%.*]] = shl i64 [[RESIZE23]], 31
-// UNSIGNED-NEXT: [[TMP29:%.*]] = add i64 [[UPSCALE24]], [[TMP27]]
-// UNSIGNED-NEXT: [[DOWNSCALE25:%.*]] = lshr i64 [[TMP29]], 31
-// UNSIGNED-NEXT: [[RESIZE26:%.*]] = trunc i64 [[DOWNSCALE25]] to i32
-// UNSIGNED-NEXT: store i32 [[RESIZE26]], i32* @i, align 4
+// SIGNED-LABEL: @add_iula(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i64, i64* @ula, align 8
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i65
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i65 [[RESIZE]], 32
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i64 [[TMP0]] to i65
+// SIGNED-NEXT: [[TMP2:%.*]] = add i65 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i65 [[TMP2]] to i64
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i64 [[RESIZE2]], 32
+// SIGNED-NEXT: [[RESIZE3:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE3]], i32* @i, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_iula(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i64, i64* @ula, align 8
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i64
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 31
+// UNSIGNED-NEXT: [[TMP2:%.*]] = add i64 [[UPSCALE]], [[TMP0]]
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i64 [[TMP2]], 31
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i64 [[DOWNSCALE]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @i, align 4
+// UNSIGNED-NEXT: ret void
+//
+void add_iula() {
i += ula;
+}
-// CHECK: [[TMP30:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[TMP31:%.*]] = load i8, i8* @c, align 1
-// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP31]] to i32
-// CHECK-NEXT: [[RESIZE43:%.*]] = sext i32 [[CONV]] to i47
-// CHECK-NEXT: [[UPSCALE44:%.*]] = shl i47 [[RESIZE43]], 15
-// CHECK-NEXT: [[RESIZE45:%.*]] = sext i32 [[TMP30]] to i47
-// CHECK-NEXT: [[TMP32:%.*]] = add i47 [[UPSCALE44]], [[RESIZE45]]
-// CHECK-NEXT: [[RESIZE46:%.*]] = trunc i47 [[TMP32]] to i32
-// CHECK-NEXT: [[TMP33:%.*]] = icmp slt i32 [[RESIZE46]], 0
-// CHECK-NEXT: [[TMP34:%.*]] = add i32 [[RESIZE46]], 32767
-// CHECK-NEXT: [[TMP35:%.*]] = select i1 [[TMP33]], i32 [[TMP34]], i32 [[RESIZE46]]
-// CHECK-NEXT: [[DOWNSCALE47:%.*]] = ashr i32 [[TMP35]], 15
-// CHECK-NEXT: [[RESIZE48:%.*]] = trunc i32 [[DOWNSCALE47]] to i8
-// CHECK-NEXT: store i8 [[RESIZE48]], i8* @c, align 1
+// CHECK-LABEL: @add_ca(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1
+// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = add i47 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[RESIZE2]], 0
+// CHECK-NEXT: [[TMP4:%.*]] = add i32 [[RESIZE2]], 32767
+// CHECK-NEXT: [[TMP5:%.*]] = select i1 [[TMP3]], i32 [[TMP4]], i32 [[RESIZE2]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP5]], 15
+// CHECK-NEXT: [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-NEXT: store i8 [[RESIZE3]], i8* @c, align 1
+// CHECK-NEXT: ret void
+//
+void add_ca() {
c += a;
+}
-// CHECK: [[TMP36:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP37:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[RESIZE47:%.*]] = sext i32 [[TMP37]] to i47
-// CHECK-NEXT: [[RESIZE48:%.*]] = sext i32 [[TMP36]] to i47
-// CHECK-NEXT: [[UPSCALE49:%.*]] = shl i47 [[RESIZE48]], 15
-// CHECK-NEXT: [[TMP38:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[RESIZE47]], i47 [[UPSCALE49]])
-// CHECK-NEXT: [[TMP39:%.*]] = icmp sgt i47 [[TMP38]], 2147483647
-// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP39]], i47 2147483647, i47 [[TMP38]]
-// CHECK-NEXT: [[TMP40:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
-// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP40]], i47 -2147483648, i47 [[SATMAX]]
-// CHECK-NEXT: [[RESIZE50:%.*]] = trunc i47 [[SATMIN]] to i32
-// CHECK-NEXT: store i32 [[RESIZE50]], i32* @sa, align 4
+// CHECK-LABEL: @add_sai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[RESIZE]], i47 [[UPSCALE]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @sa, align 4
+// CHECK-NEXT: ret void
+//
+void add_sai() {
sa += i;
+}
-// CHECK: [[TMP41:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP42:%.*]] = load i8, i8* @c, align 1
-// CHECK-NEXT: [[CONV53:%.*]] = sext i8 [[TMP42]] to i32
-// CHECK-NEXT: [[RESIZE54:%.*]] = sext i32 [[CONV53]] to i47
-// CHECK-NEXT: [[UPSCALE55:%.*]] = shl i47 [[RESIZE54]], 15
-// CHECK-NEXT: [[RESIZE56:%.*]] = sext i32 [[TMP41]] to i47
-// CHECK-NEXT: [[TMP43:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[UPSCALE55]], i47 [[RESIZE56]])
-// CHECK-NEXT: [[TMP44:%.*]] = icmp sgt i47 [[TMP43]], 2147483647
-// CHECK-NEXT: [[SATMAX57:%.*]] = select i1 [[TMP44]], i47 2147483647, i47 [[TMP43]]
-// CHECK-NEXT: [[TMP45:%.*]] = icmp slt i47 [[SATMAX57]], -2147483648
-// CHECK-NEXT: [[SATMIN58:%.*]] = select i1 [[TMP45]], i47 -2147483648, i47 [[SATMAX57]]
-// CHECK-NEXT: [[RESIZE59:%.*]] = trunc i47 [[SATMIN58]] to i32
-// CHECK-NEXT: [[TMP46:%.*]] = icmp slt i32 [[RESIZE59]], 0
-// CHECK-NEXT: [[TMP47:%.*]] = add i32 [[RESIZE59]], 32767
-// CHECK-NEXT: [[TMP48:%.*]] = select i1 [[TMP46]], i32 [[TMP47]], i32 [[RESIZE59]]
-// CHECK-NEXT: [[DOWNSCALE60:%.*]] = ashr i32 [[TMP48]], 15
-// CHECK-NEXT: [[RESIZE61:%.*]] = trunc i32 [[DOWNSCALE60]] to i8
-// CHECK-NEXT: store i8 [[RESIZE61]], i8* @c, align 1
+// CHECK-LABEL: @add_csa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1
+// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sadd.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
+// CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
+// CHECK-NEXT: [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
+// CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
+// CHECK-NEXT: [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-NEXT: store i8 [[RESIZE3]], i8* @c, align 1
+// CHECK-NEXT: ret void
+//
+void add_csa() {
c += sa;
+}
-// CHECK: [[TMP47:%.*]] = load i32, i32* @u, align 4
-// CHECK-NEXT: [[TMP48:%.*]] = load i64, i64* @sula, align 8
-// SIGNED-NEXT: [[RESIZE55:%.*]] = zext i32 [[TMP47]] to i64
-// SIGNED-NEXT: [[UPSCALE56:%.*]] = shl i64 [[RESIZE55]], 32
-// SIGNED-NEXT: [[TMP49:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[TMP48]], i64 [[UPSCALE56]])
-// SIGNED-NEXT: store i64 [[TMP49]], i64* @sula, align 8
-// UNSIGNED-NEXT: [[RESIZE39:%.*]] = trunc i64 [[TMP48]] to i63
-// UNSIGNED-NEXT: [[RESIZE40:%.*]] = zext i32 [[TMP47]] to i63
-// UNSIGNED-NEXT: [[UPSCALE41:%.*]] = shl i63 [[RESIZE40]], 31
-// UNSIGNED-NEXT: [[TMP49:%.*]] = call i63 @llvm.uadd.sat.i63(i63 [[RESIZE39]], i63 [[UPSCALE41]])
-// UNSIGNED-NEXT: [[RESIZE42:%.*]] = zext i63 [[TMP49]] to i64
-// UNSIGNED-NEXT: store i64 [[RESIZE42]], i64* @sula, align 8
+// SIGNED-LABEL: @add_sulau(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @u, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @sula, align 8
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i64
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE]], 32
+// SIGNED-NEXT: [[TMP2:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[TMP1]], i64 [[UPSCALE]])
+// SIGNED-NEXT: store i64 [[TMP2]], i64* @sula, align 8
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_sulau(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @u, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i64, i64* @sula, align 8
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i64 [[TMP1]] to i63
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP0]] to i63
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i63 [[RESIZE1]], 31
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i63 @llvm.uadd.sat.i63(i63 [[RESIZE]], i63 [[UPSCALE]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i63 [[TMP2]] to i64
+// UNSIGNED-NEXT: store i64 [[RESIZE2]], i64* @sula, align 8
+// UNSIGNED-NEXT: ret void
+//
+void add_sulau() {
sula += u;
+}
-// CHECK: [[TMP50:%.*]] = load i16, i16* @suf, align 2
-// CHECK-NEXT: [[TMP51:%.*]] = load i8, i8* @sshf, align 1
-// SIGNED-NEXT: [[RESIZE57:%.*]] = sext i8 [[TMP51]] to i17
-// SIGNED-NEXT: [[UPSCALE58:%.*]] = shl i17 [[RESIZE57]], 9
-// SIGNED-NEXT: [[RESIZE59:%.*]] = zext i16 [[TMP50]] to i17
-// SIGNED-NEXT: [[TMP52:%.*]] = call i17 @llvm.sadd.sat.i17(i17 [[UPSCALE58]], i17 [[RESIZE59]])
-// SIGNED-NEXT: [[DOWNSCALE60:%.*]] = ashr i17 [[TMP52]], 1
-// SIGNED-NEXT: [[RESIZE61:%.*]] = trunc i17 [[DOWNSCALE60]] to i16
-// SIGNED-NEXT: [[DOWNSCALE62:%.*]] = ashr i16 [[RESIZE61]], 8
-// SIGNED-NEXT: [[RESIZE63:%.*]] = trunc i16 [[DOWNSCALE62]] to i8
-// SIGNED-NEXT: store i8 [[RESIZE63]], i8* @sshf, align 1
-// UNSIGNED-NEXT: [[RESIZE43:%.*]] = sext i8 [[TMP51]] to i16
-// UNSIGNED-NEXT: [[UPSCALE44:%.*]] = shl i16 [[RESIZE43]], 8
-// UNSIGNED-NEXT: [[TMP52:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[UPSCALE44]], i16 [[TMP50]])
-// UNSIGNED-NEXT: [[DOWNSCALE45:%.*]] = ashr i16 [[TMP52]], 8
-// UNSIGNED-NEXT: [[RESIZE46:%.*]] = trunc i16 [[DOWNSCALE45]] to i8
-// UNSIGNED-NEXT: store i8 [[RESIZE46]], i8* @sshf, align 1
+// SIGNED-LABEL: @add_sshsuf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @sshf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 9
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = call i17 @llvm.sadd.sat.i17(i17 [[UPSCALE]], i17 [[RESIZE1]])
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: [[DOWNSCALE3:%.*]] = ashr i16 [[RESIZE2]], 8
+// SIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[DOWNSCALE3]] to i8
+// SIGNED-NEXT: store i8 [[RESIZE4]], i8* @sshf, align 1
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @add_sshsuf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @sshf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i16 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[UPSCALE]], i16 [[TMP0]])
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i16 [[TMP2]], 8
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[DOWNSCALE]] to i8
+// UNSIGNED-NEXT: store i8 [[RESIZE1]], i8* @sshf, align 1
+// UNSIGNED-NEXT: ret void
+//
+void add_sshsuf() {
sshf += suf;
}
// Subtraction, multiplication and division should work about the same, so
// just make sure we can do them.
-// CHECK-LABEL: @Subtraction(
-void Subtraction() {
-// CHECK: [[TMP0:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
-// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
-// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
-// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
-// SIGNED-NEXT: [[TMP2:%.*]] = sub i33 [[UPSCALE]], [[RESIZE1]]
-// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
-// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
-// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
-// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], [[RESIZE]]
-// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// SIGNED-LABEL: @sub_auf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i33 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sub_auf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], [[RESIZE]]
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sub_auf() {
a -= uf;
+}
-// CHECK: [[TMP3:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE3:%.*]] = sext i32 [[TMP4]] to i47
-// CHECK-NEXT: [[RESIZE4:%.*]] = sext i32 [[TMP3]] to i47
-// CHECK-NEXT: [[UPSCALE5:%.*]] = shl i47 [[RESIZE4]], 15
-// CHECK-NEXT: [[TMP5:%.*]] = sub i47 [[RESIZE3]], [[UPSCALE5]]
-// CHECK-NEXT: [[RESIZE6:%.*]] = trunc i47 [[TMP5]] to i32
-// CHECK-NEXT: store i32 [[RESIZE6]], i32* @a, align 4
+// CHECK-LABEL: @sub_ai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = sub i47 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sub_ai() {
a -= i;
+}
-// CHECK: [[TMP6:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* @c, align 1
-// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP7]] to i32
-// CHECK-NEXT: [[RESIZE7:%.*]] = sext i32 [[CONV]] to i47
-// CHECK-NEXT: [[UPSCALE8:%.*]] = shl i47 [[RESIZE7]], 15
-// CHECK-NEXT: [[RESIZE9:%.*]] = sext i32 [[TMP6]] to i47
-// CHECK-NEXT: [[TMP8:%.*]] = call i47 @llvm.ssub.sat.i47(i47 [[UPSCALE8]], i47 [[RESIZE9]])
-// CHECK-NEXT: [[TMP9:%.*]] = icmp sgt i47 [[TMP8]], 2147483647
-// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP9]], i47 2147483647, i47 [[TMP8]]
-// CHECK-NEXT: [[TMP10:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
-// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP10]], i47 -2147483648, i47 [[SATMAX]]
-// CHECK-NEXT: [[RESIZE10:%.*]] = trunc i47 [[SATMIN]] to i32
-// CHECK-NEXT: [[TMP11:%.*]] = icmp slt i32 [[RESIZE10]], 0
-// CHECK-NEXT: [[TMP12:%.*]] = add i32 [[RESIZE10]], 32767
-// CHECK-NEXT: [[TMP13:%.*]] = select i1 [[TMP11]], i32 [[TMP12]], i32 [[RESIZE10]]
-// CHECK-NEXT: [[DOWNSCALE11:%.*]] = ashr i32 [[TMP13]], 15
-// CHECK-NEXT: [[RESIZE12:%.*]] = trunc i32 [[DOWNSCALE11]] to i8
-// CHECK-NEXT: store i8 [[RESIZE12]], i8* @c, align 1
+// CHECK-LABEL: @sub_csa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1
+// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.ssub.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
+// CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
+// CHECK-NEXT: [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
+// CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
+// CHECK-NEXT: [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-NEXT: store i8 [[RESIZE3]], i8* @c, align 1
+// CHECK-NEXT: ret void
+//
+void sub_csa() {
c -= sa;
}
-// CHECK-LABEL: @Multiplication(
-void Multiplication() {
-// CHECK: [[TMP0:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
-// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
-// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
-// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
-// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.smul.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
-// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
-// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
-// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
-// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
-// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+
+// SIGNED-LABEL: @mul_auf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.smul.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @mul_auf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void mul_auf() {
a *= uf;
+}
-// CHECK: [[TMP3:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE3:%.*]] = sext i32 [[TMP4]] to i47
-// CHECK-NEXT: [[RESIZE4:%.*]] = sext i32 [[TMP3]] to i47
-// CHECK-NEXT: [[UPSCALE5:%.*]] = shl i47 [[RESIZE4]], 15
-// CHECK-NEXT: [[TMP5:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[RESIZE3]], i47 [[UPSCALE5]], i32 15)
-// CHECK-NEXT: [[RESIZE6:%.*]] = trunc i47 [[TMP5]] to i32
-// CHECK-NEXT: store i32 [[RESIZE6]], i32* @a, align 4
+// CHECK-LABEL: @mul_ai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void mul_ai() {
a *= i;
+}
-// CHECK: [[TMP6:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* @c, align 1
-// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP7]] to i32
-// CHECK-NEXT: [[RESIZE7:%.*]] = sext i32 [[CONV]] to i47
-// CHECK-NEXT: [[UPSCALE8:%.*]] = shl i47 [[RESIZE7]], 15
-// CHECK-NEXT: [[RESIZE9:%.*]] = sext i32 [[TMP6]] to i47
-// CHECK-NEXT: [[TMP8:%.*]] = call i47 @llvm.smul.fix.sat.i47(i47 [[UPSCALE8]], i47 [[RESIZE9]], i32 15)
-// CHECK-NEXT: [[TMP9:%.*]] = icmp sgt i47 [[TMP8]], 2147483647
-// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP9]], i47 2147483647, i47 [[TMP8]]
-// CHECK-NEXT: [[TMP10:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
-// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP10]], i47 -2147483648, i47 [[SATMAX]]
-// CHECK-NEXT: [[RESIZE10:%.*]] = trunc i47 [[SATMIN]] to i32
-// CHECK-NEXT: [[TMP11:%.*]] = icmp slt i32 [[RESIZE10]], 0
-// CHECK-NEXT: [[TMP12:%.*]] = add i32 [[RESIZE10]], 32767
-// CHECK-NEXT: [[TMP13:%.*]] = select i1 [[TMP11]], i32 [[TMP12]], i32 [[RESIZE10]]
-// CHECK-NEXT: [[DOWNSCALE11:%.*]] = ashr i32 [[TMP13]], 15
-// CHECK-NEXT: [[RESIZE12:%.*]] = trunc i32 [[DOWNSCALE11]] to i8
-// CHECK-NEXT: store i8 [[RESIZE12]], i8* @c, align 1
+// CHECK-LABEL: @mul_csa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1
+// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.smul.fix.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
+// CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
+// CHECK-NEXT: [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
+// CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
+// CHECK-NEXT: [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-NEXT: store i8 [[RESIZE3]], i8* @c, align 1
+// CHECK-NEXT: ret void
+//
+void mul_csa() {
c *= sa;
}
-// CHECK-LABEL: @Division(
-void Division() {
-// CHECK: [[TMP0:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
-// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
-// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
-// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
-// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.sdiv.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
-// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
-// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
-// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
-// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
-// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+
+// SIGNED-LABEL: @div_auf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.sdiv.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @div_auf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP1]], i32 [[RESIZE]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void div_auf() {
a /= uf;
+}
-// CHECK: [[TMP3:%.*]] = load i32, i32* @i, align 4
-// CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* @a, align 4
-// CHECK-NEXT: [[RESIZE3:%.*]] = sext i32 [[TMP4]] to i47
-// CHECK-NEXT: [[RESIZE4:%.*]] = sext i32 [[TMP3]] to i47
-// CHECK-NEXT: [[UPSCALE5:%.*]] = shl i47 [[RESIZE4]], 15
-// CHECK-NEXT: [[TMP5:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[RESIZE3]], i47 [[UPSCALE5]], i32 15)
-// CHECK-NEXT: [[RESIZE6:%.*]] = trunc i47 [[TMP5]] to i32
-// CHECK-NEXT: store i32 [[RESIZE6]], i32* @a, align 4
+// CHECK-LABEL: @div_ai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void div_ai() {
a /= i;
+}
-// CHECK: [[TMP6:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* @c, align 1
-// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP7]] to i32
-// CHECK-NEXT: [[RESIZE7:%.*]] = sext i32 [[CONV]] to i47
-// CHECK-NEXT: [[UPSCALE8:%.*]] = shl i47 [[RESIZE7]], 15
-// CHECK-NEXT: [[RESIZE9:%.*]] = sext i32 [[TMP6]] to i47
-// CHECK-NEXT: [[TMP8:%.*]] = call i47 @llvm.sdiv.fix.sat.i47(i47 [[UPSCALE8]], i47 [[RESIZE9]], i32 15)
-// CHECK-NEXT: [[TMP9:%.*]] = icmp sgt i47 [[TMP8]], 2147483647
-// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP9]], i47 2147483647, i47 [[TMP8]]
-// CHECK-NEXT: [[TMP10:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
-// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP10]], i47 -2147483648, i47 [[SATMAX]]
-// CHECK-NEXT: [[RESIZE10:%.*]] = trunc i47 [[SATMIN]] to i32
-// CHECK-NEXT: [[TMP11:%.*]] = icmp slt i32 [[RESIZE10]], 0
-// CHECK-NEXT: [[TMP12:%.*]] = add i32 [[RESIZE10]], 32767
-// CHECK-NEXT: [[TMP13:%.*]] = select i1 [[TMP11]], i32 [[TMP12]], i32 [[RESIZE10]]
-// CHECK-NEXT: [[DOWNSCALE11:%.*]] = ashr i32 [[TMP13]], 15
-// CHECK-NEXT: [[RESIZE12:%.*]] = trunc i32 [[DOWNSCALE11]] to i8
-// CHECK-NEXT: store i8 [[RESIZE12]], i8* @c, align 1
+// CHECK-LABEL: @div_csa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1
+// CHECK-NEXT: [[CONV:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.sat.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i47 [[TMP2]], 2147483647
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i47 2147483647, i47 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i47 [[SATMAX]], -2147483648
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i47 -2147483648, i47 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[SATMIN]] to i32
+// CHECK-NEXT: [[TMP5:%.*]] = icmp slt i32 [[RESIZE2]], 0
+// CHECK-NEXT: [[TMP6:%.*]] = add i32 [[RESIZE2]], 32767
+// CHECK-NEXT: [[TMP7:%.*]] = select i1 [[TMP5]], i32 [[TMP6]], i32 [[RESIZE2]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i32 [[TMP7]], 15
+// CHECK-NEXT: [[RESIZE3:%.*]] = trunc i32 [[DOWNSCALE]] to i8
+// CHECK-NEXT: store i8 [[RESIZE3]], i8* @c, align 1
+// CHECK-NEXT: ret void
+//
+void div_csa() {
c /= sa;
}
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -ffixed-point -triple x86_64-unknown-linux-gnu -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
-// Division between different fixed point types
-short _Accum sa_const = 1.0hk / 2.0hk; // CHECK-DAG: @sa_const = {{.*}}global i16 64, align 2
-_Accum a_const = 1.0hk / 2.0k; // CHECK-DAG: @a_const = {{.*}}global i32 16384, align 4
-long _Accum la_const = 1.0hk / 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 1073741824, align 8
-short _Accum sa_const2 = 0.5hr / 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 32, align 2
-short _Accum sa_const3 = 0.5r / 2.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 32, align 2
-short _Accum sa_const4 = 0.5lr / 2.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 32, align 2
-short _Accum sa_const5 = 2.0hk / 0.5lr; // CHECK-DAG: @sa_const5 = {{.*}}global i16 512, align 2
-
-// Unsigned division
-unsigned short _Accum usa_const = 3.0uhk / 2.0uhk;
-// CHECK-SIGNED-DAG: @usa_const = {{.*}}global i16 192, align 2
-// CHECK-UNSIGNED-DAG: @usa_const = {{.*}}global i16 384, align 2
-
-// Unsigned / signed
-short _Accum sa_const6 = 1.0uhk / 2.0hk;
-// CHECK-DAG: @sa_const6 = {{.*}}global i16 64, align 2
-
-// Division with negative number
-short _Accum sa_const7 = 0.5hr / (-2.0hk);
-// CHECK-DAG: @sa_const7 = {{.*}}global i16 -32, align 2
-
-// Int division
-unsigned short _Accum usa_const2 = 2 / 0.5uhk;
-// CHECK-SIGNED-DAG: @usa_const2 = {{.*}}global i16 512, align 2
-// CHECK-UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 1024, align 2
-short _Accum sa_const8 = 2 / (-0.5hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 -512, align 2
-short _Accum sa_const9 = 256 / 2.0hk; // CHECK-DAG: @sa_const9 = {{.*}}global i16 16384, align 2
-long _Fract lf_const = 0.5lr / -1; // CHECK-DAG: @lf_const = {{.*}}global i32 -1073741824, align 4
-
-// Saturated division
-_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk / (-0.25hk);
-// CHECK-DAG: @sat_sa_const = {{.*}}global i16 -32768, align 2
-_Sat unsigned short _Accum sat_usa_const = (_Sat unsigned short _Accum)128.0uhk / (0.25uhk);
-// 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 / (-0.0125hr);
-// 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 / -1;
-// CHECK-DAG: @sat_usa_const3 = {{.*}}global i16 0, align 2
-_Sat short _Accum sat_sa_const3 = (_Sat short _Accum)-128.0hk / 128;
-// CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 -128, align 2
-_Sat short _Accum sat_sa_const4 = (_Sat short _Accum)-25.7hk / 0.1lk;
-// CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
-
-// Some more cases
-short _Accum sa_const10 = 255.9921875hk / 255.9921875hk;
-// CHECK-DAG: @sa_const10 = {{.*}}global i16 128, align 2
-short _Accum sat_sa_const5 = (_Sat short _Accum)(-255.0hk - 1.0hk) / 0.0078125hk;
-// CHECK-DAG: @sat_sa_const5 = {{.*}}global i16 -32768, align 2
-_Sat short _Accum sat_sa_const6 = (_Sat short _Accum)(-255.0hk - 1.0hk) / -0.0078125hk;
-// CHECK-DAG: @sat_sa_const6 = {{.*}}global i16 32767, align 2
-short _Accum sa_const12 = 255.9921875hk / -1.0hk;
-// CHECK-DAG: @sa_const12 = {{.*}}global i16 -32767, align 2
-_Sat short _Accum sat_sa_const7 = (_Sat short _Accum)(-255.0hk - 1.0hk) / -1.0hk;
-// CHECK-DAG: @sat_sa_const7 = {{.*}}global i16 32767, align 2
-short _Accum sa_const13 = 0.0234375hk / 2.0hk;
-// CHECK-DAG: @sa_const13 = {{.*}}global i16 1, align 2
-short _Accum sa_const14 = -0.0234375hk / 2.0hk;
-// CHECK-DAG: @sa_const14 = {{.*}}global i16 -2, align 2
-short _Accum sa_const15 = -0.0078125hk / 255.28125hk;
-// CHECK-DAG: @sa_const15 = {{.*}}global i16 -1, align 2
-
-void SignedDivision() {
- // CHECK-LABEL: SignedDivision
- 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: [[TMP0:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP2]], i16* %sa, align 2
+short _Accum sa;
+_Accum a, a2, a3, a4;
+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;
+
+_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;
+_Bool b;
+
+// CHECK-LABEL: @sdiv_sasasa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sdiv_sasasa() {
sa = sa / sa;
+}
- // To larger scale and larger width
- // CHECK: [[TMP3:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP3]] to i32
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
- // CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
- // CHECK-NEXT: store i32 [[TMP5]], i32* %a, align 4
+// CHECK-LABEL: @sdiv_asaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sdiv_asaa() {
a = sa / a;
+}
- // To same scale and smaller width
- // CHECK: [[TMP6:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %sf, align 1
- // CHECK-NEXT: [[RESIZE1:%.*]] = sext i8 [[TMP7]] to i16
- // CHECK-NEXT: [[TMP8:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP8]], i16* %sa, align 2
+// CHECK-LABEL: @sdiv_sasasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sdiv_sasasf() {
sa = sa / sf;
+}
- // To smaller scale and same width.
- // CHECK: [[TMP9:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i16, i16* %f, align 2
- // CHECK-NEXT: [[RESIZE2:%.*]] = sext i16 [[TMP9]] to i24
- // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
- // CHECK-NEXT: [[RESIZE4:%.*]] = sext i16 [[TMP10]] to i24
- // CHECK-NEXT: [[TMP11:%.*]] = call i24 @llvm.sdiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
- // CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8
- // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
- // CHECK-NEXT: store i16 [[RESIZE5]], i16* %sa, align 2
+// CHECK-LABEL: @sdiv_sasaf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = call i24 @llvm.sdiv.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void sdiv_sasaf() {
sa = sa / f;
+}
- // To smaller scale and smaller width
- // CHECK: [[TMP12:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* %sf, align 1
- // CHECK-NEXT: [[RESIZE6:%.*]] = sext i8 [[TMP13]] to i32
- // CHECK-NEXT: [[UPSCALE7:%.*]] = shl i32 [[RESIZE6]], 8
- // CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP12]], i32 [[UPSCALE7]], i32 15)
- // CHECK-NEXT: store i32 [[TMP14]], i32* %a, align 4
+// CHECK-LABEL: @sdiv_aasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP0]], i32 [[UPSCALE]], i32 15)
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sdiv_aasf() {
a = a / sf;
+}
- // To larger scale and same width
- // CHECK: [[TMP15:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* %lf, align 4
- // CHECK-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP15]] to i48
- // CHECK-NEXT: [[UPSCALE9:%.*]] = shl i48 [[RESIZE8]], 16
- // CHECK-NEXT: [[RESIZE10:%.*]] = sext i32 [[TMP16]] to i48
- // CHECK-NEXT: [[TMP17:%.*]] = call i48 @llvm.sdiv.fix.i48(i48 [[UPSCALE9]], i48 [[RESIZE10]], i32 31)
- // CHECK-NEXT: [[DOWNSCALE11:%.*]] = ashr i48 [[TMP17]], 16
- // CHECK-NEXT: [[RESIZE12:%.*]] = trunc i48 [[DOWNSCALE11]] to i32
- // CHECK-NEXT: store i32 [[RESIZE12]], i32* %a, align 4
+// CHECK-LABEL: @sdiv_aalf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i48
+// CHECK-NEXT: [[TMP2:%.*]] = call i48 @llvm.sdiv.fix.i48(i48 [[UPSCALE]], i48 [[RESIZE1]], i32 31)
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i48 [[TMP2]], 16
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i48 [[DOWNSCALE]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sdiv_aalf() {
a = a / lf;
+}
- // With corresponding unsigned type
- // CHECK: [[TMP18:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[RESIZE13:%.*]] = sext i16 [[TMP18]] to i17
- // SIGNED-NEXT: [[UPSCALE14:%.*]] = shl i17 [[RESIZE13]], 1
- // SIGNED-NEXT: [[RESIZE15:%.*]] = zext i16 [[TMP19]] to i17
- // SIGNED-NEXT: [[TMP20:%.*]] = call i17 @llvm.sdiv.fix.i17(i17 [[UPSCALE14]], i17 [[RESIZE15]], i32 8)
- // SIGNED-NEXT: [[DOWNSCALE16:%.*]] = ashr i17 [[TMP20]], 1
- // SIGNED-NEXT: [[RESIZE17:%.*]] = trunc i17 [[DOWNSCALE16]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE17]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[TMP20:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP18]], i16 [[TMP19]], i32 7)
- // UNSIGNED-NEXT:store i16 [[TMP20]], i16* %sa, align 2
+// SIGNED-LABEL: @sdiv_sasausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = call i17 @llvm.sdiv.fix.i17(i17 [[UPSCALE]], i17 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sdiv_sasausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sdiv_sasausa() {
sa = sa / usa;
+}
- // With unsigned of larger scale
- // CHECK: [[TMP21:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP22:%.*]] = load i32, i32* %ua, align 4
- // SIGNED-NEXT: [[RESIZE18:%.*]] = sext i16 [[TMP21]] to i33
- // SIGNED-NEXT: [[UPSCALE19:%.*]] = shl i33 [[RESIZE18]], 9
- // SIGNED-NEXT: [[RESIZE20:%.*]] = zext i32 [[TMP22]] to i33
- // SIGNED-NEXT: [[TMP23:%.*]] = call i33 @llvm.sdiv.fix.i33(i33 [[UPSCALE19]], i33 [[RESIZE20]], i32 16)
- // SIGNED-NEXT: [[DOWNSCALE21:%.*]] = ashr i33 [[TMP23]], 1
- // SIGNED-NEXT: [[RESIZE22:%.*]] = trunc i33 [[DOWNSCALE21]] to i32
- // SIGNED-NEXT: store i32 [[RESIZE22]], i32* %a, align 4
- // UNSIGNED-NEXT:[[RESIZE13:%.*]] = sext i16 [[TMP21]] to i32
- // UNSIGNED-NEXT:[[UPSCALE14:%.*]] = shl i32 [[RESIZE13]], 8
- // UNSIGNED-NEXT:[[TMP23:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE14]], i32 [[TMP22]], i32 15)
- // UNSIGNED-NEXT:store i32 [[TMP23]], i32* %a, align 4
+// SIGNED-LABEL: @sdiv_asaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 9
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.sdiv.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sdiv_asaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sdiv_asaua() {
a = sa / ua;
+}
- // With unsigned of smaller width
- // CHECK: [[TMP24:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP25:%.*]] = load i8, i8* %usf, align 1
- // SIGNED-NEXT: [[RESIZE23:%.*]] = sext i16 [[TMP24]] to i17
- // SIGNED-NEXT: [[UPSCALE24:%.*]] = shl i17 [[RESIZE23]], 1
- // SIGNED-NEXT: [[RESIZE25:%.*]] = zext i8 [[TMP25]] to i17
- // SIGNED-NEXT: [[TMP26:%.*]] = call i17 @llvm.sdiv.fix.i17(i17 [[UPSCALE24]], i17 [[RESIZE25]], i32 8)
- // SIGNED-NEXT: [[DOWNSCALE26:%.*]] = ashr i17 [[TMP26]], 1
- // SIGNED-NEXT: [[RESIZE27:%.*]] = trunc i17 [[DOWNSCALE26]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE27]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[RESIZE15:%.*]] = zext i8 [[TMP25]] to i16
- // UNSIGNED-NEXT:[[TMP26:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP24]], i16 [[RESIZE15]], i32 7)
- // UNSIGNED-NEXT:store i16 [[TMP26]], i16* %sa, align 2
+// SIGNED-LABEL: @sdiv_sasausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = call i17 @llvm.sdiv.fix.i17(i17 [[UPSCALE]], i17 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sdiv_sasausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sdiv_sasausf() {
sa = sa / usf;
+}
- // With unsigned of larger width and smaller scale
- // CHECK: [[TMP27:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP28:%.*]] = load i32, i32* %ulf, align 4
- // SIGNED-NEXT: [[RESIZE28:%.*]] = sext i16 [[TMP27]] to i41
- // SIGNED-NEXT: [[UPSCALE29:%.*]] = shl i41 [[RESIZE28]], 25
- // SIGNED-NEXT: [[RESIZE30:%.*]] = zext i32 [[TMP28]] to i41
- // SIGNED-NEXT: [[TMP29:%.*]] = call i41 @llvm.sdiv.fix.i41(i41 [[UPSCALE29]], i41 [[RESIZE30]], i32 32)
- // SIGNED-NEXT: [[DOWNSCALE31:%.*]] = ashr i41 [[TMP29]], 25
- // SIGNED-NEXT: [[RESIZE32:%.*]] = trunc i41 [[DOWNSCALE31]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE32]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[RESIZE16:%.*]] = sext i16 [[TMP27]] to i40
- // UNSIGNED-NEXT:[[UPSCALE17:%.*]] = shl i40 [[RESIZE16]], 24
- // UNSIGNED-NEXT:[[RESIZE18:%.*]] = zext i32 [[TMP28]] to i40
- // UNSIGNED-NEXT:[[TMP29:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE17]], i40 [[RESIZE18]], i32 31)
- // UNSIGNED-NEXT:[[DOWNSCALE19:%.*]] = ashr i40 [[TMP29]], 24
- // UNSIGNED-NEXT:[[RESIZE20:%.*]] = trunc i40 [[DOWNSCALE19]] to i16
- // UNSIGNED-NEXT:store i16 [[RESIZE20]], i16* %sa, align 2
+// SIGNED-LABEL: @sdiv_sasaulf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i41
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i41 [[RESIZE]], 25
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i41
+// SIGNED-NEXT: [[TMP2:%.*]] = call i41 @llvm.sdiv.fix.i41(i41 [[UPSCALE]], i41 [[RESIZE1]], i32 32)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i41 [[TMP2]], 25
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i41 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sdiv_sasaulf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 24
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 31)
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i40 [[TMP2]], 24
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sdiv_sasaulf() {
sa = sa / ulf;
-
- // Chained divisions of the same signed type should result in the same
- // CHECK: [[TMP30:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP31:%.*]] = load i32, i32* %b, align 4
- // CHECK-NEXT: [[TMP32:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP30]], i32 [[TMP31]], i32 15)
- // CHECK-NEXT: [[TMP33:%.*]] = load i32, i32* %c, align 4
- // CHECK-NEXT: [[TMP34:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP32]], i32 [[TMP33]], i32 15)
- // CHECK-NEXT: [[TMP35:%.*]] = load i32, i32* %d, align 4
- // CHECK-NEXT: [[TMP36:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP34]], i32 [[TMP35]], i32 15)
- // CHECK-NEXT: store i32 [[TMP36]], i32* %a, align 4
- a = a / b / c / d;
}
+// CHECK-LABEL: @sdiv_aaaaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a2, align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP0]], i32 [[TMP1]], i32 15)
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @a3, align 4
+// CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP2]], i32 [[TMP3]], i32 15)
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @a4, align 4
+// CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.sdiv.fix.i32(i32 [[TMP4]], i32 [[TMP5]], i32 15)
+// CHECK-NEXT: store i32 [[TMP6]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void sdiv_aaaaa() {
+ a = a / a2 / a3 / a4;
+}
-void UnsignedDivision() {
- // CHECK-LABEL: UnsignedDivision
- unsigned short _Accum usa;
- unsigned _Accum ua;
- unsigned long _Accum ula;
-
- unsigned short _Fract usf;
- unsigned _Fract uf;
- unsigned long _Fract ulf;
- // CHECK: [[TMP0:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
- // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP2]], i16* %usa, align 2
+// SIGNED-LABEL: @udiv_usausausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @udiv_usausausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void udiv_usausausa() {
usa = usa / usa;
+}
- // CHECK: [[TMP3:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %ua, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
- // SIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16)
- // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
- // CHECK-NEXT: store i32 [[TMP5]], i32* %ua, align 4
+// SIGNED-LABEL: @udiv_uausaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 16)
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @udiv_uausaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.udiv.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void udiv_uausaua() {
ua = usa / ua;
+}
- // CHECK: [[TMP6:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %usf, align 1
- // CHECK-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16
- // SIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8)
- // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP8]], i16* %usa, align 2
+// SIGNED-LABEL: @udiv_usausausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @udiv_usausausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void udiv_usausausf() {
usa = usa / usf;
+}
- // CHECK: [[TMP9:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i16, i16* %uf, align 2
- // CHECK-NEXT: [[RESIZE2:%.*]] = zext i16 [[TMP9]] to i24
- // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
- // CHECK-NEXT: [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24
- // SIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16)
- // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
- // CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
- // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
- // CHECK-NEXT: store i16 [[RESIZE5]], i16* %usa, align 2
+// SIGNED-LABEL: @udiv_usausauf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// SIGNED-NEXT: [[TMP2:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @udiv_usausauf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i24 @llvm.udiv.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 15)
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void udiv_usausauf() {
usa = usa / uf;
}
-void IntDivision() {
- // CHECK-LABEL: IntDivision
- short _Accum sa;
- _Accum a;
- unsigned short _Accum usa;
- int i;
- unsigned int ui;
- long _Fract lf;
- _Bool b;
-
- // CHECK: [[TMP0:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* %i, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
- // CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
- // CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.sdiv.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
- // CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
- // CHECK-NEXT: store i16 [[RESIZE2]], i16* %sa, align 2
+
+// CHECK-LABEL: @int_sasai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.sdiv.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasai() {
sa = sa / i;
+}
- // CHECK: [[TMP3:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[RESIZE3:%.*]] = sext i16 [[TMP3]] to i40
- // CHECK-NEXT: [[RESIZE4:%.*]] = zext i32 [[TMP4]] to i40
- // CHECK-NEXT: [[UPSCALE5:%.*]] = shl i40 [[RESIZE4]], 7
- // CHECK-NEXT: [[TMP5:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE3]], i40 [[UPSCALE5]], i32 7)
- // CHECK-NEXT: [[RESIZE6:%.*]] = trunc i40 [[TMP5]] to i16
- // CHECK-NEXT: store i16 [[RESIZE6]], i16* %sa, align 2
+// CHECK-LABEL: @int_sasaui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasaui() {
sa = sa / ui;
+}
- // CHECK: [[TMP6:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* %i, align 4
- // SIGNED-NEXT: [[RESIZE7:%.*]] = zext i16 [[TMP6]] to i40
- // SIGNED-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP7]] to i40
- // SIGNED-NEXT: [[UPSCALE9:%.*]] = shl i40 [[RESIZE8]], 8
- // SIGNED-NEXT: [[TMP8:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE7]], i40 [[UPSCALE9]], i32 8)
- // SIGNED-NEXT: [[RESIZE10:%.*]] = trunc i40 [[TMP8]] to i16
- // UNSIGNED-NEXT: [[RESIZE7:%.*]] = zext i16 [[TMP6]] to i39
- // UNSIGNED-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP7]] to i39
- // UNSIGNED-NEXT: [[UPSCALE9:%.*]] = shl i39 [[RESIZE8]], 7
- // UNSIGNED-NEXT: [[TMP8:%.*]] = call i39 @llvm.sdiv.fix.i39(i39 [[RESIZE7]], i39 [[UPSCALE9]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE10:%.*]] = trunc i39 [[TMP8]] to i16
- // CHECK-NEXT: store i16 [[RESIZE10]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usausai(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausai(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.sdiv.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausai() {
usa = usa / i;
+}
- // CHECK: [[TMP9:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* %ui, align 4
- // SIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40
- // SIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40
- // SIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8
- // SIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8)
- // SIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
- // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39
- // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39
- // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7
- // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16
- // CHECK-NEXT: store i16 [[RESIZE14]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usausaui(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausaui(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausaui() {
usa = usa / ui;
+}
- // CHECK: [[TMP12:%.*]] = load i32, i32* %lf, align 4
- // CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[RESIZE15:%.*]] = sext i32 [[TMP12]] to i64
- // CHECK-NEXT: [[RESIZE16:%.*]] = zext i32 [[TMP13]] to i64
- // CHECK-NEXT: [[UPSCALE17:%.*]] = shl i64 [[RESIZE16]], 31
- // CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.sdiv.fix.i64(i64 [[RESIZE15]], i64 [[UPSCALE17]], i32 31)
- // CHECK-NEXT: [[RESIZE18:%.*]] = trunc i64 [[TMP14]] to i32
- // CHECK-NEXT: store i32 [[RESIZE18]], i32* %lf, align 4
+// CHECK-LABEL: @int_lflfui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i64
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE1]], 31
+// CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.sdiv.fix.i64(i64 [[RESIZE]], i64 [[UPSCALE]], i32 31)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i64 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void int_lflfui() {
lf = lf / ui;
+}
- // CHECK: [[TMP15:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP16:%.*]] = load i8, i8* %b, align 1
- // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP16]] to i1
- // CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
- // CHECK-NEXT: [[RESIZE19:%.*]] = sext i32 [[TMP15]] to i47
- // CHECK-NEXT: [[RESIZE20:%.*]] = sext i32 [[CONV]] to i47
- // CHECK-NEXT: [[UPSCALE21:%.*]] = shl i47 [[RESIZE20]], 15
- // CHECK-NEXT: [[TMP17:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[RESIZE19]], i47 [[UPSCALE21]], i32 15)
- // CHECK-NEXT: [[RESIZE22:%.*]] = trunc i47 [[TMP17]] to i32
- // CHECK-NEXT: store i32 [[RESIZE22]], i32* %a, align 4
+// CHECK-LABEL: @int_aab(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @b, align 1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aab() {
a = a / b;
+}
- // CHECK: [[TMP18:%.*]] = load i32, i32* %i, align 4
- // CHECK-NEXT: [[TMP19:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[RESIZE23:%.*]] = sext i32 [[TMP18]] to i47
- // CHECK-NEXT: [[UPSCALE24:%.*]] = shl i47 [[RESIZE23]], 15
- // CHECK-NEXT: [[RESIZE25:%.*]] = sext i32 [[TMP19]] to i47
- // CHECK-NEXT: [[TMP20:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[UPSCALE24]], i47 [[RESIZE25]], i32 15)
- // CHECK-NEXT: [[RESIZE26:%.*]] = trunc i47 [[TMP20]] to i32
- // CHECK-NEXT: store i32 [[RESIZE26]], i32* %a, align 4
+// CHECK-LABEL: @int_aia(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.sdiv.fix.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aia() {
a = i / a;
+}
- // CHECK: [[TMP21:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40
- // SIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 8
- // SIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
- // SIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8)
- // SIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
- // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39
- // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7
- // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39
- // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16
- // CHECK-NEXT: store i16 [[RESIZE30]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usauiusa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 8
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i40
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.udiv.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usauiusa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.udiv.fix.i39(i39 [[UPSCALE]], i39 [[RESIZE1]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usauiusa() {
usa = ui / usa;
+}
- // CHECK: [[TMP27:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[TMP28:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[RESIZE33:%.*]] = zext i32 [[TMP27]] to i40
- // CHECK-NEXT: [[UPSCALE34:%.*]] = shl i40 [[RESIZE33]], 7
- // CHECK-NEXT: [[RESIZE35:%.*]] = sext i16 [[TMP28]] to i40
- // CHECK-NEXT: [[TMP29:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE34]], i40 [[RESIZE35]], i32 7)
- // CHECK-NEXT: [[RESIZE36:%.*]] = trunc i40 [[TMP29]] to i16
- // CHECK-NEXT: store i16 [[RESIZE36]], i16* %sa, align 2
+// CHECK-LABEL: @int_sauisa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 7
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i40
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sauisa() {
sa = ui / sa;
}
-void SaturatedDivision() {
- // CHECK-LABEL: SaturatedDivision
- 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.sdiv.fix.sat.i16(i16 [[SA]], i16 [[SA_SAT]], i32 7)
- // CHECK-NEXT: store i16 [[SUM]], i16* %sa_sat, align 2
+
+// CHECK-LABEL: @sat_sassasas(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.sdiv.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasas() {
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.udiv.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8)
- // 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.udiv.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
- // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+// SIGNED-LABEL: @sat_usasusausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusausas() {
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.udiv.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16)
- // 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.udiv.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
- // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+// SIGNED-LABEL: @sat_uasuausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.udiv.fix.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]], i32 16)
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua_sat, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_uasuausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i31
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i31 [[RESIZE1]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i31 @llvm.udiv.fix.sat.i31(i31 [[RESIZE]], i31 [[UPSCALE]], i32 15)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i31 [[TMP2]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE2]], i32* @ua_sat, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sat_uasuausas() {
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.sdiv.fix.sat.i39(i39 [[SA_SAT_EXT]], i39 [[I]], i32 7)
- // 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
+// CHECK-LABEL: @sat_sassasi(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.sdiv.fix.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 -32768, i39 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasi() {
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.sdiv.fix.sat.i40(i40 [[SA_SAT_EXT]], i40 [[I]], i32 7)
- // 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
+// CHECK-LABEL: @sat_sassasui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 32767, i40 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 -32768, i40 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasui() {
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.udiv.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16)
- // 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.udiv.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
- // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+// SIGNED-LABEL: @sat_ufsufsufs(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.udiv.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 16)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @uf_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_ufsufsufs(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.udiv.fix.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]], i32 15)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @uf_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_ufsufsufs() {
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.sdiv.fix.sat.i40(i40 [[USA_SAT_RESIZE]], i40 [[I_UPSCALE]], i32 8)
- // 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.sdiv.fix.sat.i39(i39 [[USA_SAT_RESIZE]], i39 [[I_UPSCALE]], i32 7)
- // 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
+// SIGNED-LABEL: @sat_usasusasi(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.sdiv.fix.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 65535
+// SIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 65535, i40 [[TMP2]]
+// SIGNED-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], 0
+// SIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 0, i40 [[SATMAX]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusasi(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.sdiv.fix.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// UNSIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// UNSIGNED-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 0, i39 [[SATMAX]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusasi() {
usa_sat = usa_sat / i;
}
--- /dev/null
+// 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
+
+// Division between different fixed point types
+short _Accum sa_const = 1.0hk / 2.0hk;
+// CHECK-DAG: @sa_const = {{.*}}global i16 64, align 2
+_Accum a_const = 1.0hk / 2.0k;
+// CHECK-DAG: @a_const = {{.*}}global i32 16384, align 4
+long _Accum la_const = 1.0hk / 2.0lk;
+// CHECK-DAG: @la_const = {{.*}}global i64 1073741824, align 8
+short _Accum sa_const2 = 0.5hr / 2.0hk;
+// CHECK-DAG: @sa_const2 = {{.*}}global i16 32, align 2
+short _Accum sa_const3 = 0.5r / 2.0hk;
+// CHECK-DAG: @sa_const3 = {{.*}}global i16 32, align 2
+short _Accum sa_const4 = 0.5lr / 2.0hk;
+// CHECK-DAG: @sa_const4 = {{.*}}global i16 32, align 2
+short _Accum sa_const5 = 2.0hk / 0.5lr;
+// CHECK-DAG: @sa_const5 = {{.*}}global i16 512, align 2
+
+// Unsigned division
+unsigned short _Accum usa_const = 3.0uhk / 2.0uhk;
+// SIGNED-DAG: @usa_const = {{.*}}global i16 384, align 2
+// UNSIGNED-DAG: @usa_const = {{.*}}global i16 192, align 2
+
+// Unsigned / signed
+short _Accum sa_const6 = 1.0uhk / 2.0hk;
+// CHECK-DAG: @sa_const6 = {{.*}}global i16 64, align 2
+
+// Division with negative number
+short _Accum sa_const7 = 0.5hr / (-2.0hk);
+// CHECK-DAG: @sa_const7 = {{.*}}global i16 -32, align 2
+
+// Int division
+unsigned short _Accum usa_const2 = 2 / 0.5uhk;
+// SIGNED-DAG: @usa_const2 = {{.*}}global i16 1024, align 2
+// UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 512, align 2
+short _Accum sa_const8 = 2 / (-0.5hk);
+// CHECK-DAG: @sa_const8 = {{.*}}global i16 -512, align 2
+short _Accum sa_const9 = 256 / 2.0hk;
+// CHECK-DAG: @sa_const9 = {{.*}}global i16 16384, align 2
+long _Fract lf_const = 0.5lr / -1;
+// CHECK-DAG: @lf_const = {{.*}}global i32 -1073741824, align 4
+
+// Saturated division
+_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk / (-0.25hk);
+// CHECK-DAG: @sat_sa_const = {{.*}}global i16 -32768, align 2
+_Sat unsigned short _Accum sat_usa_const = (_Sat unsigned short _Accum)128.0uhk / (0.25uhk);
+// SIGNED-DAG: @sat_usa_const = {{.*}}global i16 -1, align 2
+// UNSIGNED-DAG: @sat_usa_const = {{.*}}global i16 32767, align 2
+_Sat short _Accum sat_sa_const2 = (_Sat short _Accum)-128.0hk / (-0.0125hr);
+// 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-DAG: @sat_usa_const2 = {{.*}}global i16 0, align 2
+_Sat unsigned short _Accum sat_usa_const3 = (_Sat unsigned short _Accum)0.5uhk / -1;
+// CHECK-DAG: @sat_usa_const3 = {{.*}}global i16 0, align 2
+_Sat short _Accum sat_sa_const3 = (_Sat short _Accum)-128.0hk / 128;
+// CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 -128, align 2
+_Sat short _Accum sat_sa_const4 = (_Sat short _Accum)-25.7hk / 0.1lk;
+// CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
+
+// Some more cases
+short _Accum sa_const10 = 255.9921875hk / 255.9921875hk;
+// CHECK-DAG: @sa_const10 = {{.*}}global i16 128, align 2
+short _Accum sat_sa_const5 = (_Sat short _Accum)(-255.0hk - 1.0hk) / 0.0078125hk;
+// CHECK-DAG: @sat_sa_const5 = {{.*}}global i16 -32768, align 2
+_Sat short _Accum sat_sa_const6 = (_Sat short _Accum)(-255.0hk - 1.0hk) / -0.0078125hk;
+// CHECK-DAG: @sat_sa_const6 = {{.*}}global i16 32767, align 2
+short _Accum sa_const12 = 255.9921875hk / -1.0hk;
+// CHECK-DAG: @sa_const12 = {{.*}}global i16 -32767, align 2
+_Sat short _Accum sat_sa_const7 = (_Sat short _Accum)(-255.0hk - 1.0hk) / -1.0hk;
+// CHECK-DAG: @sat_sa_const7 = {{.*}}global i16 32767, align 2
+short _Accum sa_const13 = 0.0234375hk / 2.0hk;
+// CHECK-DAG: @sa_const13 = {{.*}}global i16 1, align 2
+short _Accum sa_const14 = -0.0234375hk / 2.0hk;
+// CHECK-DAG: @sa_const14 = {{.*}}global i16 -2, align 2
+short _Accum sa_const15 = -0.0078125hk / 255.28125hk;
+// CHECK-DAG: @sa_const15 = {{.*}}global i16 -1, align 2
-// 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
-
-// Multiplication between different fixed point types
-short _Accum sa_const = 2.0hk * 2.0hk; // CHECK-DAG: @sa_const = {{.*}}global i16 512, align 2
-_Accum a_const = 3.0hk * 2.0k; // CHECK-DAG: @a_const = {{.*}}global i32 196608, align 4
-long _Accum la_const = 4.0hk * 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 17179869184, align 8
-short _Accum sa_const2 = 0.5hr * 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 128, align 2
-short _Accum sa_const3 = 0.5r * 3.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 192, align 2
-short _Accum sa_const4 = 0.5lr * 4.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 256, align 2
-
-// Unsigned multiplication
-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 = 20.0uhk * 3.0hk;
-// CHECK-DAG: @sa_const5 = {{.*}}global i16 7680, align 2
-
-// Multiplication with negative number
-short _Accum sa_const6 = 0.5hr * (-2.0hk);
-// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128, align 2
-
-// Int multiplication
-unsigned short _Accum usa_const2 = 5 * 10.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 = 3 * (-0.5hk); // CHECK-DAG: @sa_const7 = {{.*}}global i16 -192, align 2
-short _Accum sa_const8 = 100 * (-2.0hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 -25600, align 2
-long _Fract lf_const = -0.25lr * 3; // CHECK-DAG: @lf_const = {{.*}}global i32 -1610612736, align 4
-
-// Saturated multiplication
-_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk * 3.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 -32768, align 2
-_Sat unsigned short _Accum sat_usa_const2 = (_Sat unsigned short _Accum)128.0uhk * 30;
-// 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 SignedMultiplication() {
- // CHECK-LABEL: SignedMultiplication
- 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: [[TMP0:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP2]], i16* %sa, align 2
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// 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
+
+short _Accum sa;
+_Accum a, a2, a3, a4;
+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;
+
+_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;
+_Bool b;
+
+// CHECK-LABEL: @smul_sasasa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void smul_sasasa() {
sa = sa * sa;
+}
- // To larger scale and larger width
- // CHECK: [[TMP3:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP3]] to i32
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
- // CHECK-NEXT: [[TMP5:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
- // CHECK-NEXT: store i32 [[TMP5]], i32* %a, align 4
+// CHECK-LABEL: @smul_asaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void smul_asaa() {
a = sa * a;
+}
- // To same scale and smaller width
- // CHECK: [[TMP6:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %sf, align 1
- // CHECK-NEXT: [[RESIZE1:%.*]] = sext i8 [[TMP7]] to i16
- // CHECK-NEXT: [[TMP8:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP8]], i16* %sa, align 2
+// CHECK-LABEL: @smul_sasasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void smul_sasasf() {
sa = sa * sf;
+}
- // To smaller scale and same width.
- // CHECK: [[TMP9:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i16, i16* %f, align 2
- // CHECK-NEXT: [[RESIZE2:%.*]] = sext i16 [[TMP9]] to i24
- // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
- // CHECK-NEXT: [[RESIZE4:%.*]] = sext i16 [[TMP10]] to i24
- // CHECK-NEXT: [[TMP11:%.*]] = call i24 @llvm.smul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
- // CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP11]], 8
- // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
- // CHECK-NEXT: store i16 [[RESIZE5]], i16* %sa, align 2
+// CHECK-LABEL: @smul_sasaf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = call i24 @llvm.smul.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void smul_sasaf() {
sa = sa * f;
+}
- // To smaller scale and smaller width
- // CHECK: [[TMP12:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP13:%.*]] = load i8, i8* %sf, align 1
- // CHECK-NEXT: [[RESIZE6:%.*]] = sext i8 [[TMP13]] to i32
- // CHECK-NEXT: [[UPSCALE7:%.*]] = shl i32 [[RESIZE6]], 8
- // CHECK-NEXT: [[TMP14:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP12]], i32 [[UPSCALE7]], i32 15)
- // CHECK-NEXT: store i32 [[TMP14]], i32* %a, align 4
+// CHECK-LABEL: @smul_aasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP0]], i32 [[UPSCALE]], i32 15)
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void smul_aasf() {
a = a * sf;
+}
- // To larger scale and same width
- // CHECK: [[TMP15:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP16:%.*]] = load i32, i32* %lf, align 4
- // CHECK-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP15]] to i48
- // CHECK-NEXT: [[UPSCALE9:%.*]] = shl i48 [[RESIZE8]], 16
- // CHECK-NEXT: [[RESIZE10:%.*]] = sext i32 [[TMP16]] to i48
- // CHECK-NEXT: [[TMP17:%.*]] = call i48 @llvm.smul.fix.i48(i48 [[UPSCALE9]], i48 [[RESIZE10]], i32 31)
- // CHECK-NEXT: [[DOWNSCALE11:%.*]] = ashr i48 [[TMP17]], 16
- // CHECK-NEXT: [[RESIZE12:%.*]] = trunc i48 [[DOWNSCALE11]] to i32
- // CHECK-NEXT: store i32 [[RESIZE12]], i32* %a, align 4
+// CHECK-LABEL: @smul_aalf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i48
+// CHECK-NEXT: [[TMP2:%.*]] = call i48 @llvm.smul.fix.i48(i48 [[UPSCALE]], i48 [[RESIZE1]], i32 31)
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i48 [[TMP2]], 16
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i48 [[DOWNSCALE]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void smul_aalf() {
a = a * lf;
+}
- // With corresponding unsigned type
- // CHECK: [[TMP18:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP19:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[RESIZE13:%.*]] = sext i16 [[TMP18]] to i17
- // SIGNED-NEXT: [[UPSCALE14:%.*]] = shl i17 [[RESIZE13]], 1
- // SIGNED-NEXT: [[RESIZE15:%.*]] = zext i16 [[TMP19]] to i17
- // SIGNED-NEXT: [[TMP20:%.*]] = call i17 @llvm.smul.fix.i17(i17 [[UPSCALE14]], i17 [[RESIZE15]], i32 8)
- // SIGNED-NEXT: [[DOWNSCALE16:%.*]] = ashr i17 [[TMP20]], 1
- // SIGNED-NEXT: [[RESIZE17:%.*]] = trunc i17 [[DOWNSCALE16]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE17]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[TMP20:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP18]], i16 [[TMP19]], i32 7)
- // UNSIGNED-NEXT:store i16 [[TMP20]], i16* %sa, align 2
+// SIGNED-LABEL: @smul_sasausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = call i17 @llvm.smul.fix.i17(i17 [[UPSCALE]], i17 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @smul_sasausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void smul_sasausa() {
sa = sa * usa;
+}
- // With unsigned of larger scale
- // CHECK: [[TMP21:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP22:%.*]] = load i32, i32* %ua, align 4
- // SIGNED-NEXT: [[RESIZE18:%.*]] = sext i16 [[TMP21]] to i33
- // SIGNED-NEXT: [[UPSCALE19:%.*]] = shl i33 [[RESIZE18]], 9
- // SIGNED-NEXT: [[RESIZE20:%.*]] = zext i32 [[TMP22]] to i33
- // SIGNED-NEXT: [[TMP23:%.*]] = call i33 @llvm.smul.fix.i33(i33 [[UPSCALE19]], i33 [[RESIZE20]], i32 16)
- // SIGNED-NEXT: [[DOWNSCALE21:%.*]] = ashr i33 [[TMP23]], 1
- // SIGNED-NEXT: [[RESIZE22:%.*]] = trunc i33 [[DOWNSCALE21]] to i32
- // SIGNED-NEXT: store i32 [[RESIZE22]], i32* %a, align 4
- // UNSIGNED-NEXT:[[RESIZE13:%.*]] = sext i16 [[TMP21]] to i32
- // UNSIGNED-NEXT:[[UPSCALE14:%.*]] = shl i32 [[RESIZE13]], 8
- // UNSIGNED-NEXT:[[TMP23:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE14]], i32 [[TMP22]], i32 15)
- // UNSIGNED-NEXT:store i32 [[TMP23]], i32* %a, align 4
+// SIGNED-LABEL: @smul_asaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 9
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = call i33 @llvm.smul.fix.i33(i33 [[UPSCALE]], i33 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @smul_asaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void smul_asaua() {
a = sa * ua;
+}
- // With unsigned of smaller width
- // CHECK: [[TMP24:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP25:%.*]] = load i8, i8* %usf, align 1
- // SIGNED-NEXT: [[RESIZE23:%.*]] = sext i16 [[TMP24]] to i17
- // SIGNED-NEXT: [[UPSCALE24:%.*]] = shl i17 [[RESIZE23]], 1
- // SIGNED-NEXT: [[RESIZE25:%.*]] = zext i8 [[TMP25]] to i17
- // SIGNED-NEXT: [[TMP26:%.*]] = call i17 @llvm.smul.fix.i17(i17 [[UPSCALE24]], i17 [[RESIZE25]], i32 8)
- // SIGNED-NEXT: [[DOWNSCALE26:%.*]] = ashr i17 [[TMP26]], 1
- // SIGNED-NEXT: [[RESIZE27:%.*]] = trunc i17 [[DOWNSCALE26]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE27]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[RESIZE15:%.*]] = zext i8 [[TMP25]] to i16
- // UNSIGNED-NEXT:[[TMP26:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP24]], i16 [[RESIZE15]], i32 7)
- // UNSIGNED-NEXT:store i16 [[TMP26]], i16* %sa, align 2
+// SIGNED-LABEL: @smul_sasausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = call i17 @llvm.smul.fix.i17(i17 [[UPSCALE]], i17 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @smul_sasausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void smul_sasausf() {
sa = sa * usf;
+}
- // With unsigned of larger width and smaller scale
- // CHECK: [[TMP27:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP28:%.*]] = load i32, i32* %ulf, align 4
- // SIGNED-NEXT: [[RESIZE28:%.*]] = sext i16 [[TMP27]] to i41
- // SIGNED-NEXT: [[UPSCALE29:%.*]] = shl i41 [[RESIZE28]], 25
- // SIGNED-NEXT: [[RESIZE30:%.*]] = zext i32 [[TMP28]] to i41
- // SIGNED-NEXT: [[TMP29:%.*]] = call i41 @llvm.smul.fix.i41(i41 [[UPSCALE29]], i41 [[RESIZE30]], i32 32)
- // SIGNED-NEXT: [[DOWNSCALE31:%.*]] = ashr i41 [[TMP29]], 25
- // SIGNED-NEXT: [[RESIZE32:%.*]] = trunc i41 [[DOWNSCALE31]] to i16
- // SIGNED-NEXT: store i16 [[RESIZE32]], i16* %sa, align 2
- // UNSIGNED-NEXT:[[RESIZE16:%.*]] = sext i16 [[TMP27]] to i40
- // UNSIGNED-NEXT:[[UPSCALE17:%.*]] = shl i40 [[RESIZE16]], 24
- // UNSIGNED-NEXT:[[RESIZE18:%.*]] = zext i32 [[TMP28]] to i40
- // UNSIGNED-NEXT:[[TMP29:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE17]], i40 [[RESIZE18]], i32 31)
- // UNSIGNED-NEXT:[[DOWNSCALE19:%.*]] = ashr i40 [[TMP29]], 24
- // UNSIGNED-NEXT:[[RESIZE20:%.*]] = trunc i40 [[DOWNSCALE19]] to i16
- // UNSIGNED-NEXT:store i16 [[RESIZE20]], i16* %sa, align 2
+// SIGNED-LABEL: @smul_sasaulf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i41
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i41 [[RESIZE]], 25
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i41
+// SIGNED-NEXT: [[TMP2:%.*]] = call i41 @llvm.smul.fix.i41(i41 [[UPSCALE]], i41 [[RESIZE1]], i32 32)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i41 [[TMP2]], 25
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i41 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @smul_sasaulf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 24
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 31)
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i40 [[TMP2]], 24
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void smul_sasaulf() {
sa = sa * ulf;
-
- // Chained multiplications of the same signed type should result in the same
- // CHECK: [[TMP30:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP31:%.*]] = load i32, i32* %b, align 4
- // CHECK-NEXT: [[TMP32:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP30]], i32 [[TMP31]], i32 15)
- // CHECK-NEXT: [[TMP33:%.*]] = load i32, i32* %c, align 4
- // CHECK-NEXT: [[TMP34:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP32]], i32 [[TMP33]], i32 15)
- // CHECK-NEXT: [[TMP35:%.*]] = load i32, i32* %d, align 4
- // CHECK-NEXT: [[TMP36:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP34]], i32 [[TMP35]], i32 15)
- // CHECK-NEXT: store i32 [[TMP36]], i32* %a, align 4
- a = a * b * c * d;
}
+// CHECK-LABEL: @smul_aaaaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a2, align 4
+// CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP0]], i32 [[TMP1]], i32 15)
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @a3, align 4
+// CHECK-NEXT: [[TMP4:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP2]], i32 [[TMP3]], i32 15)
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @a4, align 4
+// CHECK-NEXT: [[TMP6:%.*]] = call i32 @llvm.smul.fix.i32(i32 [[TMP4]], i32 [[TMP5]], i32 15)
+// CHECK-NEXT: store i32 [[TMP6]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void smul_aaaaa() {
+ a = a * a2 * a3 * a4;
+}
-void UnsignedMultiplication() {
- // CHECK-LABEL: UnsignedMultiplication
- unsigned short _Accum usa;
- unsigned _Accum ua;
- unsigned long _Accum ula;
-
- unsigned short _Fract usf;
- unsigned _Fract uf;
- unsigned long _Fract ulf;
- // CHECK: [[TMP0:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
- // UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP2]], i16* %usa, align 2
+// SIGNED-LABEL: @umul_usausausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @umul_usausausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void umul_usausausa() {
usa = usa * usa;
+}
- // CHECK: [[TMP3:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %ua, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP3]] to i32
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
- // SIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 16)
- // UNSIGNED-NEXT: [[TMP5:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP4]], i32 15)
- // CHECK-NEXT: store i32 [[TMP5]], i32* %ua, align 4
+// SIGNED-LABEL: @umul_uausaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 16)
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @umul_uausaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.umul.fix.i32(i32 [[UPSCALE]], i32 [[TMP1]], i32 15)
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void umul_uausaua() {
ua = usa * ua;
+}
- // CHECK: [[TMP6:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i8, i8* %usf, align 1
- // CHECK-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP7]] to i16
- // SIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 8)
- // UNSIGNED-NEXT: [[TMP8:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP6]], i16 [[RESIZE1]], i32 7)
- // CHECK-NEXT: store i16 [[TMP8]], i16* %usa, align 2
+// SIGNED-LABEL: @umul_usausausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @umul_usausausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.i16(i16 [[TMP0]], i16 [[RESIZE]], i32 7)
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void umul_usausausf() {
usa = usa * usf;
+}
- // CHECK: [[TMP9:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i16, i16* %uf, align 2
- // CHECK-NEXT: [[RESIZE2:%.*]] = zext i16 [[TMP9]] to i24
- // CHECK-NEXT: [[UPSCALE3:%.*]] = shl i24 [[RESIZE2]], 8
- // CHECK-NEXT: [[RESIZE4:%.*]] = zext i16 [[TMP10]] to i24
- // SIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 16)
- // UNSIGNED-NEXT: [[TMP11:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE3]], i24 [[RESIZE4]], i32 15)
- // CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP11]], 8
- // CHECK-NEXT: [[RESIZE5:%.*]] = trunc i24 [[DOWNSCALE]] to i16
- // CHECK-NEXT: store i16 [[RESIZE5]], i16* %usa, align 2
+// SIGNED-LABEL: @umul_usausauf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// SIGNED-NEXT: [[TMP2:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 16)
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @umul_usausauf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i24 @llvm.umul.fix.i24(i24 [[UPSCALE]], i24 [[RESIZE1]], i32 15)
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void umul_usausauf() {
usa = usa * uf;
}
-void IntMultiplication() {
- // CHECK-LABEL: IntMultiplication
- short _Accum sa;
- _Accum a;
- unsigned short _Accum usa;
- int i;
- unsigned int ui;
- long _Fract lf;
- _Bool b;
-
- // CHECK: [[TMP0:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* %i, align 4
- // CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
- // CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
- // CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
- // CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.smul.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
- // CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
- // CHECK-NEXT: store i16 [[RESIZE2]], i16* %sa, align 2
+
+// CHECK-LABEL: @int_sasai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.smul.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasai() {
sa = sa * i;
+}
- // CHECK: [[TMP3:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[RESIZE3:%.*]] = sext i16 [[TMP3]] to i40
- // CHECK-NEXT: [[RESIZE4:%.*]] = zext i32 [[TMP4]] to i40
- // CHECK-NEXT: [[UPSCALE5:%.*]] = shl i40 [[RESIZE4]], 7
- // CHECK-NEXT: [[TMP5:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE3]], i40 [[UPSCALE5]], i32 7)
- // CHECK-NEXT: [[RESIZE6:%.*]] = trunc i40 [[TMP5]] to i16
- // CHECK-NEXT: store i16 [[RESIZE6]], i16* %sa, align 2
+// CHECK-LABEL: @int_sasaui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasaui() {
sa = sa * ui;
+}
- // CHECK: [[TMP6:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP7:%.*]] = load i32, i32* %i, align 4
- // SIGNED-NEXT: [[RESIZE7:%.*]] = zext i16 [[TMP6]] to i40
- // SIGNED-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP7]] to i40
- // SIGNED-NEXT: [[UPSCALE9:%.*]] = shl i40 [[RESIZE8]], 8
- // SIGNED-NEXT: [[TMP8:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE7]], i40 [[UPSCALE9]], i32 8)
- // SIGNED-NEXT: [[RESIZE10:%.*]] = trunc i40 [[TMP8]] to i16
- // UNSIGNED-NEXT: [[RESIZE7:%.*]] = zext i16 [[TMP6]] to i39
- // UNSIGNED-NEXT: [[RESIZE8:%.*]] = sext i32 [[TMP7]] to i39
- // UNSIGNED-NEXT: [[UPSCALE9:%.*]] = shl i39 [[RESIZE8]], 7
- // UNSIGNED-NEXT: [[TMP8:%.*]] = call i39 @llvm.smul.fix.i39(i39 [[RESIZE7]], i39 [[UPSCALE9]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE10:%.*]] = trunc i39 [[TMP8]] to i16
- // CHECK-NEXT: store i16 [[RESIZE10]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usausai(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausai(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.smul.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausai() {
usa = usa * i;
+}
- // CHECK: [[TMP9:%.*]] = load i16, i16* %usa, align 2
- // CHECK-NEXT: [[TMP10:%.*]] = load i32, i32* %ui, align 4
- // SIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i40
- // SIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i40
- // SIGNED-NEXT: [[UPSCALE13:%.*]] = shl i40 [[RESIZE12]], 8
- // SIGNED-NEXT: [[TMP11:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[RESIZE11]], i40 [[UPSCALE13]], i32 8)
- // SIGNED-NEXT: [[RESIZE14:%.*]] = trunc i40 [[TMP11]] to i16
- // UNSIGNED-NEXT: [[RESIZE11:%.*]] = zext i16 [[TMP9]] to i39
- // UNSIGNED-NEXT: [[RESIZE12:%.*]] = zext i32 [[TMP10]] to i39
- // UNSIGNED-NEXT: [[UPSCALE13:%.*]] = shl i39 [[RESIZE12]], 7
- // UNSIGNED-NEXT: [[TMP11:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[RESIZE11]], i39 [[UPSCALE13]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE14:%.*]] = trunc i39 [[TMP11]] to i16
- // CHECK-NEXT: store i16 [[RESIZE14]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usausaui(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausaui(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausaui() {
usa = usa * ui;
+}
- // CHECK: [[TMP12:%.*]] = load i32, i32* %lf, align 4
- // CHECK-NEXT: [[TMP13:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[RESIZE15:%.*]] = sext i32 [[TMP12]] to i64
- // CHECK-NEXT: [[RESIZE16:%.*]] = zext i32 [[TMP13]] to i64
- // CHECK-NEXT: [[UPSCALE17:%.*]] = shl i64 [[RESIZE16]], 31
- // CHECK-NEXT: [[TMP14:%.*]] = call i64 @llvm.smul.fix.i64(i64 [[RESIZE15]], i64 [[UPSCALE17]], i32 31)
- // CHECK-NEXT: [[RESIZE18:%.*]] = trunc i64 [[TMP14]] to i32
- // CHECK-NEXT: store i32 [[RESIZE18]], i32* %lf, align 4
+// CHECK-LABEL: @int_lflfui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i64
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE1]], 31
+// CHECK-NEXT: [[TMP2:%.*]] = call i64 @llvm.smul.fix.i64(i64 [[RESIZE]], i64 [[UPSCALE]], i32 31)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i64 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void int_lflfui() {
lf = lf * ui;
+}
- // CHECK: [[TMP15:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[TMP16:%.*]] = load i8, i8* %b, align 1
- // CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP16]] to i1
- // CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
- // CHECK-NEXT: [[RESIZE19:%.*]] = sext i32 [[TMP15]] to i47
- // CHECK-NEXT: [[RESIZE20:%.*]] = sext i32 [[CONV]] to i47
- // CHECK-NEXT: [[UPSCALE21:%.*]] = shl i47 [[RESIZE20]], 15
- // CHECK-NEXT: [[TMP17:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[RESIZE19]], i47 [[UPSCALE21]], i32 15)
- // CHECK-NEXT: [[RESIZE22:%.*]] = trunc i47 [[TMP17]] to i32
- // CHECK-NEXT: store i32 [[RESIZE22]], i32* %a, align 4
+// CHECK-LABEL: @int_aab(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @b, align 1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[RESIZE]], i47 [[UPSCALE]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aab() {
a = a * b;
+}
- // CHECK: [[TMP18:%.*]] = load i32, i32* %i, align 4
- // CHECK-NEXT: [[TMP19:%.*]] = load i32, i32* %a, align 4
- // CHECK-NEXT: [[RESIZE23:%.*]] = sext i32 [[TMP18]] to i47
- // CHECK-NEXT: [[UPSCALE24:%.*]] = shl i47 [[RESIZE23]], 15
- // CHECK-NEXT: [[RESIZE25:%.*]] = sext i32 [[TMP19]] to i47
- // CHECK-NEXT: [[TMP20:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[UPSCALE24]], i47 [[RESIZE25]], i32 15)
- // CHECK-NEXT: [[RESIZE26:%.*]] = trunc i47 [[TMP20]] to i32
- // CHECK-NEXT: store i32 [[RESIZE26]], i32* %a, align 4
+// CHECK-LABEL: @int_aia(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE]], 15
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i47
+// CHECK-NEXT: [[TMP2:%.*]] = call i47 @llvm.smul.fix.i47(i47 [[UPSCALE]], i47 [[RESIZE1]], i32 15)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aia() {
a = i * a;
+}
- // CHECK: [[TMP21:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[TMP22:%.*]] = load i16, i16* %usa, align 2
- // SIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i40
- // SIGNED-NEXT: [[UPSCALE28:%.*]] = shl i40 [[RESIZE27]], 8
- // SIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i40
- // SIGNED-NEXT: [[TMP23:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[UPSCALE28]], i40 [[RESIZE29]], i32 8)
- // SIGNED-NEXT: [[RESIZE30:%.*]] = trunc i40 [[TMP23]] to i16
- // UNSIGNED-NEXT: [[RESIZE27:%.*]] = zext i32 [[TMP21]] to i39
- // UNSIGNED-NEXT: [[UPSCALE28:%.*]] = shl i39 [[RESIZE27]], 7
- // UNSIGNED-NEXT: [[RESIZE29:%.*]] = zext i16 [[TMP22]] to i39
- // UNSIGNED-NEXT: [[TMP23:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[UPSCALE28]], i39 [[RESIZE29]], i32 7)
- // UNSIGNED-NEXT: [[RESIZE30:%.*]] = trunc i39 [[TMP23]] to i16
- // CHECK-NEXT: store i16 [[RESIZE30]], i16* %usa, align 2
+// SIGNED-LABEL: @int_usauiusa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 8
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i40
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.umul.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 8)
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usauiusa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE]], 7
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.umul.fix.i39(i39 [[UPSCALE]], i39 [[RESIZE1]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usauiusa() {
usa = ui * usa;
+}
- // CHECK: [[TMP27:%.*]] = load i32, i32* %ui, align 4
- // CHECK-NEXT: [[TMP28:%.*]] = load i16, i16* %sa, align 2
- // CHECK-NEXT: [[RESIZE33:%.*]] = zext i32 [[TMP27]] to i40
- // CHECK-NEXT: [[UPSCALE34:%.*]] = shl i40 [[RESIZE33]], 7
- // CHECK-NEXT: [[RESIZE35:%.*]] = sext i16 [[TMP28]] to i40
- // CHECK-NEXT: [[TMP29:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE34]], i40 [[RESIZE35]], i32 7)
- // CHECK-NEXT: [[RESIZE36:%.*]] = trunc i40 [[TMP29]] to i16
- // CHECK-NEXT: store i16 [[RESIZE36]], i16* %sa, align 2
+// CHECK-LABEL: @int_sauisa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i32 [[TMP0]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 7
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i40
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.i40(i40 [[UPSCALE]], i40 [[RESIZE1]], i32 7)
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sauisa() {
sa = ui * sa;
}
-void SaturatedMultiplication() {
- // CHECK-LABEL: SaturatedMultiplication
- 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.smul.fix.sat.i16(i16 [[SA]], i16 [[SA_SAT]], i32 7)
- // CHECK-NEXT: store i16 [[SUM]], i16* %sa_sat, align 2
+
+// CHECK-LABEL: @sat_sassasas(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.smul.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 7)
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasas() {
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.umul.fix.sat.i16(i16 [[USA]], i16 [[USA_SAT]], i32 8)
- // 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.umul.fix.sat.i15(i15 [[USA_TRUNC]], i15 [[USA_SAT_TRUNC]], i32 7)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
- // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %usa_sat, align 2
+// SIGNED-LABEL: @sat_usasusausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 8)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.umul.fix.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]], i32 7)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusausas() {
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.umul.fix.sat.i32(i32 [[UA]], i32 [[USA]], i32 16)
- // 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.umul.fix.sat.i31(i31 [[UA_TRUNC]], i31 [[USA]], i32 15)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i31 [[SUM]] to i32
- // UNSIGNED-NEXT: store i32 [[SUM_EXT]], i32* %ua_sat, align 4
+// SIGNED-LABEL: @sat_uasuausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.umul.fix.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]], i32 16)
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua_sat, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_uasuausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i31
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i31 [[RESIZE1]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i31 @llvm.umul.fix.sat.i31(i31 [[RESIZE]], i31 [[UPSCALE]], i32 15)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i31 [[TMP2]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE2]], i32* @ua_sat, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sat_uasuausas() {
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.smul.fix.sat.i39(i39 [[SA_SAT_EXT]], i39 [[I]], i32 7)
- // 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
+// CHECK-LABEL: @sat_sassasi(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.smul.fix.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 -32768, i39 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasi() {
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.smul.fix.sat.i40(i40 [[SA_SAT_EXT]], i40 [[I]], i32 7)
- // 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
+// CHECK-LABEL: @sat_sassasui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 7)
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 32767, i40 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 -32768, i40 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasui() {
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.umul.fix.sat.i16(i16 [[UF_SAT]], i16 [[UF_SAT2]], i32 16)
- // 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.umul.fix.sat.i15(i15 [[UF_SAT_TRUNC]], i15 [[UF_SAT_TRUNC2]], i32 15)
- // UNSIGNED-NEXT: [[SUM_EXT:%[a-z0-9]+]] = zext i15 [[SUM]] to i16
- // UNSIGNED-NEXT: store i16 [[SUM_EXT]], i16* %uf_sat, align 2
+// SIGNED-LABEL: @sat_ufsufsufs(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.umul.fix.sat.i16(i16 [[TMP0]], i16 [[TMP1]], i32 16)
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @uf_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_ufsufsufs(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.umul.fix.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]], i32 15)
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @uf_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_ufsufsufs() {
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.smul.fix.sat.i40(i40 [[USA_SAT_RESIZE]], i40 [[I_UPSCALE]], i32 8)
- // 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.smul.fix.sat.i39(i39 [[USA_SAT_RESIZE]], i39 [[I_UPSCALE]], i32 7)
- // 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
+// SIGNED-LABEL: @sat_usasusasi(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.smul.fix.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]], i32 8)
+// SIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 65535
+// SIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 65535, i40 [[TMP2]]
+// SIGNED-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], 0
+// SIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 0, i40 [[SATMAX]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusasi(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.smul.fix.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]], i32 7)
+// UNSIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// UNSIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// UNSIGNED-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 0, i39 [[SATMAX]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusasi() {
usa_sat = usa_sat * i;
}
--- /dev/null
+// 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
+
+// Multiplication between different fixed point types
+short _Accum sa_const = 2.0hk * 2.0hk;
+// CHECK-DAG: @sa_const = {{.*}}global i16 512, align 2
+_Accum a_const = 3.0hk * 2.0k;
+// CHECK-DAG: @a_const = {{.*}}global i32 196608, align 4
+long _Accum la_const = 4.0hk * 2.0lk;
+// CHECK-DAG: @la_const = {{.*}}global i64 17179869184, align 8
+short _Accum sa_const2 = 0.5hr * 2.0hk;
+// CHECK-DAG: @sa_const2 = {{.*}}global i16 128, align 2
+short _Accum sa_const3 = 0.5r * 3.0hk;
+// CHECK-DAG: @sa_const3 = {{.*}}global i16 192, align 2
+short _Accum sa_const4 = 0.5lr * 4.0hk;
+// CHECK-DAG: @sa_const4 = {{.*}}global i16 256, align 2
+
+// Unsigned multiplication
+unsigned short _Accum usa_const = 1.0uhk * 2.0uhk;
+// SIGNED-DAG: @usa_const = {{.*}}global i16 512, align 2
+// UNSIGNED-DAG: @usa_const = {{.*}}global i16 256, align 2
+
+// Unsigned * signed
+short _Accum sa_const5 = 20.0uhk * 3.0hk;
+// CHECK-DAG: @sa_const5 = {{.*}}global i16 7680, align 2
+
+// Multiplication with negative number
+short _Accum sa_const6 = 0.5hr * (-2.0hk);
+// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128, align 2
+
+// Int multiplication
+unsigned short _Accum usa_const2 = 5 * 10.5uhk;
+// SIGNED-DAG: @usa_const2 = {{.*}}global i16 13440, align 2
+// UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 6720, align 2
+short _Accum sa_const7 = 3 * (-0.5hk);
+// CHECK-DAG: @sa_const7 = {{.*}}global i16 -192, align 2
+short _Accum sa_const8 = 100 * (-2.0hk);
+// CHECK-DAG: @sa_const8 = {{.*}}global i16 -25600, align 2
+long _Fract lf_const = -0.25lr * 3;
+// CHECK-DAG: @lf_const = {{.*}}global i32 -1610612736, align 4
+
+// Saturated multiplication
+_Sat short _Accum sat_sa_const = (_Sat short _Accum)128.0hk * 3.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;
+// SIGNED-DAG: @sat_usa_const = {{.*}}global i16 -1, align 2
+// 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 -32768, align 2
+_Sat unsigned short _Accum sat_usa_const2 = (_Sat unsigned short _Accum)128.0uhk * 30;
+// SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 -1, align 2
+// 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
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// 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
-// Subtraction between different fixed point types
-short _Accum sa_const = 1.0hk - 2.0hk; // CHECK-DAG: @sa_const = {{.*}}global i16 -128, align 2
-_Accum a_const = 1.0hk - 2.0k; // CHECK-DAG: @a_const = {{.*}}global i32 -32768, align 4
-long _Accum la_const = 1.0hk - 2.0lk; // CHECK-DAG: @la_const = {{.*}}global i64 -2147483648, align 8
-short _Accum sa_const2 = 0.5hr - 2.0hk; // CHECK-DAG: @sa_const2 = {{.*}}global i16 -192, align 2
-short _Accum sa_const3 = 0.5r - 2.0hk; // CHECK-DAG: @sa_const3 = {{.*}}global i16 -192, align 2
-short _Accum sa_const4 = 0.5lr - 2.0hk; // CHECK-DAG: @sa_const4 = {{.*}}global i16 -192, align 2
-short _Accum sa_const5 = 2.0hk - 0.5lr; // CHECK-DAG: @sa_const5 = {{.*}}global i16 192, align 2
-
-// Unsigned subtraction
-unsigned short _Accum usa_const = 3.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_const6 = 1.0uhk - 2.0hk;
-// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128, align 2
-
-// Subtraction with negative number
-short _Accum sa_const7 = 0.5hr - (-2.0hk);
-// CHECK-DAG: @sa_const7 = {{.*}}global i16 320, align 2
-
-// Int subtraction
-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_const8 = 2 - (-0.5hk); // CHECK-DAG: @sa_const8 = {{.*}}global i16 320, align 2
-short _Accum sa_const9 = 257 - 2.0hk; // CHECK-DAG: @sa_const9 = {{.*}}global i16 32640, align 2
-long _Fract lf_const = 0.5lr - 1; // CHECK-DAG: @lf_const = {{.*}}global i32 -1073741824, align 4
-
-// Saturated subtraction
-_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
-_Sat short _Accum sat_sa_const3 = (_Sat short _Accum)-128.0hk - 128;
-// CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 -32768, align 2
-_Sat short _Accum sat_sa_const4 = (_Sat short _Accum)-150.0hk - 130.0lk;
-// CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
-
-
-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
+short _Accum sa;
+_Accum a, a2, a3, a4;
+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;
+
+_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;
+_Bool b;
+
+// CHECK-LABEL: @ssub_sasasa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void ssub_sasasa() {
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
+// CHECK-LABEL: @ssub_asaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void ssub_asaa() {
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
+// CHECK-LABEL: @ssub_sasasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void ssub_sasasf() {
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
+// CHECK-LABEL: @ssub_sasaf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = sub i24 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void ssub_sasaf() {
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
+// CHECK-LABEL: @ssub_aasf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @sf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i8 [[TMP1]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[UPSCALE]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void ssub_aasf() {
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
+// CHECK-LABEL: @ssub_aalf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i48
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i48 [[RESIZE]], 16
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i48
+// CHECK-NEXT: [[TMP2:%.*]] = sub i48 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = ashr i48 [[TMP2]], 16
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i48 [[DOWNSCALE]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void ssub_aalf() {
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
+// SIGNED-LABEL: @ssub_sasausa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i17 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @ssub_sasausa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void ssub_sasausa() {
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
+// SIGNED-LABEL: @ssub_asaua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i33
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i33 [[RESIZE]], 9
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i33
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i33 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i33 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i33 [[DOWNSCALE]] to i32
+// SIGNED-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @ssub_asaua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i32
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
+// UNSIGNED-NEXT: store i32 [[TMP2]], i32* @a, align 4
+// UNSIGNED-NEXT: ret void
+//
+void ssub_asaua() {
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
+// SIGNED-LABEL: @ssub_sasausf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i17
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i17 [[RESIZE]], 1
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i8 [[TMP1]] to i17
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i17 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i17 [[TMP2]], 1
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i17 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @ssub_sasausf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
+// UNSIGNED-NEXT: store i16 [[TMP2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void ssub_sasausf() {
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
+// SIGNED-LABEL: @ssub_sasaulf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i41
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i41 [[RESIZE]], 25
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i41
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i41 [[UPSCALE]], [[RESIZE1]]
+// SIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i41 [[TMP2]], 25
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i41 [[DOWNSCALE]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @ssub_sasaulf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ulf, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE]], 24
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i40 [[UPSCALE]], [[RESIZE1]]
+// UNSIGNED-NEXT: [[DOWNSCALE:%.*]] = ashr i40 [[TMP2]], 24
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[DOWNSCALE]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void ssub_sasaulf() {
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;
+// CHECK-LABEL: @ssub_aaaaa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @a2, align 4
+// CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, i32* @a3, align 4
+// CHECK-NEXT: [[TMP4:%.*]] = sub i32 [[TMP2]], [[TMP3]]
+// CHECK-NEXT: [[TMP5:%.*]] = load i32, i32* @a4, align 4
+// CHECK-NEXT: [[TMP6:%.*]] = sub i32 [[TMP4]], [[TMP5]]
+// CHECK-NEXT: store i32 [[TMP6]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void ssub_aaaaa() {
+ a = a - a2 - a3 - a4;
+}
- 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
+// CHECK-LABEL: @usub_usausausa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[TMP1]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void usub_usausausa() {
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
+// CHECK-LABEL: @usub_uausaua(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ua, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i32
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[UPSCALE]], [[TMP1]]
+// CHECK-NEXT: store i32 [[TMP2]], i32* @ua, align 4
+// CHECK-NEXT: ret void
+//
+void usub_uausaua() {
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
+// CHECK-LABEL: @usub_usausausf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @usf, align 1
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i8 [[TMP1]] to i16
+// CHECK-NEXT: [[TMP2:%.*]] = sub i16 [[TMP0]], [[RESIZE]]
+// CHECK-NEXT: store i16 [[TMP2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void usub_usausausf() {
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
+// CHECK-LABEL: @usub_usausauf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i24
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i24 [[RESIZE]], 8
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i24
+// CHECK-NEXT: [[TMP2:%.*]] = sub i24 [[UPSCALE]], [[RESIZE1]]
+// CHECK-NEXT: [[DOWNSCALE:%.*]] = lshr i24 [[TMP2]], 8
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i24 [[DOWNSCALE]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void usub_usausauf() {
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
+
+// CHECK-LABEL: @int_sasai(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasai() {
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
+// CHECK-LABEL: @int_sasaui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa, align 2
+// CHECK-NEXT: ret void
+//
+void int_sasaui() {
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
+// SIGNED-LABEL: @int_usausai(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausai(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausai() {
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
+// SIGNED-LABEL: @int_usausaui(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = sub i40 [[RESIZE]], [[UPSCALE]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[TMP2]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @int_usausaui(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = sub i39 [[RESIZE]], [[UPSCALE]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void int_usausaui() {
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
+// CHECK-LABEL: @int_lflfui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i64
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i64
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i64 [[RESIZE1]], 31
+// CHECK-NEXT: [[TMP2:%.*]] = sub i64 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i64 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void int_lflfui() {
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
+// CHECK-LABEL: @int_aab(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* @b, align 1
+// CHECK-NEXT: [[TOBOOL:%.*]] = trunc i8 [[TMP1]] to i1
+// CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TOBOOL]] to i32
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i32 [[TMP0]] to i47
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[CONV]] to i47
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i47 [[RESIZE1]], 15
+// CHECK-NEXT: [[TMP2:%.*]] = sub i47 [[RESIZE]], [[UPSCALE]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i47 [[TMP2]] to i32
+// CHECK-NEXT: store i32 [[RESIZE2]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void int_aab() {
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
+
+// CHECK-LABEL: @sat_sassasas(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// CHECK-NEXT: store i16 [[TMP2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasas() {
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
+// SIGNED-LABEL: @sat_usasusausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusausas() {
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
+// SIGNED-LABEL: @sat_uasuausas(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP1]] to i32
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]])
+// SIGNED-NEXT: store i32 [[TMP2]], i32* @ua_sat, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_uasuausas(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i16 [[TMP1]] to i31
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i31 [[RESIZE1]], 8
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i31 @llvm.usub.sat.i31(i31 [[RESIZE]], i31 [[UPSCALE]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i31 [[TMP2]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE2]], i32* @ua_sat, align 4
+// UNSIGNED-NEXT: ret void
+//
+void sat_uasuausas() {
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
+// CHECK-LABEL: @sat_sassasi(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i39
+// CHECK-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i39 @llvm.ssub.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 -32768, i39 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasi() {
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
+// CHECK-LABEL: @sat_sassasui(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sa_sat, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @ui, align 4
+// CHECK-NEXT: [[RESIZE:%.*]] = sext i16 [[TMP0]] to i40
+// CHECK-NEXT: [[RESIZE1:%.*]] = zext i32 [[TMP1]] to i40
+// CHECK-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 7
+// CHECK-NEXT: [[TMP2:%.*]] = call i40 @llvm.ssub.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
+// CHECK-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 32767
+// CHECK-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 32767, i40 [[TMP2]]
+// CHECK-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], -32768
+// CHECK-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 -32768, i40 [[SATMAX]]
+// CHECK-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// CHECK-NEXT: store i16 [[RESIZE2]], i16* @sa_sat, align 2
+// CHECK-NEXT: ret void
+//
+void sat_sassasui() {
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
+// SIGNED-LABEL: @sat_ufsufsufs(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// SIGNED-NEXT: [[TMP2:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
+// SIGNED-NEXT: store i16 [[TMP2]], i16* @uf_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_ufsufsufs(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i16, i16* @uf_sat, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = trunc i16 [[TMP1]] to i15
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE]], i15 [[RESIZE1]])
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = zext i15 [[TMP2]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @uf_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_ufsufsufs() {
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.ssub.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.ssub.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
+// SIGNED-LABEL: @sat_usasusasi(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// SIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i40
+// SIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i40
+// SIGNED-NEXT: [[UPSCALE:%.*]] = shl i40 [[RESIZE1]], 8
+// SIGNED-NEXT: [[TMP2:%.*]] = call i40 @llvm.ssub.sat.i40(i40 [[RESIZE]], i40 [[UPSCALE]])
+// SIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i40 [[TMP2]], 65535
+// SIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i40 65535, i40 [[TMP2]]
+// SIGNED-NEXT: [[TMP4:%.*]] = icmp slt i40 [[SATMAX]], 0
+// SIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i40 0, i40 [[SATMAX]]
+// SIGNED-NEXT: [[RESIZE2:%.*]] = trunc i40 [[SATMIN]] to i16
+// SIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @sat_usasusasi(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa_sat, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = load i32, i32* @i, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = zext i16 [[TMP0]] to i39
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = sext i32 [[TMP1]] to i39
+// UNSIGNED-NEXT: [[UPSCALE:%.*]] = shl i39 [[RESIZE1]], 7
+// UNSIGNED-NEXT: [[TMP2:%.*]] = call i39 @llvm.ssub.sat.i39(i39 [[RESIZE]], i39 [[UPSCALE]])
+// UNSIGNED-NEXT: [[TMP3:%.*]] = icmp sgt i39 [[TMP2]], 32767
+// UNSIGNED-NEXT: [[SATMAX:%.*]] = select i1 [[TMP3]], i39 32767, i39 [[TMP2]]
+// UNSIGNED-NEXT: [[TMP4:%.*]] = icmp slt i39 [[SATMAX]], 0
+// UNSIGNED-NEXT: [[SATMIN:%.*]] = select i1 [[TMP4]], i39 0, i39 [[SATMAX]]
+// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i39 [[SATMIN]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE2]], i16* @usa_sat, align 2
+// UNSIGNED-NEXT: ret void
+//
+void sat_usasusasi() {
usa_sat = usa_sat - i;
}
--- /dev/null
+// 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
+
+// Subtraction between different fixed point types
+short _Accum sa_const = 1.0hk - 2.0hk;
+// CHECK-DAG: @sa_const = {{.*}}global i16 -128, align 2
+_Accum a_const = 1.0hk - 2.0k;
+// CHECK-DAG: @a_const = {{.*}}global i32 -32768, align 4
+long _Accum la_const = 1.0hk - 2.0lk;
+// CHECK-DAG: @la_const = {{.*}}global i64 -2147483648, align 8
+short _Accum sa_const2 = 0.5hr - 2.0hk;
+// CHECK-DAG: @sa_const2 = {{.*}}global i16 -192, align 2
+short _Accum sa_const3 = 0.5r - 2.0hk;
+// CHECK-DAG: @sa_const3 = {{.*}}global i16 -192, align 2
+short _Accum sa_const4 = 0.5lr - 2.0hk;
+// CHECK-DAG: @sa_const4 = {{.*}}global i16 -192, align 2
+short _Accum sa_const5 = 2.0hk - 0.5lr;
+// CHECK-DAG: @sa_const5 = {{.*}}global i16 192, align 2
+
+// Unsigned subtraction
+unsigned short _Accum usa_const = 3.0uhk - 2.0uhk;
+// SIGNED-DAG: @usa_const = {{.*}}global i16 256, align 2
+// UNSIGNED-DAG: @usa_const = {{.*}}global i16 128, align 2
+
+// Unsigned - signed
+short _Accum sa_const6 = 1.0uhk - 2.0hk;
+// CHECK-DAG: @sa_const6 = {{.*}}global i16 -128, align 2
+
+// Subtraction with negative number
+short _Accum sa_const7 = 0.5hr - (-2.0hk);
+// CHECK-DAG: @sa_const7 = {{.*}}global i16 320, align 2
+
+// Int subtraction
+unsigned short _Accum usa_const2 = 2 - 0.5uhk;
+// SIGNED-DAG: @usa_const2 = {{.*}}global i16 384, align 2
+// UNSIGNED-DAG: @usa_const2 = {{.*}}global i16 192, align 2
+short _Accum sa_const8 = 2 - (-0.5hk);
+// CHECK-DAG: @sa_const8 = {{.*}}global i16 320, align 2
+short _Accum sa_const9 = 257 - 2.0hk;
+// CHECK-DAG: @sa_const9 = {{.*}}global i16 32640, align 2
+long _Fract lf_const = 0.5lr - 1;
+// CHECK-DAG: @lf_const = {{.*}}global i32 -1073741824, align 4
+
+// Saturated subtraction
+_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-DAG: @sat_usa_const = {{.*}}global i16 0, 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);
+// SIGNED-DAG: @sat_usa_const2 = {{.*}}global i16 -1, align 2
+// 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
+_Sat short _Accum sat_sa_const3 = (_Sat short _Accum)-128.0hk - 128;
+// CHECK-DAG: @sat_sa_const3 = {{.*}}global i16 -32768, align 2
+_Sat short _Accum sat_sa_const4 = (_Sat short _Accum)-150.0hk - 130.0lk;
+// CHECK-DAG: @sat_sa_const4 = {{.*}}global i16 -32768, align 2
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ffixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -ffixed-point -fpadding-on-unsigned-fixed-point -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,UNSIGNED
_Sat short unsigned _Accum susa;
_Sat unsigned _Fract suf;
-// CHECK-LABEL: @Increment(
-void Increment() {
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+int i;
+
+// CHECK-LABEL: @inc_a(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], -32768
// CHECK-NEXT: store i32 [[TMP1]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void inc_a() {
a++;
+}
-// CHECK: [[TMP2:%.*]] = load i16, i16* @f, align 2
-// CHECK-NEXT: [[TMP3:%.*]] = sub i16 [[TMP2]], -32768
-// CHECK-NEXT: store i16 [[TMP3]], i16* @f, align 2
+// CHECK-LABEL: @inc_f(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], -32768
+// CHECK-NEXT: store i16 [[TMP1]], i16* @f, align 2
+// CHECK-NEXT: ret void
+//
+void inc_f() {
f++;
+}
-// CHECK: [[TMP4:%.*]] = load i32, i32* @lf, align 4
-// CHECK-NEXT: [[TMP5:%.*]] = sub i32 [[TMP4]], -2147483648
-// CHECK-NEXT: store i32 [[TMP5]], i32* @lf, align 4
+// CHECK-LABEL: @inc_lf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], -2147483648
+// CHECK-NEXT: store i32 [[TMP1]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void inc_lf() {
lf++;
+}
-// CHECK: [[TMP6:%.*]] = load i32, i32* @ua, align 4
-// SIGNED-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], 65536
-// UNSIGNED-NEXT: [[TMP7:%.*]] = add i32 [[TMP6]], 32768
-// CHECK-NEXT: store i32 [[TMP7]], i32* @ua, align 4
+// SIGNED-LABEL: @inc_ua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 65536
+// SIGNED-NEXT: store i32 [[TMP1]], i32* @ua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_ua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], 32768
+// UNSIGNED-NEXT: store i32 [[TMP1]], i32* @ua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void inc_ua() {
ua++;
+}
-// CHECK: [[TMP8:%.*]] = load i16, i16* @usa, align 2
-// SIGNED-NEXT: [[TMP9:%.*]] = add i16 [[TMP8]], 256
-// UNSIGNED-NEXT: [[TMP9:%.*]] = add i16 [[TMP8]], 128
-// CHECK-NEXT: store i16 [[TMP9]], i16* @usa, align 2
+// SIGNED-LABEL: @inc_usa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], 256
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_usa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], 128
+// UNSIGNED-NEXT: store i16 [[TMP1]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void inc_usa() {
usa++;
+}
-// CHECK: [[TMP10:%.*]] = load i16, i16* @uf, align 2
-// SIGNED-NEXT: [[TMP11:%.*]] = add i16 [[TMP10]], undef
-// UNSIGNED-NEXT: [[TMP11:%.*]] = add i16 [[TMP10]], -32768
-// CHECK-NEXT: store i16 [[TMP11]], i16* @uf, align 2
+// SIGNED-LABEL: @inc_uf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], undef
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_uf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], -32768
+// UNSIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void inc_uf() {
uf++;
+}
-// CHECK: [[TMP12:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP12]], i32 -32768)
-// CHECK-NEXT: store i32 [[TMP13]], i32* @sa, align 4
+// CHECK-LABEL: @inc_sa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP0]], i32 -32768)
+// CHECK-NEXT: store i32 [[TMP1]], i32* @sa, align 4
+// CHECK-NEXT: ret void
+//
+void inc_sa() {
sa++;
+}
-// CHECK: [[TMP14:%.*]] = load i16, i16* @sf, align 2
-// CHECK-NEXT: [[TMP15:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP14]], i16 -32768)
-// CHECK-NEXT: store i16 [[TMP15]], i16* @sf, align 2
+// CHECK-LABEL: @inc_sf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sf, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 -32768)
+// CHECK-NEXT: store i16 [[TMP1]], i16* @sf, align 2
+// CHECK-NEXT: ret void
+//
+void inc_sf() {
sf++;
+}
-// CHECK: [[TMP16:%.*]] = load i32, i32* @slf, align 4
-// CHECK-NEXT: [[TMP17:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP16]], i32 -2147483648)
-// CHECK-NEXT: store i32 [[TMP17]], i32* @slf, align 4
+// CHECK-LABEL: @inc_slf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @slf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP0]], i32 -2147483648)
+// CHECK-NEXT: store i32 [[TMP1]], i32* @slf, align 4
+// CHECK-NEXT: ret void
+//
+void inc_slf() {
slf++;
+}
-// CHECK: [[TMP18:%.*]] = load i32, i32* @sua, align 4
-// SIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[TMP18]], i32 65536)
-// SIGNED-NEXT: store i32 [[TMP19]], i32* @sua, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31
-// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.uadd.sat.i31(i31 [[RESIZE]], i31 32768)
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32
-// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// SIGNED-LABEL: @inc_sua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @sua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[TMP0]], i32 65536)
+// SIGNED-NEXT: store i32 [[TMP1]], i32* @sua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_sua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @sua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i31 @llvm.uadd.sat.i31(i31 [[RESIZE]], i31 32768)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP1]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void inc_sua() {
sua++;
+}
-// CHECK: [[TMP20:%.*]] = load i16, i16* @susa, align 2
-// SIGNED-NEXT: [[TMP21:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP20]], i16 256)
-// SIGNED-NEXT: store i16 [[TMP21]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15
-// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE2]], i15 128)
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2
+// SIGNED-LABEL: @inc_susa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP0]], i16 256)
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @susa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_susa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE]], i15 128)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void inc_susa() {
susa++;
+}
-// CHECK: [[TMP22:%.*]] = load i16, i16* @suf, align 2
-// SIGNED-NEXT: [[TMP23:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP22]], i16 -1)
-// SIGNED-NEXT: store i16 [[TMP23]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15
-// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE4]], i15 -1)
-// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2
+// SIGNED-LABEL: @inc_suf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.uadd.sat.i16(i16 [[TMP0]], i16 -1)
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @suf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @inc_suf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.uadd.sat.i15(i15 [[RESIZE]], i15 -1)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @suf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void inc_suf() {
suf++;
}
-// CHECK-LABEL: @Decrement(
-void Decrement() {
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+
+// CHECK-LABEL: @dec_a(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -32768
// CHECK-NEXT: store i32 [[TMP1]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void dec_a() {
a--;
+}
-// CHECK: [[TMP2:%.*]] = load i16, i16* @f, align 2
-// CHECK-NEXT: [[TMP3:%.*]] = add i16 [[TMP2]], -32768
-// CHECK-NEXT: store i16 [[TMP3]], i16* @f, align 2
+// CHECK-LABEL: @dec_f(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = add i16 [[TMP0]], -32768
+// CHECK-NEXT: store i16 [[TMP1]], i16* @f, align 2
+// CHECK-NEXT: ret void
+//
+void dec_f() {
f--;
+}
-// CHECK: [[TMP4:%.*]] = load i32, i32* @lf, align 4
-// CHECK-NEXT: [[TMP5:%.*]] = add i32 [[TMP4]], -2147483648
-// CHECK-NEXT: store i32 [[TMP5]], i32* @lf, align 4
+// CHECK-LABEL: @dec_lf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @lf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = add i32 [[TMP0]], -2147483648
+// CHECK-NEXT: store i32 [[TMP1]], i32* @lf, align 4
+// CHECK-NEXT: ret void
+//
+void dec_lf() {
lf--;
+}
-// CHECK: [[TMP6:%.*]] = load i32, i32* @ua, align 4
-// SIGNED-NEXT: [[TMP7:%.*]] = sub i32 [[TMP6]], 65536
-// UNSIGNED-NEXT: [[TMP7:%.*]] = sub i32 [[TMP6]], 32768
-// CHECK-NEXT: store i32 [[TMP7]], i32* @ua, align 4
+// SIGNED-LABEL: @dec_ua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], 65536
+// SIGNED-NEXT: store i32 [[TMP1]], i32* @ua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_ua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @ua, align 4
+// UNSIGNED-NEXT: [[TMP1:%.*]] = sub i32 [[TMP0]], 32768
+// UNSIGNED-NEXT: store i32 [[TMP1]], i32* @ua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void dec_ua() {
ua--;
+}
-// CHECK: [[TMP8:%.*]] = load i16, i16* @usa, align 2
-// SIGNED-NEXT: [[TMP9:%.*]] = sub i16 [[TMP8]], 256
-// UNSIGNED-NEXT: [[TMP9:%.*]] = sub i16 [[TMP8]], 128
-// CHECK-NEXT: store i16 [[TMP9]], i16* @usa, align 2
+// SIGNED-LABEL: @dec_usa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], 256
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @usa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_usa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], 128
+// UNSIGNED-NEXT: store i16 [[TMP1]], i16* @usa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void dec_usa() {
usa--;
+}
-// CHECK: [[TMP10:%.*]] = load i16, i16* @uf, align 2
-// SIGNED-NEXT: [[TMP11:%.*]] = sub i16 [[TMP10]], undef
-// UNSIGNED-NEXT: [[TMP11:%.*]] = sub i16 [[TMP10]], -32768
-// CHECK-NEXT: store i16 [[TMP11]], i16* @uf, align 2
+// SIGNED-LABEL: @dec_uf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], undef
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_uf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// UNSIGNED-NEXT: [[TMP1:%.*]] = sub i16 [[TMP0]], -32768
+// UNSIGNED-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void dec_uf() {
uf--;
+}
-// CHECK: [[TMP12:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP13:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP12]], i32 -32768)
-// CHECK-NEXT: store i32 [[TMP13]], i32* @sa, align 4
+// CHECK-LABEL: @dec_sa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 -32768)
+// CHECK-NEXT: store i32 [[TMP1]], i32* @sa, align 4
+// CHECK-NEXT: ret void
+//
+void dec_sa() {
sa--;
+}
-// CHECK: [[TMP14:%.*]] = load i16, i16* @sf, align 2
-// CHECK-NEXT: [[TMP15:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP14]], i16 -32768)
-// CHECK-NEXT: store i16 [[TMP15]], i16* @sf, align 2
+// CHECK-LABEL: @dec_sf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sf, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[TMP0]], i16 -32768)
+// CHECK-NEXT: store i16 [[TMP1]], i16* @sf, align 2
+// CHECK-NEXT: ret void
+//
+void dec_sf() {
sf--;
+}
-// CHECK: [[TMP16:%.*]] = load i32, i32* @slf, align 4
-// CHECK-NEXT: [[TMP17:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP16]], i32 -2147483648)
-// CHECK-NEXT: store i32 [[TMP17]], i32* @slf, align 4
+// CHECK-LABEL: @dec_slf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @slf, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 -2147483648)
+// CHECK-NEXT: store i32 [[TMP1]], i32* @slf, align 4
+// CHECK-NEXT: ret void
+//
+void dec_slf() {
slf--;
+}
-// CHECK: [[TMP18:%.*]] = load i32, i32* @sua, align 4
-// SIGNED-NEXT: [[TMP19:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP18]], i32 65536)
-// SIGNED-NEXT: store i32 [[TMP19]], i32* @sua, align 4
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP18]] to i31
-// UNSIGNED-NEXT: [[TMP19:%.*]] = call i31 @llvm.usub.sat.i31(i31 [[RESIZE]], i31 32768)
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP19]] to i32
-// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// SIGNED-LABEL: @dec_sua(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @sua, align 4
+// SIGNED-NEXT: [[TMP1:%.*]] = call i32 @llvm.usub.sat.i32(i32 [[TMP0]], i32 65536)
+// SIGNED-NEXT: store i32 [[TMP1]], i32* @sua, align 4
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_sua(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i32, i32* @sua, align 4
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i32 [[TMP0]] to i31
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i31 @llvm.usub.sat.i31(i31 [[RESIZE]], i31 32768)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i31 [[TMP1]] to i32
+// UNSIGNED-NEXT: store i32 [[RESIZE1]], i32* @sua, align 4
+// UNSIGNED-NEXT: ret void
+//
+void dec_sua() {
sua--;
+}
-// CHECK: [[TMP20:%.*]] = load i16, i16* @susa, align 2
-// SIGNED-NEXT: [[TMP21:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP20]], i16 256)
-// SIGNED-NEXT: store i16 [[TMP21]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP20]] to i15
-// UNSIGNED-NEXT: [[TMP21:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE2]], i15 128)
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP21]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @susa, align 2
+// SIGNED-LABEL: @dec_susa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 256)
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @susa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_susa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE]], i15 128)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void dec_susa() {
susa--;
+}
-// CHECK: [[TMP22:%.*]] = load i16, i16* @suf, align 2
-// SIGNED-NEXT: [[TMP23:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP22]], i16 -1)
-// SIGNED-NEXT: store i16 [[TMP23]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE4:%.*]] = trunc i16 [[TMP22]] to i15
-// UNSIGNED-NEXT: [[TMP23:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE4]], i15 -1)
-// UNSIGNED-NEXT: [[RESIZE5:%.*]] = zext i15 [[TMP23]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE5]], i16* @suf, align 2
+// SIGNED-LABEL: @dec_suf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.usub.sat.i16(i16 [[TMP0]], i16 -1)
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @suf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @dec_suf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.usub.sat.i15(i15 [[RESIZE]], i15 -1)
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @suf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void dec_suf() {
suf--;
}
-// CHECK-LABEL: @Minus(
-void Minus() {
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+
+// CHECK-LABEL: @neg_a(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: [[TMP1:%.*]] = sub i32 0, [[TMP0]]
// CHECK-NEXT: store i32 [[TMP1]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void neg_a() {
a = -a;
+}
-// CHECK: [[TMP2:%.*]] = load i16, i16* @f, align 2
-// CHECK-NEXT: [[TMP3:%.*]] = sub i16 0, [[TMP2]]
-// CHECK-NEXT: store i16 [[TMP3]], i16* @f, align 2
+// CHECK-LABEL: @neg_f(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @f, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = sub i16 0, [[TMP0]]
+// CHECK-NEXT: store i16 [[TMP1]], i16* @f, align 2
+// CHECK-NEXT: ret void
+//
+void neg_f() {
f = -f;
+}
-// CHECK: [[TMP4:%.*]] = load i16, i16* @usa, align 2
-// CHECK-NEXT: [[TMP5:%.*]] = sub i16 0, [[TMP4]]
-// CHECK-NEXT: store i16 [[TMP5]], i16* @usa, align 2
+// CHECK-LABEL: @neg_usa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @usa, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = sub i16 0, [[TMP0]]
+// CHECK-NEXT: store i16 [[TMP1]], i16* @usa, align 2
+// CHECK-NEXT: ret void
+//
+void neg_usa() {
usa = -usa;
+}
-// CHECK: [[TMP6:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TMP7:%.*]] = sub i16 0, [[TMP6]]
-// CHECK-NEXT: store i16 [[TMP7]], i16* @uf, align 2
+// CHECK-LABEL: @neg_uf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = sub i16 0, [[TMP0]]
+// CHECK-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// CHECK-NEXT: ret void
+//
+void neg_uf() {
uf = -uf;
+}
-// CHECK: [[TMP8:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: [[TMP9:%.*]] = call i32 @llvm.ssub.sat.i32(i32 0, i32 [[TMP8]])
-// CHECK-NEXT: store i32 [[TMP9]], i32* @sa, align 4
+// CHECK-LABEL: @neg_sa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ssub.sat.i32(i32 0, i32 [[TMP0]])
+// CHECK-NEXT: store i32 [[TMP1]], i32* @sa, align 4
+// CHECK-NEXT: ret void
+//
+void neg_sa() {
sa = -sa;
+}
-// CHECK: [[TMP10:%.*]] = load i16, i16* @sf, align 2
-// CHECK-NEXT: [[TMP11:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP10]])
-// CHECK-NEXT: store i16 [[TMP11]], i16* @sf, align 2
+// CHECK-LABEL: @neg_sf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @sf, align 2
+// CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ssub.sat.i16(i16 0, i16 [[TMP0]])
+// CHECK-NEXT: store i16 [[TMP1]], i16* @sf, align 2
+// CHECK-NEXT: ret void
+//
+void neg_sf() {
sf = -sf;
+}
-// CHECK: [[TMP12:%.*]] = load i16, i16* @susa, align 2
-// SIGNED-NEXT: [[TMP13:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP12]])
-// SIGNED-NEXT: store i16 [[TMP13]], i16* @susa, align 2
-// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP12]] to i15
-// UNSIGNED-NEXT: [[TMP13:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE]])
-// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP13]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2
+// SIGNED-LABEL: @neg_susa(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP0]])
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @susa, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @neg_susa(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE]])
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @susa, align 2
+// UNSIGNED-NEXT: ret void
+//
+void neg_susa() {
susa = -susa;
+}
-// CHECK: [[TMP14:%.*]] = load i16, i16* @suf, align 2
-// SIGNED-NEXT: [[TMP15:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP14]])
-// SIGNED-NEXT: store i16 [[TMP15]], i16* @suf, align 2
-// UNSIGNED-NEXT: [[RESIZE2:%.*]] = trunc i16 [[TMP14]] to i15
-// UNSIGNED-NEXT: [[TMP15:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE2]])
-// UNSIGNED-NEXT: [[RESIZE3:%.*]] = zext i15 [[TMP15]] to i16
-// UNSIGNED-NEXT: store i16 [[RESIZE3]], i16* @suf, align 2
+// SIGNED-LABEL: @neg_suf(
+// SIGNED-NEXT: entry:
+// SIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// SIGNED-NEXT: [[TMP1:%.*]] = call i16 @llvm.usub.sat.i16(i16 0, i16 [[TMP0]])
+// SIGNED-NEXT: store i16 [[TMP1]], i16* @suf, align 2
+// SIGNED-NEXT: ret void
+//
+// UNSIGNED-LABEL: @neg_suf(
+// UNSIGNED-NEXT: entry:
+// UNSIGNED-NEXT: [[TMP0:%.*]] = load i16, i16* @suf, align 2
+// UNSIGNED-NEXT: [[RESIZE:%.*]] = trunc i16 [[TMP0]] to i15
+// UNSIGNED-NEXT: [[TMP1:%.*]] = call i15 @llvm.usub.sat.i15(i15 0, i15 [[RESIZE]])
+// UNSIGNED-NEXT: [[RESIZE1:%.*]] = zext i15 [[TMP1]] to i16
+// UNSIGNED-NEXT: store i16 [[RESIZE1]], i16* @suf, align 2
+// UNSIGNED-NEXT: ret void
+//
+void neg_suf() {
suf = -suf;
}
-// CHECK-LABEL: @Plus(
-void Plus() {
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+
+// CHECK-LABEL: @plus_a(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: store i32 [[TMP0]], i32* @a, align 4
+// CHECK-NEXT: ret void
+//
+void plus_a() {
a = +a;
+}
-// CHECK: [[TMP1:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: store i16 [[TMP1]], i16* @uf, align 2
+// CHECK-LABEL: @plus_uf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: store i16 [[TMP0]], i16* @uf, align 2
+// CHECK-NEXT: ret void
+//
+void plus_uf() {
uf = +uf;
+}
-// CHECK: [[TMP2:%.*]] = load i32, i32* @sa, align 4
-// CHECK-NEXT: store i32 [[TMP2]], i32* @sa, align 4
+// CHECK-LABEL: @plus_sa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @sa, align 4
+// CHECK-NEXT: store i32 [[TMP0]], i32* @sa, align 4
+// CHECK-NEXT: ret void
+//
+void plus_sa() {
sa = +sa;
}
-// CHECK-LABEL: @Not(
-void Not() {
- int i;
-// CHECK: [[TMP0:%.*]] = load i32, i32* @a, align 4
+// CHECK-LABEL: @not_a(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @a, align 4
// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[TMP0]], 0
// CHECK-NEXT: [[LNOT:%.*]] = xor i1 [[TOBOOL]], true
// CHECK-NEXT: [[LNOT_EXT:%.*]] = zext i1 [[LNOT]] to i32
-// CHECK-NEXT: store i32 [[LNOT_EXT]], i32* %i, align 4
+// CHECK-NEXT: store i32 [[LNOT_EXT]], i32* @i, align 4
+// CHECK-NEXT: ret void
+//
+void not_a() {
i = !a;
+}
-// CHECK: [[TMP1:%.*]] = load i16, i16* @uf, align 2
-// CHECK-NEXT: [[TOBOOL1:%.*]] = icmp ne i16 [[TMP1]], 0
-// CHECK-NEXT: [[LNOT2:%.*]] = xor i1 [[TOBOOL1]], true
-// CHECK-NEXT: [[LNOT_EXT3:%.*]] = zext i1 [[LNOT2]] to i32
-// CHECK-NEXT: store i32 [[LNOT_EXT3]], i32* %i, align 4
+// CHECK-LABEL: @not_uf(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @uf, align 2
+// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP0]], 0
+// CHECK-NEXT: [[LNOT:%.*]] = xor i1 [[TOBOOL]], true
+// CHECK-NEXT: [[LNOT_EXT:%.*]] = zext i1 [[LNOT]] to i32
+// CHECK-NEXT: store i32 [[LNOT_EXT]], i32* @i, align 4
+// CHECK-NEXT: ret void
+//
+void not_uf() {
i = !uf;
+}
-// CHECK: [[TMP2:%.*]] = load i16, i16* @susa, align 2
-// CHECK-NEXT: [[TOBOOL4:%.*]] = icmp ne i16 [[TMP2]], 0
-// CHECK-NEXT: [[LNOT5:%.*]] = xor i1 [[TOBOOL4]], true
-// CHECK-NEXT: [[LNOT_EXT6:%.*]] = zext i1 [[LNOT5]] to i32
-// CHECK-NEXT: store i32 [[LNOT_EXT6]], i32* %i, align 4
+// CHECK-LABEL: @not_susa(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[TMP0:%.*]] = load i16, i16* @susa, align 2
+// CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP0]], 0
+// CHECK-NEXT: [[LNOT:%.*]] = xor i1 [[TOBOOL]], true
+// CHECK-NEXT: [[LNOT_EXT:%.*]] = zext i1 [[LNOT]] to i32
+// CHECK-NEXT: store i32 [[LNOT_EXT]], i32* @i, align 4
+// CHECK-NEXT: ret void
+//
+void not_susa() {
i = !susa;
}