// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
// RUN: %clang_cc1 -no-opaque-pointers -ffixed-point -triple x86_64-unknown-linux-gnu -S -emit-llvm %s -o - | FileCheck %s --check-prefixes=CHECK,SIGNED
// RUN: %clang_cc1 -no-opaque-pointers -ffixed-point -triple x86_64-unknown-linux-gnu -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: @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(void) {
  sa = sa - sa;
}

// 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(void) {
  a = sa - a;
}

// 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(void) {
  sa = sa - sf;
}

// 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(void) {
  sa = sa - f;
}

// 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(void) {
  a = a - sf;
}

// 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(void) {
  a = a - lf;
}

// 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(void) {
  sa = sa - usa;
}

// 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(void) {
  a = sa - ua;
}

// 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(void) {
  sa = sa - usf;
}

// 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(void) {
  sa = sa - ulf;
}

// 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(void) {
  a = a - a2 - a3 - a4;
}


// 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(void) {
  usa = usa - usa;
}

// 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(void) {
  ua = usa - ua;
}

// 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(void) {
  usa = usa - usf;
}

// 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(void) {
  usa = usa - uf;
}


// 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(void) {
  sa = sa - i;
}

// 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(void) {
  sa = sa - ui;
}

// 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(void) {
  usa = usa - i;
}

// 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(void) {
  usa = usa - ui;
}

// 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(void) {
  lf = lf - ui;
}

// 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(void) {
  a = a - b;
}


// 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(void) {
  sa_sat = sa - sa_sat;
}

// 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:    [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
// UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[TMP2]], 0
// UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i16 0, i16 [[TMP2]]
// UNSIGNED-NEXT:    [[RESIZE:%.*]] = trunc i16 [[SATMIN]] to i15
// UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i15 [[RESIZE]] to i16
// UNSIGNED-NEXT:    store i16 [[RESIZE1]], i16* @usa_sat, align 2
// UNSIGNED-NEXT:    ret void
//
void sat_usasusausas(void) {
  usa_sat = usa - usa_sat;
}

// 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:%.*]] = zext i16 [[TMP1]] to i32
// UNSIGNED-NEXT:    [[UPSCALE:%.*]] = shl i32 [[RESIZE]], 8
// UNSIGNED-NEXT:    [[TMP2:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[TMP0]], i32 [[UPSCALE]])
// UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i32 [[TMP2]], 0
// UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i32 0, i32 [[TMP2]]
// UNSIGNED-NEXT:    [[RESIZE1:%.*]] = trunc i32 [[SATMIN]] to i31
// UNSIGNED-NEXT:    [[RESIZE2:%.*]] = zext i31 [[RESIZE1]] to i32
// UNSIGNED-NEXT:    store i32 [[RESIZE2]], i32* @ua_sat, align 4
// UNSIGNED-NEXT:    ret void
//
void sat_uasuausas(void) {
  ua_sat = ua - usa_sat;
}

// 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(void) {
  sa_sat = sa_sat - i;
}

// 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(void) {
  sa_sat = sa_sat - ui;
}

// 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:    [[TMP2:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[TMP0]], i16 [[TMP1]])
// UNSIGNED-NEXT:    [[TMP3:%.*]] = icmp slt i16 [[TMP2]], 0
// UNSIGNED-NEXT:    [[SATMIN:%.*]] = select i1 [[TMP3]], i16 0, i16 [[TMP2]]
// UNSIGNED-NEXT:    [[RESIZE:%.*]] = trunc i16 [[SATMIN]] to i15
// UNSIGNED-NEXT:    [[RESIZE1:%.*]] = zext i15 [[RESIZE]] to i16
// UNSIGNED-NEXT:    store i16 [[RESIZE1]], i16* @uf_sat, align 2
// UNSIGNED-NEXT:    ret void
//
void sat_ufsufsufs(void) {
  uf_sat = uf_sat - uf_sat;
}

// 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(void) {
  usa_sat = usa_sat - i;
}
