unstick r375505

Revision 375505

Date:
2019/10/22 15:39:47
Author:
dmgreen
Revision Log:
[InstCombine] Signed saturation patterns

This adds an instcombine matcher for code that attempts to perform signed
saturating arithmetic by casting to a higher type. Unsigned cases are already
matched, this adds extra matches for the more complex signed cases, which
involves matching the min(max(add a b)) nodes with proper extends to ensure
legality.

Differential Revision: https://reviews.llvm.org/D68651
Files:

Legend:

 
Added
 
Removed
 
Modified
  • llvm/trunk/lib/Transforms/InstCombine/InstCombineInternal.h

     
    601 601 Instruction *narrowMathIfNoOverflow(BinaryOperator &I);
    602 602 Instruction *narrowRotate(TruncInst &Trunc);
    603 603 Instruction *optimizeBitCastFromPhi(CastInst &CI, PHINode *PN);
    604 Instruction *matchSAddSubSat(SelectInst &MinMax1);
    604 605
    605 606 /// Determine if a pair of casts can be replaced by a single cast.
    606 607 ///
  • llvm/trunk/lib/Transforms/InstCombine/InstCombineSelect.cpp

     
    2004 2004 return nullptr;
    2005 2005 }
    2006 2006
    2007 /// Match a sadd_sat or ssub_sat which is using min/max to clamp the value.
    2008 Instruction *InstCombiner::matchSAddSubSat(SelectInst &MinMax1) {
    2009 Type *Ty = MinMax1.getType();
    2010
    2011 // We are looking for a tree of:
    2012 // max(INT_MIN, min(INT_MAX, add(sext(A), sext(B))))
    2013 // Where the min and max could be reversed
    2014 Instruction *MinMax2;
    2015 BinaryOperator *AddSub;
    2016 const APInt *MinValue, *MaxValue;
    2017 if (match(&MinMax1, m_SMin(m_Instruction(MinMax2), m_APInt(MaxValue)))) {
    2018 if (!match(MinMax2, m_SMax(m_BinOp(AddSub), m_APInt(MinValue))))
    2019 return nullptr;
    2020 } else if (match(&MinMax1,
    2021 m_SMax(m_Instruction(MinMax2), m_APInt(MinValue)))) {
    2022 if (!match(MinMax2, m_SMin(m_BinOp(AddSub), m_APInt(MaxValue))))
    2023 return nullptr;
    2024 } else
    2025 return nullptr;
    2026
    2027 // Check that the constants clamp a saturate, and that the new type would be
    2028 // sensible to convert to.
    2029 if (!(*MaxValue + 1).isPowerOf2() || -*MinValue != *MaxValue + 1)
    2030 return nullptr;
    2031 // In what bitwidth can this be treated as saturating arithmetics?
    2032 unsigned NewBitWidth = (*MaxValue + 1).logBase2() + 1;
    2033 // FIXME: This isn't quite right for vectors, but using the scalar type is a
    2034 // good first approximation for what should be done there.
    2035 if (!shouldChangeType(Ty->getScalarType()->getIntegerBitWidth(), NewBitWidth))
    2036 return nullptr;
    2037
    2038 // Also make sure that the number of uses is as expected. The "3"s are for the
    2039 // the two items of min/max (the compare and the select).
    2040 if (MinMax2->hasNUsesOrMore(3) || AddSub->hasNUsesOrMore(3))
    2041 return nullptr;
    2042
    2043 // Create the new type (which can be a vector type)
    2044 Type *NewTy = Ty->getWithNewBitWidth(NewBitWidth);
    2045 // Match the two extends from the add/sub
    2046 Value *A, *B;
    2047 if(!match(AddSub, m_BinOp(m_SExt(m_Value(A)), m_SExt(m_Value(B)))))
    2048 return nullptr;
    2049 // And check the incoming values are of a type smaller than or equal to the
    2050 // size of the saturation. Otherwise the higher bits can cause different
    2051 // results.
    2052 if (A->getType()->getScalarSizeInBits() > NewBitWidth ||
    2053 B->getType()->getScalarSizeInBits() > NewBitWidth)
    2054 return nullptr;
    2055
    2056 Intrinsic::ID IntrinsicID;
    2057 if (AddSub->getOpcode() == Instruction::Add)
    2058 IntrinsicID = Intrinsic::sadd_sat;
    2059 else if (AddSub->getOpcode() == Instruction::Sub)
    2060 IntrinsicID = Intrinsic::ssub_sat;
    2061 else
    2062 return nullptr;
    2063
    2064 // Finally create and return the sat intrinsic, truncated to the new type
    2065 Function *F = Intrinsic::getDeclaration(MinMax1.getModule(), IntrinsicID, NewTy);
    2066 Value *AT = Builder.CreateSExt(A, NewTy);
    2067 Value *BT = Builder.CreateSExt(B, NewTy);
    2068 Value *Sat = Builder.CreateCall(F, {AT, BT});
    2069 return CastInst::Create(Instruction::SExt, Sat, Ty);
    2070 }
    2071
    2007 2072 /// Reduce a sequence of min/max with a common operand.
    2008 2073 static Instruction *factorizeMinMaxTree(SelectPatternFlavor SPF, Value *LHS,
    2009 2074 Value *RHS,
     
    2430 2495
    2431 2496 if (Instruction *I = factorizeMinMaxTree(SPF, LHS, RHS, Builder))
    2432 2497 return I;
    2498 if (Instruction *I = matchSAddSubSat(SI))
    2499 return I;
    2433 2500 }
    2434 2501 }
    2435 2502
  • llvm/trunk/test/Transforms/InstCombine/sadd_sat.ll

     
    6 6 define i32 @sadd_sat32(i32 %a, i32 %b) {
    7 7 ; CHECK-LABEL: @sadd_sat32(
    8 8 ; CHECK-NEXT: entry:
    9 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    10 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
    11 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
    12 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
    13 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
    14 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
    15 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
    16 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
    17 ; CHECK-NEXT: ret i32 [[CONV7]]
    9 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
    10 ; CHECK-NEXT: ret i32 [[TMP0]]
    18 11 ;
    19 12 entry:
    20 13 %conv = sext i32 %a to i64
     
    31 24 define i32 @ssub_sat32(i32 %a, i32 %b) {
    32 25 ; CHECK-LABEL: @ssub_sat32(
    33 26 ; CHECK-NEXT: entry:
    34 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    35 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
    36 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[CONV]], [[CONV1]]
    37 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[SUB]], 2147483647
    38 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[SUB]], i64 2147483647
    39 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
    40 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
    41 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
    42 ; CHECK-NEXT: ret i32 [[CONV7]]
    27 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.ssub.sat.i32(i32 [[A:%.*]], i32 [[B:%.*]])
    28 ; CHECK-NEXT: ret i32 [[TMP0]]
    43 29 ;
    44 30 entry:
    45 31 %conv = sext i32 %a to i64
     
    81 67 define signext i16 @sadd_sat16(i16 signext %a, i16 signext %b) {
    82 68 ; CHECK-LABEL: @sadd_sat16(
    83 69 ; CHECK-NEXT: entry:
    84 ; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
    85 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
    86 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
    87 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 32767
    88 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 32767
    89 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
    90 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
    91 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
    92 ; CHECK-NEXT: ret i16 [[CONV9]]
    70 ; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.sadd.sat.i16(i16 [[B:%.*]], i16 [[A:%.*]])
    71 ; CHECK-NEXT: ret i16 [[TMP0]]
    93 72 ;
    94 73 entry:
    95 74 %conv = sext i16 %a to i32
     
    106 85 define signext i16 @ssub_sat16(i16 signext %a, i16 signext %b) {
    107 86 ; CHECK-LABEL: @ssub_sat16(
    108 87 ; CHECK-NEXT: entry:
    109 ; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32
    110 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32
    111 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
    112 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 32767
    113 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 32767
    114 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -32768
    115 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -32768
    116 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i16
    117 ; CHECK-NEXT: ret i16 [[CONV9]]
    88 ; CHECK-NEXT: [[TMP0:%.*]] = call i16 @llvm.ssub.sat.i16(i16 [[A:%.*]], i16 [[B:%.*]])
    89 ; CHECK-NEXT: ret i16 [[TMP0]]
    118 90 ;
    119 91 entry:
    120 92 %conv = sext i16 %a to i32
     
    131 103 define signext i8 @sadd_sat8(i8 signext %a, i8 signext %b) {
    132 104 ; CHECK-LABEL: @sadd_sat8(
    133 105 ; CHECK-NEXT: entry:
    134 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
    135 ; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
    136 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[CONV1]], [[CONV]]
    137 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[ADD]], 127
    138 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[ADD]], i32 127
    139 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
    140 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
    141 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
    142 ; CHECK-NEXT: ret i8 [[CONV9]]
    106 ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]])
    107 ; CHECK-NEXT: ret i8 [[TMP0]]
    143 108 ;
    144 109 entry:
    145 110 %conv = sext i8 %a to i32
     
    156 121 define signext i8 @ssub_sat8(i8 signext %a, i8 signext %b) {
    157 122 ; CHECK-LABEL: @ssub_sat8(
    158 123 ; CHECK-NEXT: entry:
    159 ; CHECK-NEXT: [[CONV:%.*]] = sext i8 [[A:%.*]] to i32
    160 ; CHECK-NEXT: [[CONV1:%.*]] = sext i8 [[B:%.*]] to i32
    161 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]
    162 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i32 [[SUB]], 127
    163 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i32 [[SUB]], i32 127
    164 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[SPEC_STORE_SELECT]], -128
    165 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i32 [[SPEC_STORE_SELECT]], i32 -128
    166 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i32 [[SPEC_STORE_SELECT10]] to i8
    167 ; CHECK-NEXT: ret i8 [[CONV9]]
    124 ; CHECK-NEXT: [[TMP0:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]])
    125 ; CHECK-NEXT: ret i8 [[TMP0]]
    168 126 ;
    169 127 entry:
    170 128 %conv = sext i8 %a to i32
     
    181 139 define signext i64 @sadd_sat64(i64 signext %a, i64 signext %b) {
    182 140 ; CHECK-LABEL: @sadd_sat64(
    183 141 ; CHECK-NEXT: entry:
    184 ; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
    185 ; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
    186 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i65 [[CONV1]], [[CONV]]
    187 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[ADD]], 9223372036854775807
    188 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[ADD]], i65 9223372036854775807
    189 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
    190 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
    191 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
    192 ; CHECK-NEXT: ret i64 [[CONV9]]
    142 ; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.sadd.sat.i64(i64 [[B:%.*]], i64 [[A:%.*]])
    143 ; CHECK-NEXT: ret i64 [[TMP0]]
    193 144 ;
    194 145 entry:
    195 146 %conv = sext i64 %a to i65
     
    206 157 define signext i64 @ssub_sat64(i64 signext %a, i64 signext %b) {
    207 158 ; CHECK-LABEL: @ssub_sat64(
    208 159 ; CHECK-NEXT: entry:
    209 ; CHECK-NEXT: [[CONV:%.*]] = sext i64 [[A:%.*]] to i65
    210 ; CHECK-NEXT: [[CONV1:%.*]] = sext i64 [[B:%.*]] to i65
    211 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i65 [[CONV]], [[CONV1]]
    212 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i65 [[SUB]], 9223372036854775807
    213 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i65 [[SUB]], i65 9223372036854775807
    214 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i65 [[SPEC_STORE_SELECT]], -9223372036854775808
    215 ; CHECK-NEXT: [[SPEC_STORE_SELECT10:%.*]] = select i1 [[TMP1]], i65 [[SPEC_STORE_SELECT]], i65 -9223372036854775808
    216 ; CHECK-NEXT: [[CONV9:%.*]] = trunc i65 [[SPEC_STORE_SELECT10]] to i64
    217 ; CHECK-NEXT: ret i64 [[CONV9]]
    160 ; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.ssub.sat.i64(i64 [[A:%.*]], i64 [[B:%.*]])
    161 ; CHECK-NEXT: ret i64 [[TMP0]]
    218 162 ;
    219 163 entry:
    220 164 %conv = sext i64 %a to i65
     
    281 225 define <4 x i32> @sadd_satv4i32(<4 x i32> %a, <4 x i32> %b) {
    282 226 ; CHECK-LABEL: @sadd_satv4i32(
    283 227 ; CHECK-NEXT: entry:
    284 ; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
    285 ; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
    286 ; CHECK-NEXT: [[ADD:%.*]] = add nsw <4 x i64> [[CONV1]], [[CONV]]
    287 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
    288 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
    289 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
    290 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
    291 ; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
    292 ; CHECK-NEXT: ret <4 x i32> [[CONV7]]
    228 ; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
    229 ; CHECK-NEXT: ret <4 x i32> [[TMP0]]
    293 230 ;
    294 231 entry:
    295 232 %conv = sext <4 x i32> %a to <4 x i64>
     
    306 243 define <4 x i32> @ssub_satv4i32(<4 x i32> %a, <4 x i32> %b) {
    307 244 ; CHECK-LABEL: @ssub_satv4i32(
    308 245 ; CHECK-NEXT: entry:
    309 ; CHECK-NEXT: [[CONV:%.*]] = sext <4 x i32> [[A:%.*]] to <4 x i64>
    310 ; CHECK-NEXT: [[CONV1:%.*]] = sext <4 x i32> [[B:%.*]] to <4 x i64>
    311 ; CHECK-NEXT: [[ADD:%.*]] = sub nsw <4 x i64> [[CONV1]], [[CONV]]
    312 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt <4 x i64> [[ADD]], <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
    313 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select <4 x i1> [[TMP0]], <4 x i64> [[ADD]], <4 x i64> <i64 2147483647, i64 2147483647, i64 2147483647, i64 2147483647>
    314 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <4 x i64> [[SPEC_STORE_SELECT]], <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
    315 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select <4 x i1> [[TMP1]], <4 x i64> [[SPEC_STORE_SELECT]], <4 x i64> <i64 -2147483648, i64 -2147483648, i64 -2147483648, i64 -2147483648>
    316 ; CHECK-NEXT: [[CONV7:%.*]] = trunc <4 x i64> [[SPEC_STORE_SELECT8]] to <4 x i32>
    317 ; CHECK-NEXT: ret <4 x i32> [[CONV7]]
    246 ; CHECK-NEXT: [[TMP0:%.*]] = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> [[B:%.*]], <4 x i32> [[A:%.*]])
    247 ; CHECK-NEXT: ret <4 x i32> [[TMP0]]
    318 248 ;
    319 249 entry:
    320 250 %conv = sext <4 x i32> %a to <4 x i64>
     
    370 300 define i32 @sadd_sat32_extrause_1(i32 %a, i32 %b) {
    371 301 ; CHECK-LABEL: @sadd_sat32_extrause_1(
    372 302 ; CHECK-NEXT: entry:
    373 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    374 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
    375 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
    376 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
    377 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
    378 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
    379 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
    380 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
    303 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
    304 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
    381 305 ; CHECK-NEXT: call void @use64(i64 [[SPEC_STORE_SELECT8]])
    382 ; CHECK-NEXT: ret i32 [[CONV7]]
    306 ; CHECK-NEXT: ret i32 [[TMP0]]
    383 307 ;
    384 308 entry:
    385 309 %conv = sext i32 %a to i64
     
    476 400 define i32 @sadd_sat32_ext16(i32 %a, i16 %b) {
    477 401 ; CHECK-LABEL: @sadd_sat32_ext16(
    478 402 ; CHECK-NEXT: entry:
    479 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    480 ; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i64
    481 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
    482 ; CHECK-NEXT: [[TMP0:%.*]] = icmp slt i64 [[ADD]], 2147483647
    483 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 2147483647
    484 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i64 [[SPEC_STORE_SELECT]], -2147483648
    485 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 -2147483648
    486 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
    487 ; CHECK-NEXT: ret i32 [[CONV7]]
    403 ; CHECK-NEXT: [[TMP0:%.*]] = sext i16 [[B:%.*]] to i32
    404 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[TMP0]], i32 [[A:%.*]])
    405 ; CHECK-NEXT: ret i32 [[TMP1]]
    488 406 ;
    489 407 entry:
    490 408 %conv = sext i32 %a to i64
     
    549 467 define i32 @sadd_sat32_maxmin(i32 %a, i32 %b) {
    550 468 ; CHECK-LABEL: @sadd_sat32_maxmin(
    551 469 ; CHECK-NEXT: entry:
    552 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    553 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
    554 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
    555 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
    556 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
    557 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
    558 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
    559 ; CHECK-NEXT: [[CONV7:%.*]] = trunc i64 [[SPEC_STORE_SELECT8]] to i32
    560 ; CHECK-NEXT: ret i32 [[CONV7]]
    470 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
    471 ; CHECK-NEXT: ret i32 [[TMP0]]
    561 472 ;
    562 473 entry:
    563 474 %conv = sext i32 %a to i64
     
    574 485 define i64 @sadd_sat32_notrunc(i32 %a, i32 %b) {
    575 486 ; CHECK-LABEL: @sadd_sat32_notrunc(
    576 487 ; CHECK-NEXT: entry:
    577 ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[A:%.*]] to i64
    578 ; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[B:%.*]] to i64
    579 ; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV1]], [[CONV]]
    580 ; CHECK-NEXT: [[TMP0:%.*]] = icmp sgt i64 [[ADD]], -2147483648
    581 ; CHECK-NEXT: [[SPEC_STORE_SELECT:%.*]] = select i1 [[TMP0]], i64 [[ADD]], i64 -2147483648
    582 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[SPEC_STORE_SELECT]], 2147483647
    583 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = select i1 [[TMP1]], i64 [[SPEC_STORE_SELECT]], i64 2147483647
    488 ; CHECK-NEXT: [[TMP0:%.*]] = call i32 @llvm.sadd.sat.i32(i32 [[B:%.*]], i32 [[A:%.*]])
    489 ; CHECK-NEXT: [[SPEC_STORE_SELECT8:%.*]] = sext i32 [[TMP0]] to i64
    584 490 ; CHECK-NEXT: ret i64 [[SPEC_STORE_SELECT8]]
    585 491 ;
    586 492 entry: