1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; 5; Saturating addition. 6; 7 8declare i8 @llvm.uadd.sat.i8(i8, i8) 9declare i8 @llvm.sadd.sat.i8(i8, i8) 10declare <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8>, <2 x i8>) 11declare <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8>, <2 x i8>) 12 13; Constant uadd argument is canonicalized to the right. 14define i8 @test_scalar_uadd_canonical(i8 %a) { 15; CHECK-LABEL: @test_scalar_uadd_canonical( 16; CHECK-NEXT: [[X:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 10) 17; CHECK-NEXT: ret i8 [[X]] 18; 19 %x = call i8 @llvm.uadd.sat.i8(i8 10, i8 %a) 20 ret i8 %x 21} 22 23define <2 x i8> @test_vector_uadd_canonical(<2 x i8> %a) { 24; CHECK-LABEL: @test_vector_uadd_canonical( 25; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 20>) 26; CHECK-NEXT: ret <2 x i8> [[X]] 27; 28 %x = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> <i8 10, i8 20>, <2 x i8> %a) 29 ret <2 x i8> %x 30} 31 32; Constant sadd argument is canonicalized to the right. 33define i8 @test_scalar_sadd_canonical(i8 %a) { 34; CHECK-LABEL: @test_scalar_sadd_canonical( 35; CHECK-NEXT: [[X:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10) 36; CHECK-NEXT: ret i8 [[X]] 37; 38 %x = call i8 @llvm.sadd.sat.i8(i8 -10, i8 %a) 39 ret i8 %x 40} 41 42define <2 x i8> @test_vector_sadd_canonical(<2 x i8> %a) { 43; CHECK-LABEL: @test_vector_sadd_canonical( 44; CHECK-NEXT: [[X:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 -20>) 45; CHECK-NEXT: ret <2 x i8> [[X]] 46; 47 %x = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 10, i8 -20>, <2 x i8> %a) 48 ret <2 x i8> %x 49} 50 51; Can combine uadds with constant operands. 52define i8 @test_scalar_uadd_combine(i8 %a) { 53; CHECK-LABEL: @test_scalar_uadd_combine( 54; CHECK-NEXT: [[X2:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 30) 55; CHECK-NEXT: ret i8 [[X2]] 56; 57 %x1 = call i8 @llvm.uadd.sat.i8(i8 %a, i8 10) 58 %x2 = call i8 @llvm.uadd.sat.i8(i8 %x1, i8 20) 59 ret i8 %x2 60} 61 62define <2 x i8> @test_vector_uadd_combine(<2 x i8> %a) { 63; CHECK-LABEL: @test_vector_uadd_combine( 64; CHECK-NEXT: [[X2:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 30)) 65; CHECK-NEXT: ret <2 x i8> [[X2]] 66; 67 %x1 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>) 68 %x2 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %x1, <2 x i8> <i8 20, i8 20>) 69 ret <2 x i8> %x2 70} 71 72; This could simplify, but currently doesn't. 73define <2 x i8> @test_vector_uadd_combine_non_splat(<2 x i8> %a) { 74; CHECK-LABEL: @test_vector_uadd_combine_non_splat( 75; CHECK-NEXT: [[X1:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 20>) 76; CHECK-NEXT: [[X2:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X1]], <2 x i8> <i8 30, i8 40>) 77; CHECK-NEXT: ret <2 x i8> [[X2]] 78; 79 %x1 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 20>) 80 %x2 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %x1, <2 x i8> <i8 30, i8 40>) 81 ret <2 x i8> %x2 82} 83 84; Can combine uadds even if they overflow. 85define i8 @test_scalar_uadd_overflow(i8 %a) { 86; CHECK-LABEL: @test_scalar_uadd_overflow( 87; CHECK-NEXT: ret i8 -1 88; 89 %y1 = call i8 @llvm.uadd.sat.i8(i8 %a, i8 100) 90 %y2 = call i8 @llvm.uadd.sat.i8(i8 %y1, i8 200) 91 ret i8 %y2 92} 93 94define <2 x i8> @test_vector_uadd_overflow(<2 x i8> %a) { 95; CHECK-LABEL: @test_vector_uadd_overflow( 96; CHECK-NEXT: ret <2 x i8> splat (i8 -1) 97; 98 %y1 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 100, i8 100>) 99 %y2 = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %y1, <2 x i8> <i8 200, i8 200>) 100 ret <2 x i8> %y2 101} 102 103; Can combine sadds if sign matches. 104define i8 @test_scalar_sadd_both_positive(i8 %a) { 105; CHECK-LABEL: @test_scalar_sadd_both_positive( 106; CHECK-NEXT: [[Z2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 30) 107; CHECK-NEXT: ret i8 [[Z2]] 108; 109 %z1 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10) 110 %z2 = call i8 @llvm.sadd.sat.i8(i8 %z1, i8 20) 111 ret i8 %z2 112} 113 114define <2 x i8> @test_vector_sadd_both_positive(<2 x i8> %a) { 115; CHECK-LABEL: @test_vector_sadd_both_positive( 116; CHECK-NEXT: [[Z2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 30)) 117; CHECK-NEXT: ret <2 x i8> [[Z2]] 118; 119 %z1 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>) 120 %z2 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %z1, <2 x i8> <i8 20, i8 20>) 121 ret <2 x i8> %z2 122} 123 124define i8 @test_scalar_sadd_both_negative(i8 %a) { 125; CHECK-LABEL: @test_scalar_sadd_both_negative( 126; CHECK-NEXT: [[U2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -30) 127; CHECK-NEXT: ret i8 [[U2]] 128; 129 %u1 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 -10) 130 %u2 = call i8 @llvm.sadd.sat.i8(i8 %u1, i8 -20) 131 ret i8 %u2 132} 133 134define <2 x i8> @test_vector_sadd_both_negative(<2 x i8> %a) { 135; CHECK-LABEL: @test_vector_sadd_both_negative( 136; CHECK-NEXT: [[U2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 -30)) 137; CHECK-NEXT: ret <2 x i8> [[U2]] 138; 139 %u1 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 -10, i8 -10>) 140 %u2 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %u1, <2 x i8> <i8 -20, i8 -20>) 141 ret <2 x i8> %u2 142} 143 144; Can't combine sadds if constants have different sign. 145define i8 @test_scalar_sadd_different_sign(i8 %a) { 146; CHECK-LABEL: @test_scalar_sadd_different_sign( 147; CHECK-NEXT: [[V1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 10) 148; CHECK-NEXT: [[V2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[V1]], i8 -20) 149; CHECK-NEXT: ret i8 [[V2]] 150; 151 %v1 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 10) 152 %v2 = call i8 @llvm.sadd.sat.i8(i8 %v1, i8 -20) 153 ret i8 %v2 154} 155 156; Can't combine sadds if they overflow. 157define i8 @test_scalar_sadd_overflow(i8 %a) { 158; CHECK-LABEL: @test_scalar_sadd_overflow( 159; CHECK-NEXT: [[W1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 100) 160; CHECK-NEXT: [[W2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[W1]], i8 100) 161; CHECK-NEXT: ret i8 [[W2]] 162; 163 %w1 = call i8 @llvm.sadd.sat.i8(i8 %a, i8 100) 164 %w2 = call i8 @llvm.sadd.sat.i8(i8 %w1, i8 100) 165 ret i8 %w2 166} 167 168; neg uadd neg always overflows. 169define i8 @test_scalar_uadd_neg_neg(i8 %a) { 170; CHECK-LABEL: @test_scalar_uadd_neg_neg( 171; CHECK-NEXT: ret i8 -1 172; 173 %a_neg = or i8 %a, -128 174 %r = call i8 @llvm.uadd.sat.i8(i8 %a_neg, i8 -10) 175 ret i8 %r 176} 177 178define <2 x i8> @test_vector_uadd_neg_neg(<2 x i8> %a) { 179; CHECK-LABEL: @test_vector_uadd_neg_neg( 180; CHECK-NEXT: ret <2 x i8> splat (i8 -1) 181; 182 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 183 %r = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 -10, i8 -20>) 184 ret <2 x i8> %r 185} 186 187; nneg uadd nneg never overflows. 188define i8 @test_scalar_uadd_nneg_nneg(i8 %a) { 189; CHECK-LABEL: @test_scalar_uadd_nneg_nneg( 190; CHECK-NEXT: [[A_NNEG:%.*]] = and i8 [[A:%.*]], 127 191; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[A_NNEG]], 10 192; CHECK-NEXT: ret i8 [[R]] 193; 194 %a_nneg = and i8 %a, 127 195 %r = call i8 @llvm.uadd.sat.i8(i8 %a_nneg, i8 10) 196 ret i8 %r 197} 198 199define <2 x i8> @test_vector_uadd_nneg_nneg(<2 x i8> %a) { 200; CHECK-LABEL: @test_vector_uadd_nneg_nneg( 201; CHECK-NEXT: [[A_NNEG:%.*]] = and <2 x i8> [[A:%.*]], splat (i8 127) 202; CHECK-NEXT: [[R:%.*]] = add nuw <2 x i8> [[A_NNEG]], <i8 10, i8 20> 203; CHECK-NEXT: ret <2 x i8> [[R]] 204; 205 %a_nneg = and <2 x i8> %a, <i8 127, i8 127> 206 %r = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a_nneg, <2 x i8> <i8 10, i8 20>) 207 ret <2 x i8> %r 208} 209 210; neg uadd nneg might overflow. 211define i8 @test_scalar_uadd_neg_nneg(i8 %a) { 212; CHECK-LABEL: @test_scalar_uadd_neg_nneg( 213; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 214; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A_NEG]], i8 10) 215; CHECK-NEXT: ret i8 [[R]] 216; 217 %a_neg = or i8 %a, -128 218 %r = call i8 @llvm.uadd.sat.i8(i8 %a_neg, i8 10) 219 ret i8 %r 220} 221 222define <2 x i8> @test_vector_uadd_neg_nneg(<2 x i8> %a) { 223; CHECK-LABEL: @test_vector_uadd_neg_nneg( 224; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 225; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[A_NEG]], <2 x i8> <i8 10, i8 20>) 226; CHECK-NEXT: ret <2 x i8> [[R]] 227; 228 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 229 %r = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 10, i8 20>) 230 ret <2 x i8> %r 231} 232 233define i8 @test_scalar_uadd_never_overflows(i8 %a) { 234; CHECK-LABEL: @test_scalar_uadd_never_overflows( 235; CHECK-NEXT: [[A_MASKED:%.*]] = and i8 [[A:%.*]], -127 236; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[A_MASKED]], 1 237; CHECK-NEXT: ret i8 [[R]] 238; 239 %a_masked = and i8 %a, 129 240 %r = call i8 @llvm.uadd.sat.i8(i8 %a_masked, i8 1) 241 ret i8 %r 242} 243 244define <2 x i8> @test_vector_uadd_never_overflows(<2 x i8> %a) { 245; CHECK-LABEL: @test_vector_uadd_never_overflows( 246; CHECK-NEXT: [[A_MASKED:%.*]] = and <2 x i8> [[A:%.*]], splat (i8 -127) 247; CHECK-NEXT: [[R:%.*]] = add nuw nsw <2 x i8> [[A_MASKED]], splat (i8 1) 248; CHECK-NEXT: ret <2 x i8> [[R]] 249; 250 %a_masked = and <2 x i8> %a, <i8 129, i8 129> 251 %r = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a_masked, <2 x i8> <i8 1, i8 1>) 252 ret <2 x i8> %r 253} 254 255define i8 @test_scalar_uadd_always_overflows(i8 %a) { 256; CHECK-LABEL: @test_scalar_uadd_always_overflows( 257; CHECK-NEXT: ret i8 -1 258; 259 %a_masked = or i8 %a, 192 260 %r = call i8 @llvm.uadd.sat.i8(i8 %a_masked, i8 64) 261 ret i8 %r 262} 263 264define <2 x i8> @test_vector_uadd_always_overflows(<2 x i8> %a) { 265; CHECK-LABEL: @test_vector_uadd_always_overflows( 266; CHECK-NEXT: ret <2 x i8> splat (i8 -1) 267; 268 %a_masked = or <2 x i8> %a, <i8 192, i8 192> 269 %r = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %a_masked, <2 x i8> <i8 64, i8 64>) 270 ret <2 x i8> %r 271} 272 273; neg sadd nneg never overflows. 274define i8 @test_scalar_sadd_neg_nneg(i8 %a) { 275; CHECK-LABEL: @test_scalar_sadd_neg_nneg( 276; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 277; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NEG]], 10 278; CHECK-NEXT: ret i8 [[R]] 279; 280 %a_neg = or i8 %a, -128 281 %r = call i8 @llvm.sadd.sat.i8(i8 %a_neg, i8 10) 282 ret i8 %r 283} 284 285define <2 x i8> @test_vector_sadd_neg_nneg(<2 x i8> %a) { 286; CHECK-LABEL: @test_vector_sadd_neg_nneg( 287; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 288; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[A_NEG]], <i8 10, i8 20> 289; CHECK-NEXT: ret <2 x i8> [[R]] 290; 291 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 292 %r = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 10, i8 20>) 293 ret <2 x i8> %r 294} 295 296; nneg sadd neg never overflows. 297define i8 @test_scalar_sadd_nneg_neg(i8 %a) { 298; CHECK-LABEL: @test_scalar_sadd_nneg_neg( 299; CHECK-NEXT: [[A_NNEG:%.*]] = and i8 [[A:%.*]], 127 300; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NNEG]], -10 301; CHECK-NEXT: ret i8 [[R]] 302; 303 %a_nneg = and i8 %a, 127 304 %r = call i8 @llvm.sadd.sat.i8(i8 %a_nneg, i8 -10) 305 ret i8 %r 306} 307 308define <2 x i8> @test_vector_sadd_nneg_neg(<2 x i8> %a) { 309; CHECK-LABEL: @test_vector_sadd_nneg_neg( 310; CHECK-NEXT: [[A_NNEG:%.*]] = and <2 x i8> [[A:%.*]], splat (i8 127) 311; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[A_NNEG]], <i8 -10, i8 -20> 312; CHECK-NEXT: ret <2 x i8> [[R]] 313; 314 %a_nneg = and <2 x i8> %a, <i8 127, i8 127> 315 %r = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a_nneg, <2 x i8> <i8 -10, i8 -20>) 316 ret <2 x i8> %r 317} 318 319; neg sadd neg might overflow. 320define i8 @test_scalar_sadd_neg_neg(i8 %a) { 321; CHECK-LABEL: @test_scalar_sadd_neg_neg( 322; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 323; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A_NEG]], i8 -10) 324; CHECK-NEXT: ret i8 [[R]] 325; 326 %a_neg = or i8 %a, -128 327 %r = call i8 @llvm.sadd.sat.i8(i8 %a_neg, i8 -10) 328 ret i8 %r 329} 330 331define <2 x i8> @test_vector_sadd_neg_neg(<2 x i8> %a) { 332; CHECK-LABEL: @test_vector_sadd_neg_neg( 333; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 334; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A_NEG]], <2 x i8> <i8 -10, i8 -20>) 335; CHECK-NEXT: ret <2 x i8> [[R]] 336; 337 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 338 %r = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 -10, i8 -20>) 339 ret <2 x i8> %r 340} 341 342define i8 @test_scalar_sadd_always_overflows_low(i8 %a) { 343; CHECK-LABEL: @test_scalar_sadd_always_overflows_low( 344; CHECK-NEXT: ret i8 -128 345; 346 %cmp = icmp slt i8 %a, -120 347 %min = select i1 %cmp, i8 %a, i8 -120 348 %r = call i8 @llvm.sadd.sat.i8(i8 %min, i8 -10) 349 ret i8 %r 350} 351 352define i8 @test_scalar_sadd_always_overflows_high(i8 %a) { 353; CHECK-LABEL: @test_scalar_sadd_always_overflows_high( 354; CHECK-NEXT: ret i8 127 355; 356 %cmp = icmp sgt i8 %a, 120 357 %max = select i1 %cmp, i8 %a, i8 120 358 %r = call i8 @llvm.sadd.sat.i8(i8 %max, i8 10) 359 ret i8 %r 360} 361 362; While this is a no-overflow condition, the nuw flag gets lost due to 363; canonicalization and we can no longer determine this 364define i8 @test_scalar_uadd_sub_nuw_lost_no_ov(i8 %a) { 365; CHECK-LABEL: @test_scalar_uadd_sub_nuw_lost_no_ov( 366; CHECK-NEXT: [[B:%.*]] = add i8 [[A:%.*]], -10 367; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[B]], i8 9) 368; CHECK-NEXT: ret i8 [[R]] 369; 370 %b = sub nuw i8 %a, 10 371 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 9) 372 ret i8 %r 373} 374 375define i8 @test_scalar_uadd_urem_no_ov(i8 %a) { 376; CHECK-LABEL: @test_scalar_uadd_urem_no_ov( 377; CHECK-NEXT: [[B:%.*]] = urem i8 [[A:%.*]], 100 378; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[B]], -100 379; CHECK-NEXT: ret i8 [[R]] 380; 381 %b = urem i8 %a, 100 382 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 156) 383 ret i8 %r 384} 385 386define i8 @test_scalar_uadd_urem_may_ov(i8 %a) { 387; CHECK-LABEL: @test_scalar_uadd_urem_may_ov( 388; CHECK-NEXT: [[B:%.*]] = urem i8 [[A:%.*]], 100 389; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[B]], i8 -99) 390; CHECK-NEXT: ret i8 [[R]] 391; 392 %b = urem i8 %a, 100 393 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 157) 394 ret i8 %r 395} 396 397; We have a constant range for the LHS, but only known bits for the RHS 398define i8 @test_scalar_uadd_udiv_known_bits(i8 %a, i8 %b) { 399; CHECK-LABEL: @test_scalar_uadd_udiv_known_bits( 400; CHECK-NEXT: [[AA:%.*]] = udiv i8 -66, [[A:%.*]] 401; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 63 402; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[AA]], [[BB]] 403; CHECK-NEXT: ret i8 [[R]] 404; 405 %aa = udiv i8 190, %a 406 %bb = and i8 %b, 63 407 %r = call i8 @llvm.uadd.sat.i8(i8 %aa, i8 %bb) 408 ret i8 %r 409} 410 411define i8 @test_scalar_sadd_srem_no_ov(i8 %a) { 412; CHECK-LABEL: @test_scalar_sadd_srem_no_ov( 413; CHECK-NEXT: [[B:%.*]] = srem i8 [[A:%.*]], 100 414; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[B]], 28 415; CHECK-NEXT: ret i8 [[R]] 416; 417 %b = srem i8 %a, 100 418 %r = call i8 @llvm.sadd.sat.i8(i8 %b, i8 28) 419 ret i8 %r 420} 421 422define i8 @test_scalar_sadd_srem_may_ov(i8 %a) { 423; CHECK-LABEL: @test_scalar_sadd_srem_may_ov( 424; CHECK-NEXT: [[B:%.*]] = srem i8 [[A:%.*]], 100 425; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[B]], i8 29) 426; CHECK-NEXT: ret i8 [[R]] 427; 428 %b = srem i8 %a, 100 429 %r = call i8 @llvm.sadd.sat.i8(i8 %b, i8 29) 430 ret i8 %r 431} 432 433define i8 @test_scalar_sadd_srem_and_no_ov(i8 %a, i8 %b) { 434; CHECK-LABEL: @test_scalar_sadd_srem_and_no_ov( 435; CHECK-NEXT: [[AA:%.*]] = srem i8 [[A:%.*]], 100 436; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 15 437; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[AA]], [[BB]] 438; CHECK-NEXT: ret i8 [[R]] 439; 440 %aa = srem i8 %a, 100 441 %bb = and i8 %b, 15 442 %r = call i8 @llvm.sadd.sat.i8(i8 %aa, i8 %bb) 443 ret i8 %r 444} 445 446; 447; Saturating subtraction. 448; 449 450declare i8 @llvm.usub.sat.i8(i8, i8) 451declare i8 @llvm.ssub.sat.i8(i8, i8) 452declare <2 x i8> @llvm.usub.sat.v2i8(<2 x i8>, <2 x i8>) 453declare <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8>, <2 x i8>) 454 455; Cannot canonicalize usub to uadd. 456define i8 @test_scalar_usub_canonical(i8 %a) { 457; CHECK-LABEL: @test_scalar_usub_canonical( 458; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10) 459; CHECK-NEXT: ret i8 [[R]] 460; 461 %r = call i8 @llvm.usub.sat.i8(i8 %a, i8 10) 462 ret i8 %r 463} 464 465; Canonicalize ssub to sadd. 466define i8 @test_scalar_ssub_canonical(i8 %a) { 467; CHECK-LABEL: @test_scalar_ssub_canonical( 468; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10) 469; CHECK-NEXT: ret i8 [[R]] 470; 471 %r = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10) 472 ret i8 %r 473} 474 475define <2 x i8> @test_vector_ssub_canonical(<2 x i8> %a) { 476; CHECK-LABEL: @test_vector_ssub_canonical( 477; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 -10)) 478; CHECK-NEXT: ret <2 x i8> [[R]] 479; 480 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>) 481 ret <2 x i8> %r 482} 483 484define <2 x i8> @test_vector_ssub_canonical_min_non_splat(<2 x i8> %a) { 485; CHECK-LABEL: @test_vector_ssub_canonical_min_non_splat( 486; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -10, i8 10>) 487; CHECK-NEXT: ret <2 x i8> [[R]] 488; 489 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 -10>) 490 ret <2 x i8> %r 491} 492 493; Cannot canonicalize signed min. 494define i8 @test_scalar_ssub_canonical_min(i8 %a) { 495; CHECK-LABEL: @test_scalar_ssub_canonical_min( 496; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[A:%.*]], i8 -128) 497; CHECK-NEXT: ret i8 [[R]] 498; 499 %r = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -128) 500 ret i8 %r 501} 502 503define <2 x i8> @test_vector_ssub_canonical_min(<2 x i8> %a) { 504; CHECK-LABEL: @test_vector_ssub_canonical_min( 505; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 -128, i8 -10>) 506; CHECK-NEXT: ret <2 x i8> [[R]] 507; 508 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 -128, i8 -10>) 509 ret <2 x i8> %r 510} 511 512; Can combine usubs with constant operands. 513define i8 @test_scalar_usub_combine(i8 %a) { 514; CHECK-LABEL: @test_scalar_usub_combine( 515; CHECK-NEXT: [[X2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 30) 516; CHECK-NEXT: ret i8 [[X2]] 517; 518 %x1 = call i8 @llvm.usub.sat.i8(i8 %a, i8 10) 519 %x2 = call i8 @llvm.usub.sat.i8(i8 %x1, i8 20) 520 ret i8 %x2 521} 522 523; Can simplify zero check followed by decrement 524define i8 @test_simplify_decrement(i8 %a) { 525; CHECK-LABEL: @test_simplify_decrement( 526; CHECK-NEXT: [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 1) 527; CHECK-NEXT: ret i8 [[I2]] 528; 529 %i = icmp eq i8 %a, 0 530 %i1 = sub i8 %a, 1 531 %i2 = select i1 %i, i8 0, i8 %i1 532 ret i8 %i2 533} 534 535declare void @use.i1(i1) 536 537define i8 @test_simplify_decrement_ne(i8 %a) { 538; CHECK-LABEL: @test_simplify_decrement_ne( 539; CHECK-NEXT: [[I:%.*]] = icmp ne i8 [[A:%.*]], 0 540; CHECK-NEXT: call void @use.i1(i1 [[I]]) 541; CHECK-NEXT: [[I2:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A]], i8 1) 542; CHECK-NEXT: ret i8 [[I2]] 543; 544 %i = icmp ne i8 %a, 0 545 call void @use.i1(i1 %i) 546 %i1 = add i8 %a, -1 547 %i2 = select i1 %i, i8 %i1, i8 0 548 ret i8 %i2 549} 550 551define <2 x i8> @test_simplify_decrement_vec(<2 x i8> %a) { 552; CHECK-LABEL: @test_simplify_decrement_vec( 553; CHECK-NEXT: [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 1)) 554; CHECK-NEXT: ret <2 x i8> [[I2]] 555; 556 %i = icmp eq <2 x i8> %a, <i8 0, i8 0> 557 %i1 = sub <2 x i8> %a, <i8 1, i8 1> 558 %i2 = select <2 x i1> %i, <2 x i8> <i8 0, i8 0>, <2 x i8> %i1 559 ret <2 x i8> %i2 560} 561 562define <2 x i8> @test_simplify_decrement_vec_poison(<2 x i8> %a) { 563; CHECK-LABEL: @test_simplify_decrement_vec_poison( 564; CHECK-NEXT: [[I2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 1)) 565; CHECK-NEXT: ret <2 x i8> [[I2]] 566; 567 %i = icmp eq <2 x i8> %a, <i8 0, i8 0> 568 %i1 = sub <2 x i8> %a, <i8 1, i8 1> 569 %i2 = select <2 x i1> %i, <2 x i8> <i8 0, i8 poison>, <2 x i8> %i1 570 ret <2 x i8> %i2 571} 572 573define i8 @test_simplify_decrement_invalid_ne(i8 %a) { 574; CHECK-LABEL: @test_simplify_decrement_invalid_ne( 575; CHECK-NEXT: [[I_NOT:%.*]] = icmp eq i8 [[A:%.*]], 0 576; CHECK-NEXT: [[I2:%.*]] = sext i1 [[I_NOT]] to i8 577; CHECK-NEXT: ret i8 [[I2]] 578; 579 %i = icmp ne i8 %a, 0 580 %i1 = sub i8 %a, 1 581 %i2 = select i1 %i, i8 0, i8 %i1 582 ret i8 %i2 583} 584 585define i8 @test_invalid_simplify_sub2(i8 %a) { 586; CHECK-LABEL: @test_invalid_simplify_sub2( 587; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0 588; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -2 589; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]] 590; CHECK-NEXT: ret i8 [[I2]] 591; 592 %i = icmp eq i8 %a, 0 593 %i1 = sub i8 %a, 2 594 %i2 = select i1 %i, i8 0, i8 %i1 595 ret i8 %i2 596} 597 598define i8 @test_invalid_simplify_eq2(i8 %a) { 599; CHECK-LABEL: @test_invalid_simplify_eq2( 600; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 2 601; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -1 602; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]] 603; CHECK-NEXT: ret i8 [[I2]] 604; 605 %i = icmp eq i8 %a, 2 606 %i1 = sub i8 %a, 1 607 %i2 = select i1 %i, i8 0, i8 %i1 608 ret i8 %i2 609} 610 611define i8 @test_invalid_simplify_select_1(i8 %a) { 612; CHECK-LABEL: @test_invalid_simplify_select_1( 613; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0 614; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -1 615; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 1, i8 [[I1]] 616; CHECK-NEXT: ret i8 [[I2]] 617; 618 %i = icmp eq i8 %a, 0 619 %i1 = sub i8 %a, 1 620 %i2 = select i1 %i, i8 1, i8 %i1 621 ret i8 %i2 622} 623 624define i8 @test_invalid_simplify_other(i8 %a, i8 %b) { 625; CHECK-LABEL: @test_invalid_simplify_other( 626; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0 627; CHECK-NEXT: [[I1:%.*]] = add i8 [[B:%.*]], -1 628; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]] 629; CHECK-NEXT: ret i8 [[I2]] 630; 631 %i = icmp eq i8 %a, 0 632 %i1 = sub i8 %b, 1 633 %i2 = select i1 %i, i8 0, i8 %i1 634 ret i8 %i2 635} 636 637define <2 x i8> @test_vector_usub_combine(<2 x i8> %a) { 638; CHECK-LABEL: @test_vector_usub_combine( 639; CHECK-NEXT: [[X2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 30)) 640; CHECK-NEXT: ret <2 x i8> [[X2]] 641; 642 %x1 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>) 643 %x2 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %x1, <2 x i8> <i8 20, i8 20>) 644 ret <2 x i8> %x2 645} 646 647; This could simplify, but currently doesn't. 648define <2 x i8> @test_vector_usub_combine_non_splat(<2 x i8> %a) { 649; CHECK-LABEL: @test_vector_usub_combine_non_splat( 650; CHECK-NEXT: [[X1:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> <i8 10, i8 20>) 651; CHECK-NEXT: [[X2:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[X1]], <2 x i8> <i8 30, i8 40>) 652; CHECK-NEXT: ret <2 x i8> [[X2]] 653; 654 %x1 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 20>) 655 %x2 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %x1, <2 x i8> <i8 30, i8 40>) 656 ret <2 x i8> %x2 657} 658 659; Can combine usubs even if they overflow. 660define i8 @test_scalar_usub_overflow(i8 %a) { 661; CHECK-LABEL: @test_scalar_usub_overflow( 662; CHECK-NEXT: ret i8 0 663; 664 %y1 = call i8 @llvm.usub.sat.i8(i8 %a, i8 100) 665 %y2 = call i8 @llvm.usub.sat.i8(i8 %y1, i8 200) 666 ret i8 %y2 667} 668 669define <2 x i8> @test_vector_usub_overflow(<2 x i8> %a) { 670; CHECK-LABEL: @test_vector_usub_overflow( 671; CHECK-NEXT: ret <2 x i8> zeroinitializer 672; 673 %y1 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 100, i8 100>) 674 %y2 = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %y1, <2 x i8> <i8 200, i8 200>) 675 ret <2 x i8> %y2 676} 677 678; Can combine ssubs if sign matches. 679define i8 @test_scalar_ssub_both_positive(i8 %a) { 680; CHECK-LABEL: @test_scalar_ssub_both_positive( 681; CHECK-NEXT: [[Z2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -30) 682; CHECK-NEXT: ret i8 [[Z2]] 683; 684 %z1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10) 685 %z2 = call i8 @llvm.ssub.sat.i8(i8 %z1, i8 20) 686 ret i8 %z2 687} 688 689define <2 x i8> @test_vector_ssub_both_positive(<2 x i8> %a) { 690; CHECK-LABEL: @test_vector_ssub_both_positive( 691; CHECK-NEXT: [[Z2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 -30)) 692; CHECK-NEXT: ret <2 x i8> [[Z2]] 693; 694 %z1 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 10, i8 10>) 695 %z2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %z1, <2 x i8> <i8 20, i8 20>) 696 ret <2 x i8> %z2 697} 698 699define i8 @test_scalar_ssub_both_negative(i8 %a) { 700; CHECK-LABEL: @test_scalar_ssub_both_negative( 701; CHECK-NEXT: [[U2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 30) 702; CHECK-NEXT: ret i8 [[U2]] 703; 704 %u1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 -10) 705 %u2 = call i8 @llvm.ssub.sat.i8(i8 %u1, i8 -20) 706 ret i8 %u2 707} 708 709define <2 x i8> @test_vector_ssub_both_negative(<2 x i8> %a) { 710; CHECK-LABEL: @test_vector_ssub_both_negative( 711; CHECK-NEXT: [[U2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 30)) 712; CHECK-NEXT: ret <2 x i8> [[U2]] 713; 714 %u1 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a, <2 x i8> <i8 -10, i8 -10>) 715 %u2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %u1, <2 x i8> <i8 -20, i8 -20>) 716 ret <2 x i8> %u2 717} 718 719; Can't combine ssubs if constants have different sign. 720define i8 @test_scalar_ssub_different_sign(i8 %a) { 721; CHECK-LABEL: @test_scalar_ssub_different_sign( 722; CHECK-NEXT: [[V1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -10) 723; CHECK-NEXT: [[V2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[V1]], i8 20) 724; CHECK-NEXT: ret i8 [[V2]] 725; 726 %v1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 10) 727 %v2 = call i8 @llvm.ssub.sat.i8(i8 %v1, i8 -20) 728 ret i8 %v2 729} 730 731; Can combine sadd and ssub with appropriate signs. 732define i8 @test_scalar_sadd_ssub(i8 %a) { 733; CHECK-LABEL: @test_scalar_sadd_ssub( 734; CHECK-NEXT: [[V2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 30) 735; CHECK-NEXT: ret i8 [[V2]] 736; 737 %v1 = call i8 @llvm.sadd.sat.i8(i8 10, i8 %a) 738 %v2 = call i8 @llvm.ssub.sat.i8(i8 %v1, i8 -20) 739 ret i8 %v2 740} 741 742define <2 x i8> @test_vector_sadd_ssub(<2 x i8> %a) { 743; CHECK-LABEL: @test_vector_sadd_ssub( 744; CHECK-NEXT: [[V2:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A:%.*]], <2 x i8> splat (i8 -30)) 745; CHECK-NEXT: ret <2 x i8> [[V2]] 746; 747 %v1 = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> <i8 -10, i8 -10>, <2 x i8> %a) 748 %v2 = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %v1, <2 x i8> <i8 20, i8 20>) 749 ret <2 x i8> %v2 750} 751 752; Can't combine ssubs if they overflow. 753define i8 @test_scalar_ssub_overflow(i8 %a) { 754; CHECK-LABEL: @test_scalar_ssub_overflow( 755; CHECK-NEXT: [[W1:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A:%.*]], i8 -100) 756; CHECK-NEXT: [[W2:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[W1]], i8 -100) 757; CHECK-NEXT: ret i8 [[W2]] 758; 759 %w1 = call i8 @llvm.ssub.sat.i8(i8 %a, i8 100) 760 %w2 = call i8 @llvm.ssub.sat.i8(i8 %w1, i8 100) 761 ret i8 %w2 762} 763 764; nneg usub neg always overflows. 765define i8 @test_scalar_usub_nneg_neg(i8 %a) { 766; CHECK-LABEL: @test_scalar_usub_nneg_neg( 767; CHECK-NEXT: ret i8 0 768; 769 %a_nneg = and i8 %a, 127 770 %r = call i8 @llvm.usub.sat.i8(i8 %a_nneg, i8 -10) 771 ret i8 %r 772} 773 774define <2 x i8> @test_vector_usub_nneg_neg(<2 x i8> %a) { 775; CHECK-LABEL: @test_vector_usub_nneg_neg( 776; CHECK-NEXT: ret <2 x i8> zeroinitializer 777; 778 %a_nneg = and <2 x i8> %a, <i8 127, i8 127> 779 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a_nneg, <2 x i8> <i8 -10, i8 -20>) 780 ret <2 x i8> %r 781} 782 783; neg usub nneg never overflows. 784define i8 @test_scalar_usub_neg_nneg(i8 %a) { 785; CHECK-LABEL: @test_scalar_usub_neg_nneg( 786; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 787; CHECK-NEXT: [[R:%.*]] = add i8 [[A_NEG]], -10 788; CHECK-NEXT: ret i8 [[R]] 789; 790 %a_neg = or i8 %a, -128 791 %r = call i8 @llvm.usub.sat.i8(i8 %a_neg, i8 10) 792 ret i8 %r 793} 794 795define <2 x i8> @test_vector_usub_neg_nneg(<2 x i8> %a) { 796; CHECK-LABEL: @test_vector_usub_neg_nneg( 797; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 798; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[A_NEG]], <i8 -10, i8 -20> 799; CHECK-NEXT: ret <2 x i8> [[R]] 800; 801 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 802 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 10, i8 20>) 803 ret <2 x i8> %r 804} 805 806; nneg usub nneg never may overflow. 807define i8 @test_scalar_usub_nneg_nneg(i8 %a) { 808; CHECK-LABEL: @test_scalar_usub_nneg_nneg( 809; CHECK-NEXT: [[A_NNEG:%.*]] = and i8 [[A:%.*]], 127 810; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A_NNEG]], i8 10) 811; CHECK-NEXT: ret i8 [[R]] 812; 813 %a_nneg = and i8 %a, 127 814 %r = call i8 @llvm.usub.sat.i8(i8 %a_nneg, i8 10) 815 ret i8 %r 816} 817 818define <2 x i8> @test_vector_usub_nneg_nneg(<2 x i8> %a) { 819; CHECK-LABEL: @test_vector_usub_nneg_nneg( 820; CHECK-NEXT: [[A_NNEG:%.*]] = and <2 x i8> [[A:%.*]], splat (i8 127) 821; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[A_NNEG]], <2 x i8> <i8 10, i8 20>) 822; CHECK-NEXT: ret <2 x i8> [[R]] 823; 824 %a_nneg = and <2 x i8> %a, <i8 127, i8 127> 825 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a_nneg, <2 x i8> <i8 10, i8 20>) 826 ret <2 x i8> %r 827} 828 829define i8 @test_scalar_usub_never_overflows(i8 %a) { 830; CHECK-LABEL: @test_scalar_usub_never_overflows( 831; CHECK-NEXT: [[A_MASKED:%.*]] = or i8 [[A:%.*]], 64 832; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_MASKED]], -10 833; CHECK-NEXT: ret i8 [[R]] 834; 835 %a_masked = or i8 %a, 64 836 %r = call i8 @llvm.usub.sat.i8(i8 %a_masked, i8 10) 837 ret i8 %r 838} 839 840define <2 x i8> @test_vector_usub_never_overflows(<2 x i8> %a) { 841; CHECK-LABEL: @test_vector_usub_never_overflows( 842; CHECK-NEXT: [[A_MASKED:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 64) 843; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[A_MASKED]], splat (i8 -10) 844; CHECK-NEXT: ret <2 x i8> [[R]] 845; 846 %a_masked = or <2 x i8> %a, <i8 64, i8 64> 847 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a_masked, <2 x i8> <i8 10, i8 10>) 848 ret <2 x i8> %r 849} 850 851define i8 @test_scalar_usub_always_overflows(i8 %a) { 852; CHECK-LABEL: @test_scalar_usub_always_overflows( 853; CHECK-NEXT: ret i8 0 854; 855 %a_masked = and i8 %a, 64 856 %r = call i8 @llvm.usub.sat.i8(i8 %a_masked, i8 100) 857 ret i8 %r 858} 859 860define <2 x i8> @test_vector_usub_always_overflows(<2 x i8> %a) { 861; CHECK-LABEL: @test_vector_usub_always_overflows( 862; CHECK-NEXT: ret <2 x i8> zeroinitializer 863; 864 %a_masked = and <2 x i8> %a, <i8 64, i8 64> 865 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a_masked, <2 x i8> <i8 100, i8 100>) 866 ret <2 x i8> %r 867} 868 869; neg ssub neg never overflows. 870define i8 @test_scalar_ssub_neg_neg(i8 %a) { 871; CHECK-LABEL: @test_scalar_ssub_neg_neg( 872; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 873; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NEG]], 10 874; CHECK-NEXT: ret i8 [[R]] 875; 876 %a_neg = or i8 %a, -128 877 %r = call i8 @llvm.ssub.sat.i8(i8 %a_neg, i8 -10) 878 ret i8 %r 879} 880 881define <2 x i8> @test_vector_ssub_neg_neg(<2 x i8> %a) { 882; CHECK-LABEL: @test_vector_ssub_neg_neg( 883; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 884; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[A_NEG]], <i8 10, i8 20> 885; CHECK-NEXT: ret <2 x i8> [[R]] 886; 887 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 888 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 -10, i8 -20>) 889 ret <2 x i8> %r 890} 891 892; nneg ssub nneg never overflows. 893define i8 @test_scalar_ssub_nneg_nneg(i8 %a) { 894; CHECK-LABEL: @test_scalar_ssub_nneg_nneg( 895; CHECK-NEXT: [[A_NNEG:%.*]] = and i8 [[A:%.*]], 127 896; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NNEG]], -10 897; CHECK-NEXT: ret i8 [[R]] 898; 899 %a_nneg = and i8 %a, 127 900 %r = call i8 @llvm.ssub.sat.i8(i8 %a_nneg, i8 10) 901 ret i8 %r 902} 903 904define <2 x i8> @test_vector_ssub_nneg_nneg(<2 x i8> %a) { 905; CHECK-LABEL: @test_vector_ssub_nneg_nneg( 906; CHECK-NEXT: [[A_NNEG:%.*]] = and <2 x i8> [[A:%.*]], splat (i8 127) 907; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[A_NNEG]], <i8 -10, i8 -20> 908; CHECK-NEXT: ret <2 x i8> [[R]] 909; 910 %a_nneg = and <2 x i8> %a, <i8 127, i8 127> 911 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a_nneg, <2 x i8> <i8 10, i8 20>) 912 ret <2 x i8> %r 913} 914 915; neg ssub nneg may overflow. 916define i8 @test_scalar_ssub_neg_nneg(i8 %a) { 917; CHECK-LABEL: @test_scalar_ssub_neg_nneg( 918; CHECK-NEXT: [[A_NEG:%.*]] = or i8 [[A:%.*]], -128 919; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[A_NEG]], i8 -10) 920; CHECK-NEXT: ret i8 [[R]] 921; 922 %a_neg = or i8 %a, -128 923 %r = call i8 @llvm.ssub.sat.i8(i8 %a_neg, i8 10) 924 ret i8 %r 925} 926 927define <2 x i8> @test_vector_ssub_neg_nneg(<2 x i8> %a) { 928; CHECK-LABEL: @test_vector_ssub_neg_nneg( 929; CHECK-NEXT: [[A_NEG:%.*]] = or <2 x i8> [[A:%.*]], splat (i8 -128) 930; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> [[A_NEG]], <2 x i8> <i8 -10, i8 -20>) 931; CHECK-NEXT: ret <2 x i8> [[R]] 932; 933 %a_neg = or <2 x i8> %a, <i8 -128, i8 -128> 934 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %a_neg, <2 x i8> <i8 10, i8 20>) 935 ret <2 x i8> %r 936} 937 938define i8 @test_scalar_ssub_always_overflows_low(i8 %a) { 939; CHECK-LABEL: @test_scalar_ssub_always_overflows_low( 940; CHECK-NEXT: ret i8 -128 941; 942 %cmp = icmp sgt i8 %a, 120 943 %max = select i1 %cmp, i8 %a, i8 120 944 %r = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %max) 945 ret i8 %r 946} 947 948define i8 @test_scalar_ssub_always_overflows_high(i8 %a) { 949; CHECK-LABEL: @test_scalar_ssub_always_overflows_high( 950; CHECK-NEXT: ret i8 127 951; 952 %cmp = icmp slt i8 %a, -120 953 %min = select i1 %cmp, i8 %a, i8 -120 954 %r = call i8 @llvm.ssub.sat.i8(i8 10, i8 %min) 955 ret i8 %r 956} 957 958define i8 @test_scalar_usub_add_nuw_no_ov(i8 %a) { 959; CHECK-LABEL: @test_scalar_usub_add_nuw_no_ov( 960; CHECK-NEXT: [[R:%.*]] = add i8 [[A:%.*]], 1 961; CHECK-NEXT: ret i8 [[R]] 962; 963 %b = add nuw i8 %a, 10 964 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9) 965 ret i8 %r 966} 967 968define i8 @test_scalar_usub_add_nuw_nsw_no_ov(i8 %a) { 969; CHECK-LABEL: @test_scalar_usub_add_nuw_nsw_no_ov( 970; CHECK-NEXT: [[R:%.*]] = add i8 [[A:%.*]], 1 971; CHECK-NEXT: ret i8 [[R]] 972; 973 %b = add nuw nsw i8 %a, 10 974 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9) 975 ret i8 %r 976} 977 978define i8 @test_scalar_usub_add_nuw_eq(i8 %a) { 979; CHECK-LABEL: @test_scalar_usub_add_nuw_eq( 980; CHECK-NEXT: ret i8 [[A:%.*]] 981; 982 %b = add nuw i8 %a, 10 983 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10) 984 ret i8 %r 985} 986 987define i8 @test_scalar_usub_add_nuw_may_ov(i8 %a) { 988; CHECK-LABEL: @test_scalar_usub_add_nuw_may_ov( 989; CHECK-NEXT: [[B:%.*]] = add nuw i8 [[A:%.*]], 10 990; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 11) 991; CHECK-NEXT: ret i8 [[R]] 992; 993 %b = add nuw i8 %a, 10 994 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 11) 995 ret i8 %r 996} 997 998define i8 @test_scalar_usub_urem_must_ov(i8 %a) { 999; CHECK-LABEL: @test_scalar_usub_urem_must_ov( 1000; CHECK-NEXT: ret i8 0 1001; 1002 %b = urem i8 %a, 10 1003 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10) 1004 ret i8 %r 1005} 1006 1007; Like the previous case, the result is always zero here. However, as there's 1008; no actual overflow, we won't know about it. 1009define i8 @test_scalar_usub_urem_must_zero(i8 %a) { 1010; CHECK-LABEL: @test_scalar_usub_urem_must_zero( 1011; CHECK-NEXT: [[B:%.*]] = urem i8 [[A:%.*]], 10 1012; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B]], i8 9) 1013; CHECK-NEXT: ret i8 [[R]] 1014; 1015 %b = urem i8 %a, 10 1016 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9) 1017 ret i8 %r 1018} 1019 1020; We have a constant range for the LHS, but only known bits for the RHS 1021define i8 @test_scalar_usub_add_nuw_known_bits(i8 %a, i8 %b) { 1022; CHECK-LABEL: @test_scalar_usub_add_nuw_known_bits( 1023; CHECK-NEXT: [[AA:%.*]] = add nuw i8 [[A:%.*]], 10 1024; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 7 1025; CHECK-NEXT: [[R:%.*]] = sub nuw i8 [[AA]], [[BB]] 1026; CHECK-NEXT: ret i8 [[R]] 1027; 1028 %aa = add nuw i8 %a, 10 1029 %bb = and i8 %b, 7 1030 %r = call i8 @llvm.usub.sat.i8(i8 %aa, i8 %bb) 1031 ret i8 %r 1032} 1033 1034define i8 @test_scalar_usub_add_nuw_inferred(i8 %a) { 1035; CHECK-LABEL: @test_scalar_usub_add_nuw_inferred( 1036; CHECK-NEXT: [[B:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10) 1037; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[B]], 9 1038; CHECK-NEXT: ret i8 [[R]] 1039; 1040 %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10) 1041 %r = add i8 %b, 9 1042 ret i8 %r 1043} 1044 1045define <2 x i8> @test_vector_usub_add_nuw_no_ov(<2 x i8> %a) { 1046; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov( 1047; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[A:%.*]], splat (i8 1) 1048; CHECK-NEXT: ret <2 x i8> [[R]] 1049; 1050 %b = add nuw <2 x i8> %a, <i8 10, i8 10> 1051 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %b, <2 x i8> <i8 9, i8 9>) 1052 ret <2 x i8> %r 1053} 1054 1055define <2 x i8> @test_vector_usub_add_nuw_no_ov_nonsplat1(<2 x i8> %a) { 1056; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov_nonsplat1( 1057; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[A:%.*]], <i8 0, i8 1> 1058; CHECK-NEXT: ret <2 x i8> [[R]] 1059; 1060 %b = add nuw <2 x i8> %a, <i8 10, i8 10> 1061 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %b, <2 x i8> <i8 10, i8 9>) 1062 ret <2 x i8> %r 1063} 1064 1065define <3 x i8> @test_vector_usub_add_nuw_no_ov_nonsplat1_poison(<3 x i8> %a) { 1066; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov_nonsplat1_poison( 1067; CHECK-NEXT: [[R:%.*]] = add <3 x i8> [[A:%.*]], <i8 0, i8 1, i8 poison> 1068; CHECK-NEXT: ret <3 x i8> [[R]] 1069; 1070 %b = add nuw <3 x i8> %a, <i8 10, i8 10, i8 10> 1071 %r = call <3 x i8> @llvm.usub.sat.v3i8(<3 x i8> %b, <3 x i8> <i8 10, i8 9, i8 poison>) 1072 ret <3 x i8> %r 1073} 1074 1075; Can be optimized if the add nuw RHS constant range handles non-splat vectors. 1076define <2 x i8> @test_vector_usub_add_nuw_no_ov_nonsplat2(<2 x i8> %a) { 1077; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov_nonsplat2( 1078; CHECK-NEXT: [[B:%.*]] = add nuw <2 x i8> [[A:%.*]], <i8 10, i8 9> 1079; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> splat (i8 9)) 1080; CHECK-NEXT: ret <2 x i8> [[R]] 1081; 1082 %b = add nuw <2 x i8> %a, <i8 10, i8 9> 1083 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %b, <2 x i8> <i8 9, i8 9>) 1084 ret <2 x i8> %r 1085} 1086 1087; Can be optimized if constant range is tracked per-element. 1088define <2 x i8> @test_vector_usub_add_nuw_no_ov_nonsplat3(<2 x i8> %a) { 1089; CHECK-LABEL: @test_vector_usub_add_nuw_no_ov_nonsplat3( 1090; CHECK-NEXT: [[B:%.*]] = add nuw <2 x i8> [[A:%.*]], <i8 10, i8 9> 1091; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> [[B]], <2 x i8> <i8 10, i8 9>) 1092; CHECK-NEXT: ret <2 x i8> [[R]] 1093; 1094 %b = add nuw <2 x i8> %a, <i8 10, i8 9> 1095 %r = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %b, <2 x i8> <i8 10, i8 9>) 1096 ret <2 x i8> %r 1097} 1098 1099define i8 @test_scalar_ssub_add_nsw_no_ov(i8 %a, i8 %b) { 1100; CHECK-LABEL: @test_scalar_ssub_add_nsw_no_ov( 1101; CHECK-NEXT: [[AA:%.*]] = add nsw i8 [[A:%.*]], 7 1102; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 7 1103; CHECK-NEXT: [[R:%.*]] = sub nsw i8 [[AA]], [[BB]] 1104; CHECK-NEXT: ret i8 [[R]] 1105; 1106 %aa = add nsw i8 %a, 7 1107 %bb = and i8 %b, 7 1108 %r = call i8 @llvm.ssub.sat.i8(i8 %aa, i8 %bb) 1109 ret i8 %r 1110} 1111 1112define i8 @test_scalar_ssub_add_nsw_may_ov(i8 %a, i8 %b) { 1113; CHECK-LABEL: @test_scalar_ssub_add_nsw_may_ov( 1114; CHECK-NEXT: [[AA:%.*]] = add nsw i8 [[A:%.*]], 6 1115; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 7 1116; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[AA]], i8 [[BB]]) 1117; CHECK-NEXT: ret i8 [[R]] 1118; 1119 %aa = add nsw i8 %a, 6 1120 %bb = and i8 %b, 7 1121 %r = call i8 @llvm.ssub.sat.i8(i8 %aa, i8 %bb) 1122 ret i8 %r 1123} 1124 1125define <2 x i8> @test_vector_ssub_add_nsw_no_ov_splat(<2 x i8> %a, <2 x i8> %b) { 1126; CHECK-LABEL: @test_vector_ssub_add_nsw_no_ov_splat( 1127; CHECK-NEXT: [[AA:%.*]] = add nsw <2 x i8> [[A:%.*]], splat (i8 7) 1128; CHECK-NEXT: [[BB:%.*]] = and <2 x i8> [[B:%.*]], splat (i8 7) 1129; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> [[AA]], [[BB]] 1130; CHECK-NEXT: ret <2 x i8> [[R]] 1131; 1132 %aa = add nsw <2 x i8> %a, <i8 7, i8 7> 1133 %bb = and <2 x i8> %b, <i8 7, i8 7> 1134 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %aa, <2 x i8> %bb) 1135 ret <2 x i8> %r 1136} 1137 1138define <2 x i8> @test_vector_ssub_add_nsw_no_ov_nonsplat1(<2 x i8> %a, <2 x i8> %b) { 1139; CHECK-LABEL: @test_vector_ssub_add_nsw_no_ov_nonsplat1( 1140; CHECK-NEXT: [[AA:%.*]] = add nsw <2 x i8> [[A:%.*]], splat (i8 7) 1141; CHECK-NEXT: [[BB:%.*]] = and <2 x i8> [[B:%.*]], <i8 7, i8 6> 1142; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> [[AA]], [[BB]] 1143; CHECK-NEXT: ret <2 x i8> [[R]] 1144; 1145 %aa = add nsw <2 x i8> %a, <i8 7, i8 7> 1146 %bb = and <2 x i8> %b, <i8 7, i8 6> 1147 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %aa, <2 x i8> %bb) 1148 ret <2 x i8> %r 1149} 1150 1151define <2 x i8> @test_vector_ssub_add_nsw_no_ov_nonsplat2(<2 x i8> %a, <2 x i8> %b) { 1152; CHECK-LABEL: @test_vector_ssub_add_nsw_no_ov_nonsplat2( 1153; CHECK-NEXT: [[AA:%.*]] = add nsw <2 x i8> [[A:%.*]], <i8 7, i8 8> 1154; CHECK-NEXT: [[BB:%.*]] = and <2 x i8> [[B:%.*]], splat (i8 7) 1155; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[AA]], <2 x i8> [[BB]]) 1156; CHECK-NEXT: ret <2 x i8> [[R]] 1157; 1158 %aa = add nsw <2 x i8> %a, <i8 7, i8 8> 1159 %bb = and <2 x i8> %b, <i8 7, i8 7> 1160 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %aa, <2 x i8> %bb) 1161 ret <2 x i8> %r 1162} 1163 1164define <2 x i8> @test_vector_ssub_add_nsw_no_ov_nonsplat3(<2 x i8> %a, <2 x i8> %b) { 1165; CHECK-LABEL: @test_vector_ssub_add_nsw_no_ov_nonsplat3( 1166; CHECK-NEXT: [[AA:%.*]] = add nsw <2 x i8> [[A:%.*]], <i8 7, i8 6> 1167; CHECK-NEXT: [[BB:%.*]] = and <2 x i8> [[B:%.*]], <i8 7, i8 6> 1168; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> [[AA]], <2 x i8> [[BB]]) 1169; CHECK-NEXT: ret <2 x i8> [[R]] 1170; 1171 %aa = add nsw <2 x i8> %a, <i8 7, i8 6> 1172 %bb = and <2 x i8> %b, <i8 7, i8 6> 1173 %r = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %aa, <2 x i8> %bb) 1174 ret <2 x i8> %r 1175} 1176 1177define i8 @test_scalar_usub_add(i8 %a, i8 %b) { 1178; CHECK-LABEL: @test_scalar_usub_add( 1179; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1180; CHECK-NEXT: ret i8 [[RES]] 1181; 1182 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1183 %res = add i8 %sat, %b 1184 ret i8 %res 1185} 1186 1187define i8 @test_scalar_usub_add_extra_use(i8 %a, i8 %b, ptr %p) { 1188; CHECK-LABEL: @test_scalar_usub_add_extra_use( 1189; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1190; CHECK-NEXT: store i8 [[SAT]], ptr [[P:%.*]], align 1 1191; CHECK-NEXT: [[RES:%.*]] = add i8 [[SAT]], [[B]] 1192; CHECK-NEXT: ret i8 [[RES]] 1193; 1194 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1195 store i8 %sat, ptr %p 1196 %res = add i8 %sat, %b 1197 ret i8 %res 1198} 1199 1200define i8 @test_scalar_usub_add_commuted(i8 %a, i8 %b) { 1201; CHECK-LABEL: @test_scalar_usub_add_commuted( 1202; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1203; CHECK-NEXT: ret i8 [[RES]] 1204; 1205 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1206 %res = add i8 %b, %sat 1207 ret i8 %res 1208} 1209 1210define i8 @test_scalar_usub_add_commuted_wrong(i8 %a, i8 %b) { 1211; CHECK-LABEL: @test_scalar_usub_add_commuted_wrong( 1212; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]]) 1213; CHECK-NEXT: [[RES:%.*]] = add i8 [[SAT]], [[B]] 1214; CHECK-NEXT: ret i8 [[RES]] 1215; 1216 %sat = call i8 @llvm.usub.sat.i8(i8 %b, i8 %a) 1217 %res = add i8 %sat, %b 1218 ret i8 %res 1219} 1220 1221define i8 @test_scalar_usub_add_const(i8 %a) { 1222; CHECK-LABEL: @test_scalar_usub_add_const( 1223; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 42) 1224; CHECK-NEXT: ret i8 [[RES]] 1225; 1226 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 42) 1227 %res = add i8 %sat, 42 1228 ret i8 %res 1229} 1230 1231define i8 @test_scalar_usub_sub(i8 %a, i8 %b) { 1232; CHECK-LABEL: @test_scalar_usub_sub( 1233; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.umin.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1234; CHECK-NEXT: ret i8 [[RES]] 1235; 1236 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1237 %res = sub i8 %a, %sat 1238 ret i8 %res 1239} 1240 1241define i8 @test_scalar_usub_sub_extra_use(i8 %a, i8 %b, ptr %p) { 1242; CHECK-LABEL: @test_scalar_usub_sub_extra_use( 1243; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1244; CHECK-NEXT: store i8 [[SAT]], ptr [[P:%.*]], align 1 1245; CHECK-NEXT: [[RES:%.*]] = sub i8 [[A]], [[SAT]] 1246; CHECK-NEXT: ret i8 [[RES]] 1247; 1248 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1249 store i8 %sat, ptr %p 1250 %res = sub i8 %a, %sat 1251 ret i8 %res 1252} 1253 1254define <2 x i8> @test_vector_usub_sub(<2 x i8> %a, <2 x i8> %b) { 1255; CHECK-LABEL: @test_vector_usub_sub( 1256; CHECK-NEXT: [[RES:%.*]] = call <2 x i8> @llvm.umin.v2i8(<2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) 1257; CHECK-NEXT: ret <2 x i8> [[RES]] 1258; 1259 %sat = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %a, <2 x i8> %b) 1260 %res = sub <2 x i8> %a, %sat 1261 ret <2 x i8> %res 1262} 1263 1264define i8 @test_scalar_usub_sub_wrong(i8 %a, i8 %b) { 1265; CHECK-LABEL: @test_scalar_usub_sub_wrong( 1266; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1267; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[SAT]] 1268; CHECK-NEXT: ret i8 [[RES]] 1269; 1270 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1271 %res = sub i8 %b, %sat 1272 ret i8 %res 1273} 1274 1275define i8 @test_scalar_usub_sub_wrong2(i8 %a, i8 %b) { 1276; CHECK-LABEL: @test_scalar_usub_sub_wrong2( 1277; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1278; CHECK-NEXT: [[RES:%.*]] = sub i8 [[SAT]], [[B]] 1279; CHECK-NEXT: ret i8 [[RES]] 1280; 1281 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1282 %res = sub i8 %sat, %b 1283 ret i8 %res 1284} 1285 1286define i8 @test_scalar_uadd_sub(i8 %a, i8 %b) { 1287; CHECK-LABEL: @test_scalar_uadd_sub( 1288; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1289; CHECK-NEXT: [[RES:%.*]] = sub i8 [[SAT]], [[B]] 1290; CHECK-NEXT: ret i8 [[RES]] 1291; 1292 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) 1293 %res = sub i8 %sat, %b 1294 ret i8 %res 1295} 1296 1297define i8 @test_scalar_uadd_sub_extra_use(i8 %a, i8 %b, ptr %p) { 1298; CHECK-LABEL: @test_scalar_uadd_sub_extra_use( 1299; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1300; CHECK-NEXT: store i8 [[SAT]], ptr [[P:%.*]], align 1 1301; CHECK-NEXT: [[RES:%.*]] = sub i8 [[SAT]], [[B]] 1302; CHECK-NEXT: ret i8 [[RES]] 1303; 1304 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) 1305 store i8 %sat, ptr %p 1306 %res = sub i8 %sat, %b 1307 ret i8 %res 1308} 1309 1310define i8 @test_scalar_uadd_sub_commuted(i8 %a, i8 %b) { 1311; CHECK-LABEL: @test_scalar_uadd_sub_commuted( 1312; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[B:%.*]], i8 [[A:%.*]]) 1313; CHECK-NEXT: [[RES:%.*]] = sub i8 [[SAT]], [[B]] 1314; CHECK-NEXT: ret i8 [[RES]] 1315; 1316 %sat = call i8 @llvm.uadd.sat.i8(i8 %b, i8 %a) 1317 %res = sub i8 %sat, %b 1318 ret i8 %res 1319} 1320 1321define i8 @test_scalar_uadd_sub_commuted_wrong(i8 %a, i8 %b) { 1322; CHECK-LABEL: @test_scalar_uadd_sub_commuted_wrong( 1323; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 [[B:%.*]]) 1324; CHECK-NEXT: [[RES:%.*]] = sub i8 [[B]], [[SAT]] 1325; CHECK-NEXT: ret i8 [[RES]] 1326; 1327 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) 1328 %res = sub i8 %b, %sat 1329 ret i8 %res 1330} 1331 1332define i8 @test_scalar_uadd_sub_const(i8 %a) { 1333; CHECK-LABEL: @test_scalar_uadd_sub_const( 1334; CHECK-NEXT: [[SAT:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[A:%.*]], i8 42) 1335; CHECK-NEXT: [[RES:%.*]] = add i8 [[SAT]], -42 1336; CHECK-NEXT: ret i8 [[RES]] 1337; 1338 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 42) 1339 %res = sub i8 %sat, 42 1340 ret i8 %res 1341} 1342 1343define i1 @scalar_uadd_eq_zero(i8 %a, i8 %b) { 1344; CHECK-LABEL: @scalar_uadd_eq_zero( 1345; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], [[B:%.*]] 1346; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1]], 0 1347; CHECK-NEXT: ret i1 [[CMP]] 1348; 1349 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) 1350 %cmp = icmp eq i8 %sat, 0 1351 ret i1 %cmp 1352} 1353 1354define i1 @scalar_uadd_ne_zero(i8 %a, i8 %b) { 1355; CHECK-LABEL: @scalar_uadd_ne_zero( 1356; CHECK-NEXT: [[TMP1:%.*]] = or i8 [[A:%.*]], [[B:%.*]] 1357; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP1]], 0 1358; CHECK-NEXT: ret i1 [[CMP]] 1359; 1360 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b) 1361 %cmp = icmp ne i8 %sat, 0 1362 ret i1 %cmp 1363} 1364 1365define i1 @scalar_usub_eq_zero(i8 %a, i8 %b) { 1366; CHECK-LABEL: @scalar_usub_eq_zero( 1367; CHECK-NEXT: [[CMP:%.*]] = icmp ule i8 [[A:%.*]], [[B:%.*]] 1368; CHECK-NEXT: ret i1 [[CMP]] 1369; 1370 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1371 %cmp = icmp eq i8 %sat, 0 1372 ret i1 %cmp 1373} 1374 1375define i1 @scalar_usub_ne_zero(i8 %a, i8 %b) { 1376; CHECK-LABEL: @scalar_usub_ne_zero( 1377; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i8 [[A:%.*]], [[B:%.*]] 1378; CHECK-NEXT: ret i1 [[CMP]] 1379; 1380 %sat = call i8 @llvm.usub.sat.i8(i8 %a, i8 %b) 1381 %cmp = icmp ne i8 %sat, 0 1382 ret i1 %cmp 1383} 1384 1385; Raw IR tests 1386 1387define i32 @uadd_sat(i32 %x, i32 %y) { 1388; CHECK-LABEL: @uadd_sat( 1389; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) 1390; CHECK-NEXT: ret i32 [[R]] 1391; 1392 %notx = xor i32 %x, -1 1393 %a = add i32 %y, %x 1394 %c = icmp ult i32 %notx, %y 1395 %r = select i1 %c, i32 -1, i32 %a 1396 ret i32 %r 1397} 1398 1399define i32 @uadd_sat_flipped(i32 %x) { 1400; CHECK-LABEL: @uadd_sat_flipped( 1401; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 9) 1402; CHECK-NEXT: ret i32 [[COND]] 1403; 1404 %cmp = icmp ugt i32 %x, -11 1405 %add = add i32 %x, 9 1406 %cond = select i1 %cmp, i32 -1, i32 %add 1407 ret i32 %cond 1408} 1409 1410define i32 @uadd_sat_flipped2(i32 %x) { 1411; CHECK-LABEL: @uadd_sat_flipped2( 1412; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 9) 1413; CHECK-NEXT: ret i32 [[COND]] 1414; 1415 %cmp = icmp ugt i32 %x, -10 1416 %add = add i32 %x, 9 1417 %cond = select i1 %cmp, i32 -1, i32 %add 1418 ret i32 %cond 1419} 1420 1421define i32 @uadd_sat_flipped3(i32 %x) { 1422; CHECK-LABEL: @uadd_sat_flipped3( 1423; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -8 1424; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[X]], 9 1425; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1426; CHECK-NEXT: ret i32 [[COND]] 1427; 1428 %cmp = icmp ugt i32 %x, -8 1429 %add = add nuw i32 %x, 9 1430 %cond = select i1 %cmp, i32 -1, i32 %add 1431 ret i32 %cond 1432} 1433 1434; Negative Test 1435 1436define i32 @uadd_sat_flipped3_neg_no_nuw(i32 %x) { 1437; CHECK-LABEL: @uadd_sat_flipped3_neg_no_nuw( 1438; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -8 1439; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1440; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1441; CHECK-NEXT: ret i32 [[COND]] 1442; 1443 %cmp = icmp ugt i32 %x, -8 1444 %add = add i32 %x, 9 1445 %cond = select i1 %cmp, i32 -1, i32 %add 1446 ret i32 %cond 1447} 1448 1449define i32 @uadd_sat_negative_one(i32 %x) { 1450; CHECK-LABEL: @uadd_sat_negative_one( 1451; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 1) 1452; CHECK-NEXT: ret i32 [[COND]] 1453; 1454 %cmp = icmp eq i32 %x, -1 1455 %add = add i32 %x, 1 1456 %cond = select i1 %cmp, i32 -1, i32 %add 1457 ret i32 %cond 1458} 1459 1460define <2 x i8> @uadd_sat_flipped4_vector(<2 x i8> %x) { 1461; CHECK-LABEL: @uadd_sat_flipped4_vector( 1462; CHECK-NEXT: [[COND:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 9)) 1463; CHECK-NEXT: ret <2 x i8> [[COND]] 1464; 1465 %cmp = icmp ult <2 x i8> %x, <i8 -10, i8 -10> 1466 %add = add <2 x i8> %x, <i8 9, i8 9> 1467 %cond = select <2 x i1> %cmp, <2 x i8> %add, <2 x i8> <i8 -1, i8 -1> 1468 ret <2 x i8> %cond 1469} 1470 1471define <2 x i8> @uadd_sat_flipped4_poison_vector(<2 x i8> %x) { 1472; CHECK-LABEL: @uadd_sat_flipped4_poison_vector( 1473; CHECK-NEXT: [[COND:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 9)) 1474; CHECK-NEXT: ret <2 x i8> [[COND]] 1475; 1476 %cmp = icmp ult <2 x i8> %x, <i8 -10, i8 poison> 1477 %add = add <2 x i8> %x, <i8 9, i8 9> 1478 %cond = select <2 x i1> %cmp, <2 x i8> %add,<2 x i8> <i8 -1, i8 -1> 1479 ret <2 x i8> %cond 1480} 1481 1482define <2 x i8> @uadd_sat_flipped4_poison_vector_compare(<2 x i8> %x) { 1483; CHECK-LABEL: @uadd_sat_flipped4_poison_vector_compare( 1484; CHECK-NEXT: [[COND:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> splat (i8 9)) 1485; CHECK-NEXT: ret <2 x i8> [[COND]] 1486; 1487 %cmp = icmp ult <2 x i8> %x, <i8 -10, i8 poison> 1488 %add = add <2 x i8> %x, <i8 9, i8 poison> 1489 %cond = select <2 x i1> %cmp, <2 x i8> %add,<2 x i8> <i8 -1, i8 -1> 1490 ret <2 x i8> %cond 1491} 1492 1493define <2 x i8> @uadd_sat_flipped4_poison_vector_compare2(<2 x i8> %x) { 1494; CHECK-LABEL: @uadd_sat_flipped4_poison_vector_compare2( 1495; CHECK-NEXT: ret <2 x i8> splat (i8 -1) 1496; 1497 %cmp = icmp ult <2 x i8> %x, <i8 -10, i8 poison> 1498 %add = add <2 x i8> %x, <i8 poison, i8 poison> 1499 %cond = select <2 x i1> %cmp, <2 x i8> %add,<2 x i8> <i8 -1, i8 -1> 1500 ret <2 x i8> %cond 1501} 1502 1503; Negative test: 1504 1505define i32 @uadd_sat_flipped_too_big(i32 %x) { 1506; CHECK-LABEL: @uadd_sat_flipped_too_big( 1507; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -8 1508; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1509; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -1 1510; CHECK-NEXT: ret i32 [[COND]] 1511; 1512 %cmp = icmp ult i32 %x, -8 1513 %add = add i32 %x, 9 1514 %cond = select i1 %cmp, i32 %add, i32 -1 1515 ret i32 %cond 1516} 1517 1518; Negative test: 1519 1520define i32 @uadd_sat_flipped_wrong_bounds(i32 %x) { 1521; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds( 1522; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -13 1523; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1524; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1525; CHECK-NEXT: ret i32 [[COND]] 1526; 1527 %cmp = icmp uge i32 %x, -12 1528 %add = add i32 %x, 9 1529 %cond = select i1 %cmp, i32 -1, i32 %add 1530 ret i32 %cond 1531} 1532 1533; Negative test: 1534 1535define i32 @uadd_sat_flipped_wrong_bounds2(i32 %x) { 1536; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds2( 1537; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -12 1538; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1539; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1540; CHECK-NEXT: ret i32 [[COND]] 1541; 1542 %cmp = icmp ugt i32 %x, -12 1543 %add = add i32 %x, 9 1544 %cond = select i1 %cmp, i32 -1, i32 %add 1545 ret i32 %cond 1546} 1547 1548; Negative test: 1549 1550define i32 @uadd_sat_flipped_wrong_bounds3(i32 %x) { 1551; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds3( 1552; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -12 1553; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1554; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1555; CHECK-NEXT: ret i32 [[COND]] 1556; 1557 %cmp = icmp ugt i32 %x, -12 1558 %add = add i32 %x, 9 1559 %cond = select i1 %cmp, i32 -1, i32 %add 1560 ret i32 %cond 1561} 1562 1563; Negative test: 1564 1565define i32 @uadd_sat_flipped_wrong_bounds4(i32 %x) { 1566; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds4( 1567; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -9 1568; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1569; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]] 1570; CHECK-NEXT: ret i32 [[COND]] 1571; 1572 %cmp = icmp uge i32 %x, -8 1573 %add = add i32 %x, 9 1574 %cond = select i1 %cmp, i32 -1, i32 %add 1575 ret i32 %cond 1576} 1577 1578; Negative test: 1579 1580define i32 @uadd_sat_flipped_wrong_bounds5(i32 %x) { 1581; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds5( 1582; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -8 1583; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1584; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -1 1585; CHECK-NEXT: ret i32 [[COND]] 1586; 1587 %cmp = icmp ult i32 %x, -8 1588 %add = add i32 %x, 9 1589 %cond = select i1 %cmp, i32 %add, i32 -1 1590 ret i32 %cond 1591} 1592 1593; Negative test: 1594 1595define i32 @uadd_sat_flipped_wrong_bounds6(i32 %x) { 1596; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds6( 1597; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -11 1598; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1599; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -1 1600; CHECK-NEXT: ret i32 [[COND]] 1601; 1602 %cmp = icmp ule i32 %x, -12 1603 %add = add i32 %x, 9 1604 %cond = select i1 %cmp, i32 %add, i32 -1 1605 ret i32 %cond 1606} 1607 1608; Negative test: 1609 1610define i32 @uadd_sat_flipped_wrong_bounds7(i32 %x) { 1611; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds7( 1612; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -11 1613; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1614; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -1 1615; CHECK-NEXT: ret i32 [[COND]] 1616; 1617 %cmp = icmp ule i32 %x, -12 1618 %add = add i32 %x, 9 1619 %cond = select i1 %cmp, i32 %add, i32 -1 1620 ret i32 %cond 1621} 1622 1623; Negative test: 1624 1625define i32 @uadd_sat_flipped_wrong_bounds8(i32 %x) { 1626; CHECK-LABEL: @uadd_sat_flipped_wrong_bounds8( 1627; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], -12 1628; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 9 1629; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -1 1630; CHECK-NEXT: ret i32 [[COND]] 1631; 1632 %cmp = icmp ult i32 %x, -12 1633 %add = add i32 %x, 9 1634 %cond = select i1 %cmp, i32 %add, i32 -1 1635 ret i32 %cond 1636} 1637 1638define i32 @uadd_sat_nonstrict(i32 %x, i32 %y) { 1639; CHECK-LABEL: @uadd_sat_nonstrict( 1640; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) 1641; CHECK-NEXT: ret i32 [[R]] 1642; 1643 %notx = xor i32 %x, -1 1644 %a = add i32 %y, %x 1645 %c = icmp ule i32 %notx, %y 1646 %r = select i1 %c, i32 -1, i32 %a 1647 ret i32 %r 1648} 1649 1650define i32 @uadd_sat_commute_add(i32 %xp, i32 %y) { 1651; CHECK-LABEL: @uadd_sat_commute_add( 1652; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[XP:%.*]] 1653; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X]], i32 [[Y:%.*]]) 1654; CHECK-NEXT: ret i32 [[R]] 1655; 1656 %x = urem i32 42, %xp ; thwart complexity-based-canonicalization 1657 %notx = xor i32 %x, -1 1658 %a = add i32 %x, %y 1659 %c = icmp ult i32 %notx, %y 1660 %r = select i1 %c, i32 -1, i32 %a 1661 ret i32 %r 1662} 1663 1664define i32 @uadd_sat_ugt(i32 %x, i32 %yp) { 1665; CHECK-LABEL: @uadd_sat_ugt( 1666; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 2442 1667; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 1668; CHECK-NEXT: ret i32 [[R]] 1669; 1670 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization 1671 %notx = xor i32 %x, -1 1672 %a = add i32 %y, %x 1673 %c = icmp ugt i32 %y, %notx 1674 %r = select i1 %c, i32 -1, i32 %a 1675 ret i32 %r 1676} 1677define i32 @uadd_sat_uge(i32 %x, i32 %yp) { 1678; CHECK-LABEL: @uadd_sat_uge( 1679; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 2442 1680; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 1681; CHECK-NEXT: ret i32 [[R]] 1682; 1683 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization 1684 %notx = xor i32 %x, -1 1685 %a = add i32 %y, %x 1686 %c = icmp uge i32 %y, %notx 1687 %r = select i1 %c, i32 -1, i32 %a 1688 ret i32 %r 1689} 1690 1691define <2 x i32> @uadd_sat_ugt_commute_add(<2 x i32> %xp, <2 x i32> %yp) { 1692; CHECK-LABEL: @uadd_sat_ugt_commute_add( 1693; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i32> [[YP:%.*]], <i32 2442, i32 4242> 1694; CHECK-NEXT: [[X:%.*]] = srem <2 x i32> <i32 42, i32 43>, [[XP:%.*]] 1695; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]]) 1696; CHECK-NEXT: ret <2 x i32> [[R]] 1697; 1698 %y = sdiv <2 x i32> %yp, <i32 2442, i32 4242> ; thwart complexity-based-canonicalization 1699 %x = srem <2 x i32> <i32 42, i32 43>, %xp ; thwart complexity-based-canonicalization 1700 %notx = xor <2 x i32> %x, <i32 -1, i32 -1> 1701 %a = add <2 x i32> %x, %y 1702 %c = icmp ugt <2 x i32> %y, %notx 1703 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a 1704 ret <2 x i32> %r 1705} 1706 1707define i32 @uadd_sat_commute_select(i32 %x, i32 %yp) { 1708; CHECK-LABEL: @uadd_sat_commute_select( 1709; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 2442 1710; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 1711; CHECK-NEXT: ret i32 [[R]] 1712; 1713 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization 1714 %notx = xor i32 %x, -1 1715 %a = add i32 %y, %x 1716 %c = icmp ult i32 %y, %notx 1717 %r = select i1 %c, i32 %a, i32 -1 1718 ret i32 %r 1719} 1720 1721define i32 @uadd_sat_commute_select_nonstrict(i32 %x, i32 %yp) { 1722; CHECK-LABEL: @uadd_sat_commute_select_nonstrict( 1723; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 2442 1724; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 1725; CHECK-NEXT: ret i32 [[R]] 1726; 1727 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization 1728 %notx = xor i32 %x, -1 1729 %a = add i32 %y, %x 1730 %c = icmp ule i32 %y, %notx 1731 %r = select i1 %c, i32 %a, i32 -1 1732 ret i32 %r 1733} 1734 1735define i32 @uadd_sat_commute_select_commute_add(i32 %xp, i32 %yp) { 1736; CHECK-LABEL: @uadd_sat_commute_select_commute_add( 1737; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[XP:%.*]] 1738; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 2442 1739; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X]], i32 [[Y]]) 1740; CHECK-NEXT: ret i32 [[R]] 1741; 1742 %x = urem i32 42, %xp ; thwart complexity-based-canonicalization 1743 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization 1744 %notx = xor i32 %x, -1 1745 %a = add i32 %x, %y 1746 %c = icmp ult i32 %y, %notx 1747 %r = select i1 %c, i32 %a, i32 -1 1748 ret i32 %r 1749} 1750 1751define <2 x i32> @uadd_sat_commute_select_ugt(<2 x i32> %x, <2 x i32> %y) { 1752; CHECK-LABEL: @uadd_sat_commute_select_ugt( 1753; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) 1754; CHECK-NEXT: ret <2 x i32> [[R]] 1755; 1756 %notx = xor <2 x i32> %x, <i32 -1, i32 -1> 1757 %a = add <2 x i32> %y, %x 1758 %c = icmp ugt <2 x i32> %notx, %y 1759 %r = select <2 x i1> %c, <2 x i32> %a, <2 x i32> <i32 -1, i32 -1> 1760 ret <2 x i32> %r 1761} 1762 1763define i32 @uadd_sat_commute_select_ugt_commute_add(i32 %xp, i32 %y) { 1764; CHECK-LABEL: @uadd_sat_commute_select_ugt_commute_add( 1765; CHECK-NEXT: [[X:%.*]] = srem i32 42, [[XP:%.*]] 1766; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X]], i32 [[Y:%.*]]) 1767; CHECK-NEXT: ret i32 [[R]] 1768; 1769 %x = srem i32 42, %xp ; thwart complexity-based-canonicalization 1770 %notx = xor i32 %x, -1 1771 %a = add i32 %x, %y 1772 %c = icmp ugt i32 %notx, %y 1773 %r = select i1 %c, i32 %a, i32 -1 1774 ret i32 %r 1775} 1776 1777; Negative test - make sure we have a -1 in the select. 1778 1779define i32 @not_uadd_sat(i32 %x, i32 %y) { 1780; CHECK-LABEL: @not_uadd_sat( 1781; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], -2 1782; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[X]], 1 1783; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 [[Y:%.*]] 1784; CHECK-NEXT: ret i32 [[R]] 1785; 1786 %a = add i32 %x, -2 1787 %c = icmp ugt i32 %x, 1 1788 %r = select i1 %c, i32 %a, i32 %y 1789 ret i32 %r 1790} 1791 1792; Negative test - make sure the predicate is 'ult'. 1793 1794define i32 @not_uadd_sat2(i32 %x, i32 %y) { 1795; CHECK-LABEL: @not_uadd_sat2( 1796; CHECK-NEXT: [[X:%.*]] = call i32 @llvm.umax.i32(i32 [[X1:%.*]], i32 1) 1797; CHECK-NEXT: [[A:%.*]] = add i32 [[X]], -2 1798; CHECK-NEXT: ret i32 [[A]] 1799; 1800 %a = add i32 %x, -2 1801 %c = icmp ugt i32 %x, 1 1802 %r = select i1 %c, i32 %a, i32 -1 1803 ret i32 %r 1804} 1805 1806; The add may include a 'not' op rather than the cmp. 1807 1808define i32 @uadd_sat_not(i32 %x, i32 %y) { 1809; CHECK-LABEL: @uadd_sat_not( 1810; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1811; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1812; CHECK-NEXT: ret i32 [[R]] 1813; 1814 %notx = xor i32 %x, -1 1815 %a = add i32 %notx, %y 1816 %c = icmp ult i32 %x, %y 1817 %r = select i1 %c, i32 -1, i32 %a 1818 ret i32 %r 1819} 1820 1821define i32 @uadd_sat_not_nonstrict(i32 %x, i32 %y) { 1822; CHECK-LABEL: @uadd_sat_not_nonstrict( 1823; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1824; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1825; CHECK-NEXT: ret i32 [[R]] 1826; 1827 %notx = xor i32 %x, -1 1828 %a = add i32 %notx, %y 1829 %c = icmp ule i32 %x, %y 1830 %r = select i1 %c, i32 -1, i32 %a 1831 ret i32 %r 1832} 1833 1834define i32 @uadd_sat_not_commute_add(i32 %xp, i32 %yp) { 1835; CHECK-LABEL: @uadd_sat_not_commute_add( 1836; CHECK-NEXT: [[X:%.*]] = srem i32 42, [[XP:%.*]] 1837; CHECK-NEXT: [[Y:%.*]] = urem i32 42, [[YP:%.*]] 1838; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X]], -1 1839; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y]], i32 [[NOTX]]) 1840; CHECK-NEXT: ret i32 [[R]] 1841; 1842 %x = srem i32 42, %xp ; thwart complexity-based-canonicalization 1843 %y = urem i32 42, %yp ; thwart complexity-based-canonicalization 1844 %notx = xor i32 %x, -1 1845 %a = add i32 %y, %notx 1846 %c = icmp ult i32 %x, %y 1847 %r = select i1 %c, i32 -1, i32 %a 1848 ret i32 %r 1849} 1850 1851define i32 @uadd_sat_not_ugt(i32 %x, i32 %y) { 1852; CHECK-LABEL: @uadd_sat_not_ugt( 1853; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1854; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1855; CHECK-NEXT: ret i32 [[R]] 1856; 1857 %notx = xor i32 %x, -1 1858 %a = add i32 %notx, %y 1859 %c = icmp ugt i32 %y, %x 1860 %r = select i1 %c, i32 -1, i32 %a 1861 ret i32 %r 1862} 1863 1864define i32 @uadd_sat_not_uge(i32 %x, i32 %y) { 1865; CHECK-LABEL: @uadd_sat_not_uge( 1866; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1867; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1868; CHECK-NEXT: ret i32 [[R]] 1869; 1870 %notx = xor i32 %x, -1 1871 %a = add i32 %notx, %y 1872 %c = icmp uge i32 %y, %x 1873 %r = select i1 %c, i32 -1, i32 %a 1874 ret i32 %r 1875} 1876 1877define <2 x i32> @uadd_sat_not_ugt_commute_add(<2 x i32> %x, <2 x i32> %yp) { 1878; CHECK-LABEL: @uadd_sat_not_ugt_commute_add( 1879; CHECK-NEXT: [[Y:%.*]] = sdiv <2 x i32> [[YP:%.*]], <i32 2442, i32 4242> 1880; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i32> [[X:%.*]], splat (i32 -1) 1881; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> [[Y]], <2 x i32> [[NOTX]]) 1882; CHECK-NEXT: ret <2 x i32> [[R]] 1883; 1884 %y = sdiv <2 x i32> %yp, <i32 2442, i32 4242> ; thwart complexity-based-canonicalization 1885 %notx = xor <2 x i32> %x, <i32 -1, i32 -1> 1886 %a = add <2 x i32> %y, %notx 1887 %c = icmp ugt <2 x i32> %y, %x 1888 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a 1889 ret <2 x i32> %r 1890} 1891 1892define <2 x i32> @uadd_sat_not_ugt_commute_add_partial_poison(<2 x i32> %x, <2 x i32> %yp) { 1893; CHECK-LABEL: @uadd_sat_not_ugt_commute_add_partial_poison( 1894; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i32> [[X:%.*]], <i32 -1, i32 poison> 1895; CHECK-NEXT: [[A:%.*]] = add nuw <2 x i32> [[YP:%.*]], [[NOTX]] 1896; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i32> [[YP]], [[X]] 1897; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[C]], <2 x i32> splat (i32 -1), <2 x i32> [[A]] 1898; CHECK-NEXT: ret <2 x i32> [[R]] 1899; 1900 %notx = xor <2 x i32> %x, <i32 -1, i32 poison> 1901 %a = add nuw <2 x i32> %yp, %notx 1902 %c = icmp ugt <2 x i32> %yp, %x 1903 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a 1904 ret <2 x i32> %r 1905} 1906 1907define i32 @uadd_sat_not_commute_select(i32 %x, i32 %y) { 1908; CHECK-LABEL: @uadd_sat_not_commute_select( 1909; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1910; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1911; CHECK-NEXT: ret i32 [[R]] 1912; 1913 %notx = xor i32 %x, -1 1914 %a = add i32 %notx, %y 1915 %c = icmp ult i32 %y, %x 1916 %r = select i1 %c, i32 %a, i32 -1 1917 ret i32 %r 1918} 1919 1920define i32 @uadd_sat_not_commute_select_nonstrict(i32 %x, i32 %y) { 1921; CHECK-LABEL: @uadd_sat_not_commute_select_nonstrict( 1922; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1923; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1924; CHECK-NEXT: ret i32 [[R]] 1925; 1926 %notx = xor i32 %x, -1 1927 %a = add i32 %notx, %y 1928 %c = icmp ule i32 %y, %x 1929 %r = select i1 %c, i32 %a, i32 -1 1930 ret i32 %r 1931} 1932 1933define i32 @uadd_sat_not_commute_select_commute_add(i32 %x, i32 %yp) { 1934; CHECK-LABEL: @uadd_sat_not_commute_select_commute_add( 1935; CHECK-NEXT: [[Y:%.*]] = sdiv i32 42, [[YP:%.*]] 1936; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1937; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y]], i32 [[NOTX]]) 1938; CHECK-NEXT: ret i32 [[R]] 1939; 1940 %y = sdiv i32 42, %yp ; thwart complexity-based-canonicalization 1941 %notx = xor i32 %x, -1 1942 %a = add i32 %y, %notx 1943 %c = icmp ult i32 %y, %x 1944 %r = select i1 %c, i32 %a, i32 -1 1945 ret i32 %r 1946} 1947 1948define <2 x i32> @uadd_sat_not_commute_select_ugt(<2 x i32> %xp, <2 x i32> %yp) { 1949; CHECK-LABEL: @uadd_sat_not_commute_select_ugt( 1950; CHECK-NEXT: [[X:%.*]] = urem <2 x i32> <i32 42, i32 -42>, [[XP:%.*]] 1951; CHECK-NEXT: [[Y:%.*]] = srem <2 x i32> <i32 12, i32 412>, [[YP:%.*]] 1952; CHECK-NEXT: [[NOTX:%.*]] = xor <2 x i32> [[X]], splat (i32 -1) 1953; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> [[Y]], <2 x i32> [[NOTX]]) 1954; CHECK-NEXT: ret <2 x i32> [[R]] 1955; 1956 %x = urem <2 x i32> <i32 42, i32 -42>, %xp ; thwart complexity-based-canonicalization 1957 %y = srem <2 x i32> <i32 12, i32 412>, %yp ; thwart complexity-based-canonicalization 1958 %notx = xor <2 x i32> %x, <i32 -1, i32 -1> 1959 %a = add <2 x i32> %y, %notx 1960 %c = icmp ugt <2 x i32> %x, %y 1961 %r = select <2 x i1> %c, <2 x i32> %a, <2 x i32> <i32 -1, i32 -1> 1962 ret <2 x i32> %r 1963} 1964 1965define i32 @uadd_sat_not_commute_select_ugt_commute_add(i32 %x, i32 %y) { 1966; CHECK-LABEL: @uadd_sat_not_commute_select_ugt_commute_add( 1967; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1968; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1969; CHECK-NEXT: ret i32 [[R]] 1970; 1971 %notx = xor i32 %x, -1 1972 %a = add i32 %notx, %y 1973 %c = icmp ugt i32 %x, %y 1974 %r = select i1 %c, i32 %a, i32 -1 1975 ret i32 %r 1976} 1977 1978define i32 @uadd_sat_not_commute_select_uge_commute_add(i32 %x, i32 %y) { 1979; CHECK-LABEL: @uadd_sat_not_commute_select_uge_commute_add( 1980; CHECK-NEXT: [[NOTX:%.*]] = xor i32 [[X:%.*]], -1 1981; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[NOTX]]) 1982; CHECK-NEXT: ret i32 [[R]] 1983; 1984 %notx = xor i32 %x, -1 1985 %a = add i32 %notx, %y 1986 %c = icmp uge i32 %x, %y 1987 %r = select i1 %c, i32 %a, i32 -1 1988 ret i32 %r 1989} 1990 1991define i32 @uadd_sat_constant(i32 %x) { 1992; CHECK-LABEL: @uadd_sat_constant( 1993; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 42) 1994; CHECK-NEXT: ret i32 [[R]] 1995; 1996 %a = add i32 %x, 42 1997 %c = icmp ugt i32 %x, -43 1998 %r = select i1 %c, i32 -1, i32 %a 1999 ret i32 %r 2000} 2001 2002define i32 @uadd_sat_constant_commute(i32 %x) { 2003; CHECK-LABEL: @uadd_sat_constant_commute( 2004; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 42) 2005; CHECK-NEXT: ret i32 [[R]] 2006; 2007 %a = add i32 %x, 42 2008 %c = icmp ult i32 %x, -43 2009 %r = select i1 %c, i32 %a, i32 -1 2010 ret i32 %r 2011} 2012 2013define i32 @uadd_sat_canon(i32 %x, i32 %y) { 2014; CHECK-LABEL: @uadd_sat_canon( 2015; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y:%.*]]) 2016; CHECK-NEXT: ret i32 [[R]] 2017; 2018 %a = add i32 %x, %y 2019 %c = icmp ult i32 %a, %x 2020 %r = select i1 %c, i32 -1, i32 %a 2021 ret i32 %r 2022} 2023 2024define i32 @uadd_sat_canon_y(i32 %x, i32 %y) { 2025; CHECK-LABEL: @uadd_sat_canon_y( 2026; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]]) 2027; CHECK-NEXT: ret i32 [[R]] 2028; 2029 %a = add i32 %x, %y 2030 %c = icmp ult i32 %a, %y 2031 %r = select i1 %c, i32 -1, i32 %a 2032 ret i32 %r 2033} 2034 2035define i32 @uadd_sat_canon_nuw(i32 %x, i32 %y) { 2036; CHECK-LABEL: @uadd_sat_canon_nuw( 2037; CHECK-NEXT: [[A:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]] 2038; CHECK-NEXT: ret i32 [[A]] 2039; 2040 %a = add nuw i32 %x, %y 2041 %c = icmp ult i32 %a, %x 2042 %r = select i1 %c, i32 -1, i32 %a 2043 ret i32 %r 2044} 2045 2046define i32 @uadd_sat_canon_y_nuw(i32 %x, i32 %y) { 2047; CHECK-LABEL: @uadd_sat_canon_y_nuw( 2048; CHECK-NEXT: [[A:%.*]] = add nuw i32 [[X:%.*]], [[Y:%.*]] 2049; CHECK-NEXT: ret i32 [[A]] 2050; 2051 %a = add nuw i32 %x, %y 2052 %c = icmp ult i32 %a, %y 2053 %r = select i1 %c, i32 -1, i32 %a 2054 ret i32 %r 2055} 2056 2057define <4 x i32> @uadd_sat_constant_vec(<4 x i32> %x) { 2058; CHECK-LABEL: @uadd_sat_constant_vec( 2059; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> [[X:%.*]], <4 x i32> splat (i32 42)) 2060; CHECK-NEXT: ret <4 x i32> [[R]] 2061; 2062 %a = add <4 x i32> %x, <i32 42, i32 42, i32 42, i32 42> 2063 %c = icmp ugt <4 x i32> %x, <i32 -43, i32 -43, i32 -43, i32 -43> 2064 %r = select <4 x i1> %c, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1>, <4 x i32> %a 2065 ret <4 x i32> %r 2066} 2067 2068define <4 x i32> @uadd_sat_constant_vec_commute(<4 x i32> %x) { 2069; CHECK-LABEL: @uadd_sat_constant_vec_commute( 2070; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> [[X:%.*]], <4 x i32> splat (i32 42)) 2071; CHECK-NEXT: ret <4 x i32> [[R]] 2072; 2073 %a = add <4 x i32> %x, <i32 42, i32 42, i32 42, i32 42> 2074 %c = icmp ult <4 x i32> %x, <i32 -43, i32 -43, i32 -43, i32 -43> 2075 %r = select <4 x i1> %c, <4 x i32> %a, <4 x i32> <i32 -1, i32 -1, i32 -1, i32 -1> 2076 ret <4 x i32> %r 2077} 2078 2079define <4 x i32> @uadd_sat_constant_vec_commute_undefs(<4 x i32> %x) { 2080; CHECK-LABEL: @uadd_sat_constant_vec_commute_undefs( 2081; CHECK-NEXT: [[R:%.*]] = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> [[X:%.*]], <4 x i32> splat (i32 42)) 2082; CHECK-NEXT: ret <4 x i32> [[R]] 2083; 2084 %a = add <4 x i32> %x, <i32 42, i32 42, i32 42, i32 poison> 2085 %c = icmp ult <4 x i32> %x, <i32 -43, i32 -43, i32 poison, i32 -43> 2086 %r = select <4 x i1> %c, <4 x i32> %a, <4 x i32> <i32 -1, i32 poison, i32 -1, i32 -1> 2087 ret <4 x i32> %r 2088} 2089 2090declare i32 @get_i32() 2091declare <2 x i8> @get_v2i8() 2092 2093define i32 @unsigned_sat_variable_using_min_add(i32 %x) { 2094; CHECK-LABEL: @unsigned_sat_variable_using_min_add( 2095; CHECK-NEXT: [[Y:%.*]] = call i32 @get_i32() 2096; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 2097; CHECK-NEXT: ret i32 [[R]] 2098; 2099 %y = call i32 @get_i32() ; thwart complexity-based canonicalization 2100 %noty = xor i32 %y, -1 2101 %c = icmp ult i32 %x, %noty 2102 %s = select i1 %c, i32 %x, i32 %noty 2103 %r = add i32 %s, %y 2104 ret i32 %r 2105} 2106 2107define i32 @unsigned_sat_variable_using_min_commute_add(i32 %x) { 2108; CHECK-LABEL: @unsigned_sat_variable_using_min_commute_add( 2109; CHECK-NEXT: [[Y:%.*]] = call i32 @get_i32() 2110; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 [[Y]]) 2111; CHECK-NEXT: ret i32 [[R]] 2112; 2113 %y = call i32 @get_i32() ; thwart complexity-based canonicalization 2114 %noty = xor i32 %y, -1 2115 %c = icmp ult i32 %x, %noty 2116 %s = select i1 %c, i32 %x, i32 %noty 2117 %r = add i32 %y, %s 2118 ret i32 %r 2119} 2120 2121define <2 x i8> @unsigned_sat_variable_using_min_commute_select(<2 x i8> %x) { 2122; CHECK-LABEL: @unsigned_sat_variable_using_min_commute_select( 2123; CHECK-NEXT: [[Y:%.*]] = call <2 x i8> @get_v2i8() 2124; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y]]) 2125; CHECK-NEXT: ret <2 x i8> [[R]] 2126; 2127 %y = call <2 x i8> @get_v2i8() ; thwart complexity-based canonicalization 2128 %noty = xor <2 x i8> %y, <i8 -1, i8 -1> 2129 %c = icmp ult <2 x i8> %noty, %x 2130 %s = select <2 x i1> %c, <2 x i8> %noty, <2 x i8> %x 2131 %r = add <2 x i8> %s, %y 2132 ret <2 x i8> %r 2133} 2134 2135define <2 x i8> @unsigned_sat_variable_using_min_commute_add_select(<2 x i8> %x) { 2136; CHECK-LABEL: @unsigned_sat_variable_using_min_commute_add_select( 2137; CHECK-NEXT: [[Y:%.*]] = call <2 x i8> @get_v2i8() 2138; CHECK-NEXT: [[R:%.*]] = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> [[X:%.*]], <2 x i8> [[Y]]) 2139; CHECK-NEXT: ret <2 x i8> [[R]] 2140; 2141 %y = call <2 x i8> @get_v2i8() ; thwart complexity-based canonicalization 2142 %noty = xor <2 x i8> %y, <i8 -1, i8 -1> 2143 %c = icmp ult <2 x i8> %noty, %x 2144 %s = select <2 x i1> %c, <2 x i8> %noty, <2 x i8> %x 2145 %r = add <2 x i8> %y, %s 2146 ret <2 x i8> %r 2147} 2148 2149; Negative test 2150 2151define i32 @unsigned_sat_variable_using_wrong_min(i32 %x) { 2152; CHECK-LABEL: @unsigned_sat_variable_using_wrong_min( 2153; CHECK-NEXT: [[Y:%.*]] = call i32 @get_i32() 2154; CHECK-NEXT: [[NOTY:%.*]] = xor i32 [[Y]], -1 2155; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 [[NOTY]]) 2156; CHECK-NEXT: [[R:%.*]] = add i32 [[Y]], [[S]] 2157; CHECK-NEXT: ret i32 [[R]] 2158; 2159 %y = call i32 @get_i32() ; thwart complexity-based canonicalization 2160 %noty = xor i32 %y, -1 2161 %c = icmp slt i32 %x, %noty 2162 %s = select i1 %c, i32 %x, i32 %noty 2163 %r = add i32 %y, %s 2164 ret i32 %r 2165} 2166 2167; Negative test 2168 2169define i32 @unsigned_sat_variable_using_wrong_value(i32 %x, i32 %z) { 2170; CHECK-LABEL: @unsigned_sat_variable_using_wrong_value( 2171; CHECK-NEXT: [[Y:%.*]] = call i32 @get_i32() 2172; CHECK-NEXT: [[NOTY:%.*]] = xor i32 [[Y]], -1 2173; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 [[NOTY]]) 2174; CHECK-NEXT: [[R:%.*]] = add i32 [[Z:%.*]], [[S]] 2175; CHECK-NEXT: ret i32 [[R]] 2176; 2177 %y = call i32 @get_i32() ; thwart complexity-based canonicalization 2178 %noty = xor i32 %y, -1 2179 %c = icmp ult i32 %x, %noty 2180 %s = select i1 %c, i32 %x, i32 %noty 2181 %r = add i32 %z, %s 2182 ret i32 %r 2183} 2184 2185; If we have a constant operand, there's no commutativity variation. 2186 2187define i32 @unsigned_sat_constant_using_min(i32 %x) { 2188; CHECK-LABEL: @unsigned_sat_constant_using_min( 2189; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[X:%.*]], i32 -43) 2190; CHECK-NEXT: ret i32 [[R]] 2191; 2192 %c = icmp ult i32 %x, 42 2193 %s = select i1 %c, i32 %x, i32 42 2194 %r = add i32 %s, -43 2195 ret i32 %r 2196} 2197 2198define <2 x i32> @unsigned_sat_constant_using_min_splat(<2 x i32> %x) { 2199; CHECK-LABEL: @unsigned_sat_constant_using_min_splat( 2200; CHECK-NEXT: [[R:%.*]] = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> [[X:%.*]], <2 x i32> splat (i32 -15)) 2201; CHECK-NEXT: ret <2 x i32> [[R]] 2202; 2203 %c = icmp ult <2 x i32> %x, <i32 14, i32 14> 2204 %s = select <2 x i1> %c, <2 x i32> %x, <2 x i32> <i32 14, i32 14> 2205 %r = add <2 x i32> %s, <i32 -15, i32 -15> 2206 ret <2 x i32> %r 2207} 2208 2209; Negative test 2210 2211define i32 @unsigned_sat_constant_using_min_wrong_constant(i32 %x) { 2212; CHECK-LABEL: @unsigned_sat_constant_using_min_wrong_constant( 2213; CHECK-NEXT: [[S:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 42) 2214; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[S]], -42 2215; CHECK-NEXT: ret i32 [[R]] 2216; 2217 %c = icmp ult i32 %x, 42 2218 %s = select i1 %c, i32 %x, i32 42 2219 %r = add i32 %s, -42 2220 ret i32 %r 2221} 2222 2223define i32 @uadd_sat_via_add(i32 %x, i32 %y) { 2224; CHECK-LABEL: @uadd_sat_via_add( 2225; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]]) 2226; CHECK-NEXT: ret i32 [[R]] 2227; 2228 %a = add i32 %x, %y 2229 %c = icmp ult i32 %a, %y 2230 %r = select i1 %c, i32 -1, i32 %a 2231 ret i32 %r 2232} 2233 2234define i32 @uadd_sat_via_add_nonstrict(i32 %x, i32 %y) { 2235; CHECK-LABEL: @uadd_sat_via_add_nonstrict( 2236; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 2237; CHECK-NEXT: [[C_NOT:%.*]] = icmp ugt i32 [[A]], [[Y]] 2238; CHECK-NEXT: [[R:%.*]] = select i1 [[C_NOT]], i32 [[A]], i32 -1 2239; CHECK-NEXT: ret i32 [[R]] 2240; 2241 %a = add i32 %x, %y 2242 %c = icmp ule i32 %a, %y 2243 %r = select i1 %c, i32 -1, i32 %a 2244 ret i32 %r 2245} 2246 2247define i32 @uadd_sat_via_add_swapped_select(i32 %x, i32 %y) { 2248; CHECK-LABEL: @uadd_sat_via_add_swapped_select( 2249; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]]) 2250; CHECK-NEXT: ret i32 [[R]] 2251; 2252 %a = add i32 %x, %y 2253 %c = icmp uge i32 %a, %y 2254 %r = select i1 %c, i32 %a, i32 -1 2255 ret i32 %r 2256} 2257 2258define i32 @uadd_sat_via_add_swapped_select_strict(i32 %x, i32 %y) { 2259; CHECK-LABEL: @uadd_sat_via_add_swapped_select_strict( 2260; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 2261; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[A]], [[Y]] 2262; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 -1 2263; CHECK-NEXT: ret i32 [[R]] 2264; 2265 %a = add i32 %x, %y 2266 %c = icmp ugt i32 %a, %y 2267 %r = select i1 %c, i32 %a, i32 -1 2268 ret i32 %r 2269} 2270 2271define i32 @uadd_sat_via_add_swapped_cmp(i32 %x, i32 %y) { 2272; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp( 2273; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]]) 2274; CHECK-NEXT: ret i32 [[R]] 2275; 2276 %a = add i32 %x, %y 2277 %c = icmp ugt i32 %y, %a 2278 %r = select i1 %c, i32 -1, i32 %a 2279 ret i32 %r 2280} 2281 2282define i32 @uadd_sat_via_add_swapped_cmp_nonstrict(i32 %x, i32 %y) { 2283; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp_nonstrict( 2284; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 2285; CHECK-NEXT: [[C_NOT:%.*]] = icmp ult i32 [[Y]], [[A]] 2286; CHECK-NEXT: [[R:%.*]] = select i1 [[C_NOT]], i32 [[A]], i32 -1 2287; CHECK-NEXT: ret i32 [[R]] 2288; 2289 %a = add i32 %x, %y 2290 %c = icmp uge i32 %y, %a 2291 %r = select i1 %c, i32 -1, i32 %a 2292 ret i32 %r 2293} 2294 2295define i32 @uadd_sat_via_add_swapped_cmp_nonstric(i32 %x, i32 %y) { 2296; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp_nonstric( 2297; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.uadd.sat.i32(i32 [[Y:%.*]], i32 [[X:%.*]]) 2298; CHECK-NEXT: ret i32 [[R]] 2299; 2300 %a = add i32 %x, %y 2301 %c = icmp ule i32 %y, %a 2302 %r = select i1 %c, i32 %a, i32 -1 2303 ret i32 %r 2304} 2305 2306define i32 @uadd_sat_via_add_swapped_cmp_select_nonstrict(i32 %x, i32 %y) { 2307; CHECK-LABEL: @uadd_sat_via_add_swapped_cmp_select_nonstrict( 2308; CHECK-NEXT: [[A:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] 2309; CHECK-NEXT: [[C:%.*]] = icmp ult i32 [[Y]], [[A]] 2310; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 -1 2311; CHECK-NEXT: ret i32 [[R]] 2312; 2313 %a = add i32 %x, %y 2314 %c = icmp ult i32 %y, %a 2315 %r = select i1 %c, i32 %a, i32 -1 2316 ret i32 %r 2317} 2318 2319define i8 @fold_add_umax_to_usub(i8 %a) { 2320; CHECK-LABEL: @fold_add_umax_to_usub( 2321; CHECK-NEXT: [[SEL:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[A:%.*]], i8 10) 2322; CHECK-NEXT: ret i8 [[SEL]] 2323; 2324 %umax = call i8 @llvm.umax.i8(i8 %a, i8 10) 2325 %sel = add i8 %umax, -10 2326 ret i8 %sel 2327} 2328 2329define i8 @fold_add_umax_to_usub_incorrect_rhs(i8 %a) { 2330; CHECK-LABEL: @fold_add_umax_to_usub_incorrect_rhs( 2331; CHECK-NEXT: [[UMAX:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 10) 2332; CHECK-NEXT: [[SEL:%.*]] = add i8 [[UMAX]], -11 2333; CHECK-NEXT: ret i8 [[SEL]] 2334; 2335 %umax = call i8 @llvm.umax.i8(i8 %a, i8 10) 2336 %sel = add i8 %umax, -11 2337 ret i8 %sel 2338} 2339 2340define i8 @fold_add_umax_to_usub_multiuse(i8 %a) { 2341; CHECK-LABEL: @fold_add_umax_to_usub_multiuse( 2342; CHECK-NEXT: [[UMAX:%.*]] = call i8 @llvm.umax.i8(i8 [[A:%.*]], i8 10) 2343; CHECK-NEXT: call void @usei8(i8 [[UMAX]]) 2344; CHECK-NEXT: [[SEL:%.*]] = add i8 [[UMAX]], -10 2345; CHECK-NEXT: ret i8 [[SEL]] 2346; 2347 %umax = call i8 @llvm.umax.i8(i8 %a, i8 10) 2348 call void @usei8(i8 %umax) 2349 %sel = add i8 %umax, -10 2350 ret i8 %sel 2351} 2352 2353declare void @usei8(i8) 2354