2690 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 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 %x21}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> %x30}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 %x40}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> %x49}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 %x260}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> %x270}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> %x282}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 -188;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 %y292}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> %y2101}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 %z2112}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> %z2122}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 %u2132}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> %u2142}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 %v2154}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 %w2166}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 -1172;173 %a_neg = or i8 %a, -128174 %r = call i8 @llvm.uadd.sat.i8(i8 %a_neg, i8 -10)175 ret i8 %r176}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> %r185}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:%.*]], 127191; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[A_NNEG]], 10192; CHECK-NEXT: ret i8 [[R]]193;194 %a_nneg = and i8 %a, 127195 %r = call i8 @llvm.uadd.sat.i8(i8 %a_nneg, i8 10)196 ret i8 %r197}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> %r208}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:%.*]], -128214; 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, -128218 %r = call i8 @llvm.uadd.sat.i8(i8 %a_neg, i8 10)219 ret i8 %r220}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> %r231}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:%.*]], -127236; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[A_MASKED]], 1237; CHECK-NEXT: ret i8 [[R]]238;239 %a_masked = and i8 %a, 129240 %r = call i8 @llvm.uadd.sat.i8(i8 %a_masked, i8 1)241 ret i8 %r242}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> %r253}254 255define i8 @test_scalar_uadd_always_overflows(i8 %a) {256; CHECK-LABEL: @test_scalar_uadd_always_overflows(257; CHECK-NEXT: ret i8 -1258;259 %a_masked = or i8 %a, 192260 %r = call i8 @llvm.uadd.sat.i8(i8 %a_masked, i8 64)261 ret i8 %r262}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> %r271}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:%.*]], -128277; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NEG]], 10278; CHECK-NEXT: ret i8 [[R]]279;280 %a_neg = or i8 %a, -128281 %r = call i8 @llvm.sadd.sat.i8(i8 %a_neg, i8 10)282 ret i8 %r283}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> %r294}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:%.*]], 127300; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NNEG]], -10301; CHECK-NEXT: ret i8 [[R]]302;303 %a_nneg = and i8 %a, 127304 %r = call i8 @llvm.sadd.sat.i8(i8 %a_nneg, i8 -10)305 ret i8 %r306}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> %r317}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:%.*]], -128323; 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, -128327 %r = call i8 @llvm.sadd.sat.i8(i8 %a_neg, i8 -10)328 ret i8 %r329}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> %r340}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 -128345;346 %cmp = icmp slt i8 %a, -120347 %min = select i1 %cmp, i8 %a, i8 -120348 %r = call i8 @llvm.sadd.sat.i8(i8 %min, i8 -10)349 ret i8 %r350}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 127355;356 %cmp = icmp sgt i8 %a, 120357 %max = select i1 %cmp, i8 %a, i8 120358 %r = call i8 @llvm.sadd.sat.i8(i8 %max, i8 10)359 ret i8 %r360}361 362; While this is a no-overflow condition, the nuw flag gets lost due to363; canonicalization and we can no longer determine this364define 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:%.*]], -10367; 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, 10371 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 9)372 ret i8 %r373}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:%.*]], 100378; CHECK-NEXT: [[R:%.*]] = add nuw nsw i8 [[B]], -100379; CHECK-NEXT: ret i8 [[R]]380;381 %b = urem i8 %a, 100382 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 156)383 ret i8 %r384}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:%.*]], 100389; 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, 100393 %r = call i8 @llvm.uadd.sat.i8(i8 %b, i8 157)394 ret i8 %r395}396 397; We have a constant range for the LHS, but only known bits for the RHS398define 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:%.*]], 63402; CHECK-NEXT: [[R:%.*]] = add nuw i8 [[AA]], [[BB]]403; CHECK-NEXT: ret i8 [[R]]404;405 %aa = udiv i8 190, %a406 %bb = and i8 %b, 63407 %r = call i8 @llvm.uadd.sat.i8(i8 %aa, i8 %bb)408 ret i8 %r409}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:%.*]], 100414; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[B]], 28415; CHECK-NEXT: ret i8 [[R]]416;417 %b = srem i8 %a, 100418 %r = call i8 @llvm.sadd.sat.i8(i8 %b, i8 28)419 ret i8 %r420}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:%.*]], 100425; 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, 100429 %r = call i8 @llvm.sadd.sat.i8(i8 %b, i8 29)430 ret i8 %r431}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:%.*]], 100436; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 15437; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[AA]], [[BB]]438; CHECK-NEXT: ret i8 [[R]]439;440 %aa = srem i8 %a, 100441 %bb = and i8 %b, 15442 %r = call i8 @llvm.sadd.sat.i8(i8 %aa, i8 %bb)443 ret i8 %r444}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 %r463}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 %r473}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> %r482}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> %r491}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 %r501}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> %r510}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 %x2521}522 523; Can simplify zero check followed by decrement524define 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, 0530 %i1 = sub i8 %a, 1531 %i2 = select i1 %i, i8 0, i8 %i1532 ret i8 %i2533}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:%.*]], 0540; 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, 0545 call void @use.i1(i1 %i)546 %i1 = add i8 %a, -1547 %i2 = select i1 %i, i8 %i1, i8 0548 ret i8 %i2549}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> %i1559 ret <2 x i8> %i2560}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> %i1570 ret <2 x i8> %i2571}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:%.*]], 0576; CHECK-NEXT: [[I2:%.*]] = sext i1 [[I_NOT]] to i8577; CHECK-NEXT: ret i8 [[I2]]578;579 %i = icmp ne i8 %a, 0580 %i1 = sub i8 %a, 1581 %i2 = select i1 %i, i8 0, i8 %i1582 ret i8 %i2583}584 585define i8 @test_invalid_simplify_sub2(i8 %a) {586; CHECK-LABEL: @test_invalid_simplify_sub2(587; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 0588; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -2589; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]]590; CHECK-NEXT: ret i8 [[I2]]591;592 %i = icmp eq i8 %a, 0593 %i1 = sub i8 %a, 2594 %i2 = select i1 %i, i8 0, i8 %i1595 ret i8 %i2596}597 598define i8 @test_invalid_simplify_eq2(i8 %a) {599; CHECK-LABEL: @test_invalid_simplify_eq2(600; CHECK-NEXT: [[I:%.*]] = icmp eq i8 [[A:%.*]], 2601; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -1602; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]]603; CHECK-NEXT: ret i8 [[I2]]604;605 %i = icmp eq i8 %a, 2606 %i1 = sub i8 %a, 1607 %i2 = select i1 %i, i8 0, i8 %i1608 ret i8 %i2609}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:%.*]], 0614; CHECK-NEXT: [[I1:%.*]] = add i8 [[A]], -1615; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 1, i8 [[I1]]616; CHECK-NEXT: ret i8 [[I2]]617;618 %i = icmp eq i8 %a, 0619 %i1 = sub i8 %a, 1620 %i2 = select i1 %i, i8 1, i8 %i1621 ret i8 %i2622}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:%.*]], 0627; CHECK-NEXT: [[I1:%.*]] = add i8 [[B:%.*]], -1628; CHECK-NEXT: [[I2:%.*]] = select i1 [[I]], i8 0, i8 [[I1]]629; CHECK-NEXT: ret i8 [[I2]]630;631 %i = icmp eq i8 %a, 0632 %i1 = sub i8 %b, 1633 %i2 = select i1 %i, i8 0, i8 %i1634 ret i8 %i2635}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> %x2645}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> %x2657}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 0663;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 %y2667}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> zeroinitializer672;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> %y2676}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 %z2687}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> %z2697}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 %u2707}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> %u2717}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 %v2729}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 %v2740}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> %v2750}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 %w2762}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 0768;769 %a_nneg = and i8 %a, 127770 %r = call i8 @llvm.usub.sat.i8(i8 %a_nneg, i8 -10)771 ret i8 %r772}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> zeroinitializer777;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> %r781}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:%.*]], -128787; CHECK-NEXT: [[R:%.*]] = add i8 [[A_NEG]], -10788; CHECK-NEXT: ret i8 [[R]]789;790 %a_neg = or i8 %a, -128791 %r = call i8 @llvm.usub.sat.i8(i8 %a_neg, i8 10)792 ret i8 %r793}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> %r804}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:%.*]], 127810; 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, 127814 %r = call i8 @llvm.usub.sat.i8(i8 %a_nneg, i8 10)815 ret i8 %r816}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> %r827}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:%.*]], 64832; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_MASKED]], -10833; CHECK-NEXT: ret i8 [[R]]834;835 %a_masked = or i8 %a, 64836 %r = call i8 @llvm.usub.sat.i8(i8 %a_masked, i8 10)837 ret i8 %r838}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> %r849}850 851define i8 @test_scalar_usub_always_overflows(i8 %a) {852; CHECK-LABEL: @test_scalar_usub_always_overflows(853; CHECK-NEXT: ret i8 0854;855 %a_masked = and i8 %a, 64856 %r = call i8 @llvm.usub.sat.i8(i8 %a_masked, i8 100)857 ret i8 %r858}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> zeroinitializer863;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> %r867}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:%.*]], -128873; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NEG]], 10874; CHECK-NEXT: ret i8 [[R]]875;876 %a_neg = or i8 %a, -128877 %r = call i8 @llvm.ssub.sat.i8(i8 %a_neg, i8 -10)878 ret i8 %r879}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> %r890}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:%.*]], 127896; CHECK-NEXT: [[R:%.*]] = add nsw i8 [[A_NNEG]], -10897; CHECK-NEXT: ret i8 [[R]]898;899 %a_nneg = and i8 %a, 127900 %r = call i8 @llvm.ssub.sat.i8(i8 %a_nneg, i8 10)901 ret i8 %r902}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> %r913}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:%.*]], -128919; 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, -128923 %r = call i8 @llvm.ssub.sat.i8(i8 %a_neg, i8 10)924 ret i8 %r925}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> %r936}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 -128941;942 %cmp = icmp sgt i8 %a, 120943 %max = select i1 %cmp, i8 %a, i8 120944 %r = call i8 @llvm.ssub.sat.i8(i8 -10, i8 %max)945 ret i8 %r946}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 127951;952 %cmp = icmp slt i8 %a, -120953 %min = select i1 %cmp, i8 %a, i8 -120954 %r = call i8 @llvm.ssub.sat.i8(i8 10, i8 %min)955 ret i8 %r956}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:%.*]], 1961; CHECK-NEXT: ret i8 [[R]]962;963 %b = add nuw i8 %a, 10964 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9)965 ret i8 %r966}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:%.*]], 1971; CHECK-NEXT: ret i8 [[R]]972;973 %b = add nuw nsw i8 %a, 10974 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9)975 ret i8 %r976}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, 10983 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)984 ret i8 %r985}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:%.*]], 10990; 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, 10994 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 11)995 ret i8 %r996}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 01001;1002 %b = urem i8 %a, 101003 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 10)1004 ret i8 %r1005}1006 1007; Like the previous case, the result is always zero here. However, as there's1008; 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:%.*]], 101012; 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, 101016 %r = call i8 @llvm.usub.sat.i8(i8 %b, i8 9)1017 ret i8 %r1018}1019 1020; We have a constant range for the LHS, but only known bits for the RHS1021define 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:%.*]], 101024; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 71025; CHECK-NEXT: [[R:%.*]] = sub nuw i8 [[AA]], [[BB]]1026; CHECK-NEXT: ret i8 [[R]]1027;1028 %aa = add nuw i8 %a, 101029 %bb = and i8 %b, 71030 %r = call i8 @llvm.usub.sat.i8(i8 %aa, i8 %bb)1031 ret i8 %r1032}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]], 91038; CHECK-NEXT: ret i8 [[R]]1039;1040 %b = call i8 @llvm.usub.sat.i8(i8 %a, i8 10)1041 %r = add i8 %b, 91042 ret i8 %r1043}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> %r1053}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> %r1063}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> %r1073}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> %r1085}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> %r1097}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:%.*]], 71102; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 71103; CHECK-NEXT: [[R:%.*]] = sub nsw i8 [[AA]], [[BB]]1104; CHECK-NEXT: ret i8 [[R]]1105;1106 %aa = add nsw i8 %a, 71107 %bb = and i8 %b, 71108 %r = call i8 @llvm.ssub.sat.i8(i8 %aa, i8 %bb)1109 ret i8 %r1110}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:%.*]], 61115; CHECK-NEXT: [[BB:%.*]] = and i8 [[B:%.*]], 71116; 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, 61120 %bb = and i8 %b, 71121 %r = call i8 @llvm.ssub.sat.i8(i8 %aa, i8 %bb)1122 ret i8 %r1123}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> %r1136}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> %r1149}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> %r1162}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> %r1175}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, %b1184 ret i8 %res1185}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 11191; 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 %p1196 %res = add i8 %sat, %b1197 ret i8 %res1198}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, %sat1207 ret i8 %res1208}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, %b1218 ret i8 %res1219}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, 421228 ret i8 %res1229}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, %sat1238 ret i8 %res1239}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 11245; 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 %p1250 %res = sub i8 %a, %sat1251 ret i8 %res1252}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, %sat1261 ret <2 x i8> %res1262}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, %sat1272 ret i8 %res1273}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, %b1283 ret i8 %res1284}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, %b1294 ret i8 %res1295}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 11301; 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 %p1306 %res = sub i8 %sat, %b1307 ret i8 %res1308}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, %b1318 ret i8 %res1319}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, %sat1329 ret i8 %res1330}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]], -421336; CHECK-NEXT: ret i8 [[RES]]1337;1338 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 42)1339 %res = sub i8 %sat, 421340 ret i8 %res1341}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]], 01347; CHECK-NEXT: ret i1 [[CMP]]1348;1349 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b)1350 %cmp = icmp eq i8 %sat, 01351 ret i1 %cmp1352}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]], 01358; CHECK-NEXT: ret i1 [[CMP]]1359;1360 %sat = call i8 @llvm.uadd.sat.i8(i8 %a, i8 %b)1361 %cmp = icmp ne i8 %sat, 01362 ret i1 %cmp1363}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, 01372 ret i1 %cmp1373}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, 01382 ret i1 %cmp1383}1384 1385; Raw IR tests1386 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, -11393 %a = add i32 %y, %x1394 %c = icmp ult i32 %notx, %y1395 %r = select i1 %c, i32 -1, i32 %a1396 ret i32 %r1397}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, -111405 %add = add i32 %x, 91406 %cond = select i1 %cmp, i32 -1, i32 %add1407 ret i32 %cond1408}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, -101416 %add = add i32 %x, 91417 %cond = select i1 %cmp, i32 -1, i32 %add1418 ret i32 %cond1419}1420 1421define i32 @uadd_sat_flipped3(i32 %x) {1422; CHECK-LABEL: @uadd_sat_flipped3(1423; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[X:%.*]], -81424; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[X]], 91425; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1426; CHECK-NEXT: ret i32 [[COND]]1427;1428 %cmp = icmp ugt i32 %x, -81429 %add = add nuw i32 %x, 91430 %cond = select i1 %cmp, i32 -1, i32 %add1431 ret i32 %cond1432}1433 1434; Negative Test1435 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:%.*]], -81439; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91440; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1441; CHECK-NEXT: ret i32 [[COND]]1442;1443 %cmp = icmp ugt i32 %x, -81444 %add = add i32 %x, 91445 %cond = select i1 %cmp, i32 -1, i32 %add1446 ret i32 %cond1447}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, -11455 %add = add i32 %x, 11456 %cond = select i1 %cmp, i32 -1, i32 %add1457 ret i32 %cond1458}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> %cond1469}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> %cond1480}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> %cond1491}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> %cond1501}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:%.*]], -81508; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91509; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -11510; CHECK-NEXT: ret i32 [[COND]]1511;1512 %cmp = icmp ult i32 %x, -81513 %add = add i32 %x, 91514 %cond = select i1 %cmp, i32 %add, i32 -11515 ret i32 %cond1516}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:%.*]], -131523; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91524; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1525; CHECK-NEXT: ret i32 [[COND]]1526;1527 %cmp = icmp uge i32 %x, -121528 %add = add i32 %x, 91529 %cond = select i1 %cmp, i32 -1, i32 %add1530 ret i32 %cond1531}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:%.*]], -121538; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91539; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1540; CHECK-NEXT: ret i32 [[COND]]1541;1542 %cmp = icmp ugt i32 %x, -121543 %add = add i32 %x, 91544 %cond = select i1 %cmp, i32 -1, i32 %add1545 ret i32 %cond1546}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:%.*]], -121553; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91554; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1555; CHECK-NEXT: ret i32 [[COND]]1556;1557 %cmp = icmp ugt i32 %x, -121558 %add = add i32 %x, 91559 %cond = select i1 %cmp, i32 -1, i32 %add1560 ret i32 %cond1561}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:%.*]], -91568; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91569; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 -1, i32 [[ADD]]1570; CHECK-NEXT: ret i32 [[COND]]1571;1572 %cmp = icmp uge i32 %x, -81573 %add = add i32 %x, 91574 %cond = select i1 %cmp, i32 -1, i32 %add1575 ret i32 %cond1576}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:%.*]], -81583; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91584; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -11585; CHECK-NEXT: ret i32 [[COND]]1586;1587 %cmp = icmp ult i32 %x, -81588 %add = add i32 %x, 91589 %cond = select i1 %cmp, i32 %add, i32 -11590 ret i32 %cond1591}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:%.*]], -111598; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91599; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -11600; CHECK-NEXT: ret i32 [[COND]]1601;1602 %cmp = icmp ule i32 %x, -121603 %add = add i32 %x, 91604 %cond = select i1 %cmp, i32 %add, i32 -11605 ret i32 %cond1606}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:%.*]], -111613; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91614; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -11615; CHECK-NEXT: ret i32 [[COND]]1616;1617 %cmp = icmp ule i32 %x, -121618 %add = add i32 %x, 91619 %cond = select i1 %cmp, i32 %add, i32 -11620 ret i32 %cond1621}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:%.*]], -121628; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 91629; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 -11630; CHECK-NEXT: ret i32 [[COND]]1631;1632 %cmp = icmp ult i32 %x, -121633 %add = add i32 %x, 91634 %cond = select i1 %cmp, i32 %add, i32 -11635 ret i32 %cond1636}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, -11644 %a = add i32 %y, %x1645 %c = icmp ule i32 %notx, %y1646 %r = select i1 %c, i32 -1, i32 %a1647 ret i32 %r1648}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-canonicalization1657 %notx = xor i32 %x, -11658 %a = add i32 %x, %y1659 %c = icmp ult i32 %notx, %y1660 %r = select i1 %c, i32 -1, i32 %a1661 ret i32 %r1662}1663 1664define i32 @uadd_sat_ugt(i32 %x, i32 %yp) {1665; CHECK-LABEL: @uadd_sat_ugt(1666; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 24421667; 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-canonicalization1671 %notx = xor i32 %x, -11672 %a = add i32 %y, %x1673 %c = icmp ugt i32 %y, %notx1674 %r = select i1 %c, i32 -1, i32 %a1675 ret i32 %r1676}1677define i32 @uadd_sat_uge(i32 %x, i32 %yp) {1678; CHECK-LABEL: @uadd_sat_uge(1679; CHECK-NEXT: [[Y:%.*]] = sdiv i32 [[YP:%.*]], 24421680; 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-canonicalization1684 %notx = xor i32 %x, -11685 %a = add i32 %y, %x1686 %c = icmp uge i32 %y, %notx1687 %r = select i1 %c, i32 -1, i32 %a1688 ret i32 %r1689}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-canonicalization1699 %x = srem <2 x i32> <i32 42, i32 43>, %xp ; thwart complexity-based-canonicalization1700 %notx = xor <2 x i32> %x, <i32 -1, i32 -1>1701 %a = add <2 x i32> %x, %y1702 %c = icmp ugt <2 x i32> %y, %notx1703 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a1704 ret <2 x i32> %r1705}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:%.*]], 24421710; 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-canonicalization1714 %notx = xor i32 %x, -11715 %a = add i32 %y, %x1716 %c = icmp ult i32 %y, %notx1717 %r = select i1 %c, i32 %a, i32 -11718 ret i32 %r1719}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:%.*]], 24421724; 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-canonicalization1728 %notx = xor i32 %x, -11729 %a = add i32 %y, %x1730 %c = icmp ule i32 %y, %notx1731 %r = select i1 %c, i32 %a, i32 -11732 ret i32 %r1733}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:%.*]], 24421739; 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-canonicalization1743 %y = sdiv i32 %yp, 2442 ; thwart complexity-based-canonicalization1744 %notx = xor i32 %x, -11745 %a = add i32 %x, %y1746 %c = icmp ult i32 %y, %notx1747 %r = select i1 %c, i32 %a, i32 -11748 ret i32 %r1749}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, %x1758 %c = icmp ugt <2 x i32> %notx, %y1759 %r = select <2 x i1> %c, <2 x i32> %a, <2 x i32> <i32 -1, i32 -1>1760 ret <2 x i32> %r1761}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-canonicalization1770 %notx = xor i32 %x, -11771 %a = add i32 %x, %y1772 %c = icmp ugt i32 %notx, %y1773 %r = select i1 %c, i32 %a, i32 -11774 ret i32 %r1775}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:%.*]], -21782; CHECK-NEXT: [[C:%.*]] = icmp ugt i32 [[X]], 11783; CHECK-NEXT: [[R:%.*]] = select i1 [[C]], i32 [[A]], i32 [[Y:%.*]]1784; CHECK-NEXT: ret i32 [[R]]1785;1786 %a = add i32 %x, -21787 %c = icmp ugt i32 %x, 11788 %r = select i1 %c, i32 %a, i32 %y1789 ret i32 %r1790}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]], -21798; CHECK-NEXT: ret i32 [[A]]1799;1800 %a = add i32 %x, -21801 %c = icmp ugt i32 %x, 11802 %r = select i1 %c, i32 %a, i32 -11803 ret i32 %r1804}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:%.*]], -11811; 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, -11815 %a = add i32 %notx, %y1816 %c = icmp ult i32 %x, %y1817 %r = select i1 %c, i32 -1, i32 %a1818 ret i32 %r1819}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:%.*]], -11824; 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, -11828 %a = add i32 %notx, %y1829 %c = icmp ule i32 %x, %y1830 %r = select i1 %c, i32 -1, i32 %a1831 ret i32 %r1832}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]], -11839; 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-canonicalization1843 %y = urem i32 42, %yp ; thwart complexity-based-canonicalization1844 %notx = xor i32 %x, -11845 %a = add i32 %y, %notx1846 %c = icmp ult i32 %x, %y1847 %r = select i1 %c, i32 -1, i32 %a1848 ret i32 %r1849}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:%.*]], -11854; 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, -11858 %a = add i32 %notx, %y1859 %c = icmp ugt i32 %y, %x1860 %r = select i1 %c, i32 -1, i32 %a1861 ret i32 %r1862}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:%.*]], -11867; 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, -11871 %a = add i32 %notx, %y1872 %c = icmp uge i32 %y, %x1873 %r = select i1 %c, i32 -1, i32 %a1874 ret i32 %r1875}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-canonicalization1885 %notx = xor <2 x i32> %x, <i32 -1, i32 -1>1886 %a = add <2 x i32> %y, %notx1887 %c = icmp ugt <2 x i32> %y, %x1888 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a1889 ret <2 x i32> %r1890}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, %notx1902 %c = icmp ugt <2 x i32> %yp, %x1903 %r = select <2 x i1> %c, <2 x i32> <i32 -1, i32 -1>, <2 x i32> %a1904 ret <2 x i32> %r1905}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:%.*]], -11910; 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, -11914 %a = add i32 %notx, %y1915 %c = icmp ult i32 %y, %x1916 %r = select i1 %c, i32 %a, i32 -11917 ret i32 %r1918}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:%.*]], -11923; 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, -11927 %a = add i32 %notx, %y1928 %c = icmp ule i32 %y, %x1929 %r = select i1 %c, i32 %a, i32 -11930 ret i32 %r1931}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:%.*]], -11937; 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-canonicalization1941 %notx = xor i32 %x, -11942 %a = add i32 %y, %notx1943 %c = icmp ult i32 %y, %x1944 %r = select i1 %c, i32 %a, i32 -11945 ret i32 %r1946}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-canonicalization1957 %y = srem <2 x i32> <i32 12, i32 412>, %yp ; thwart complexity-based-canonicalization1958 %notx = xor <2 x i32> %x, <i32 -1, i32 -1>1959 %a = add <2 x i32> %y, %notx1960 %c = icmp ugt <2 x i32> %x, %y1961 %r = select <2 x i1> %c, <2 x i32> %a, <2 x i32> <i32 -1, i32 -1>1962 ret <2 x i32> %r1963}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:%.*]], -11968; 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, -11972 %a = add i32 %notx, %y1973 %c = icmp ugt i32 %x, %y1974 %r = select i1 %c, i32 %a, i32 -11975 ret i32 %r1976}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:%.*]], -11981; 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, -11985 %a = add i32 %notx, %y1986 %c = icmp uge i32 %x, %y1987 %r = select i1 %c, i32 %a, i32 -11988 ret i32 %r1989}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, 421997 %c = icmp ugt i32 %x, -431998 %r = select i1 %c, i32 -1, i32 %a1999 ret i32 %r2000}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, 422008 %c = icmp ult i32 %x, -432009 %r = select i1 %c, i32 %a, i32 -12010 ret i32 %r2011}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, %y2019 %c = icmp ult i32 %a, %x2020 %r = select i1 %c, i32 -1, i32 %a2021 ret i32 %r2022}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, %y2030 %c = icmp ult i32 %a, %y2031 %r = select i1 %c, i32 -1, i32 %a2032 ret i32 %r2033}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, %y2041 %c = icmp ult i32 %a, %x2042 %r = select i1 %c, i32 -1, i32 %a2043 ret i32 %r2044}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, %y2052 %c = icmp ult i32 %a, %y2053 %r = select i1 %c, i32 -1, i32 %a2054 ret i32 %r2055}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> %a2065 ret <4 x i32> %r2066}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> %r2077}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> %r2088}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 canonicalization2100 %noty = xor i32 %y, -12101 %c = icmp ult i32 %x, %noty2102 %s = select i1 %c, i32 %x, i32 %noty2103 %r = add i32 %s, %y2104 ret i32 %r2105}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 canonicalization2114 %noty = xor i32 %y, -12115 %c = icmp ult i32 %x, %noty2116 %s = select i1 %c, i32 %x, i32 %noty2117 %r = add i32 %y, %s2118 ret i32 %r2119}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 canonicalization2128 %noty = xor <2 x i8> %y, <i8 -1, i8 -1>2129 %c = icmp ult <2 x i8> %noty, %x2130 %s = select <2 x i1> %c, <2 x i8> %noty, <2 x i8> %x2131 %r = add <2 x i8> %s, %y2132 ret <2 x i8> %r2133}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 canonicalization2142 %noty = xor <2 x i8> %y, <i8 -1, i8 -1>2143 %c = icmp ult <2 x i8> %noty, %x2144 %s = select <2 x i1> %c, <2 x i8> %noty, <2 x i8> %x2145 %r = add <2 x i8> %y, %s2146 ret <2 x i8> %r2147}2148 2149; Negative test2150 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]], -12155; 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 canonicalization2160 %noty = xor i32 %y, -12161 %c = icmp slt i32 %x, %noty2162 %s = select i1 %c, i32 %x, i32 %noty2163 %r = add i32 %y, %s2164 ret i32 %r2165}2166 2167; Negative test2168 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]], -12173; 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 canonicalization2178 %noty = xor i32 %y, -12179 %c = icmp ult i32 %x, %noty2180 %s = select i1 %c, i32 %x, i32 %noty2181 %r = add i32 %z, %s2182 ret i32 %r2183}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, 422193 %s = select i1 %c, i32 %x, i32 422194 %r = add i32 %s, -432195 ret i32 %r2196}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> %r2207}2208 2209; Negative test2210 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]], -422215; CHECK-NEXT: ret i32 [[R]]2216;2217 %c = icmp ult i32 %x, 422218 %s = select i1 %c, i32 %x, i32 422219 %r = add i32 %s, -422220 ret i32 %r2221}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, %y2229 %c = icmp ult i32 %a, %y2230 %r = select i1 %c, i32 -1, i32 %a2231 ret i32 %r2232}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 -12239; CHECK-NEXT: ret i32 [[R]]2240;2241 %a = add i32 %x, %y2242 %c = icmp ule i32 %a, %y2243 %r = select i1 %c, i32 -1, i32 %a2244 ret i32 %r2245}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, %y2253 %c = icmp uge i32 %a, %y2254 %r = select i1 %c, i32 %a, i32 -12255 ret i32 %r2256}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 -12263; CHECK-NEXT: ret i32 [[R]]2264;2265 %a = add i32 %x, %y2266 %c = icmp ugt i32 %a, %y2267 %r = select i1 %c, i32 %a, i32 -12268 ret i32 %r2269}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, %y2277 %c = icmp ugt i32 %y, %a2278 %r = select i1 %c, i32 -1, i32 %a2279 ret i32 %r2280}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 -12287; CHECK-NEXT: ret i32 [[R]]2288;2289 %a = add i32 %x, %y2290 %c = icmp uge i32 %y, %a2291 %r = select i1 %c, i32 -1, i32 %a2292 ret i32 %r2293}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, %y2301 %c = icmp ule i32 %y, %a2302 %r = select i1 %c, i32 %a, i32 -12303 ret i32 %r2304}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 -12311; CHECK-NEXT: ret i32 [[R]]2312;2313 %a = add i32 %x, %y2314 %c = icmp ult i32 %y, %a2315 %r = select i1 %c, i32 %a, i32 -12316 ret i32 %r2317}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, -102326 ret i8 %sel2327}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]], -112333; CHECK-NEXT: ret i8 [[SEL]]2334;2335 %umax = call i8 @llvm.umax.i8(i8 %a, i8 10)2336 %sel = add i8 %umax, -112337 ret i8 %sel2338}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]], -102345; 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, -102350 ret i8 %sel2351}2352 2353declare void @usei8(i8)2354 2355define i8 @sadd_sat_uge_int_max(i8 %x, i8 %y) {2356; CHECK-LABEL: @sadd_sat_uge_int_max(2357; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1272358; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y:%.*]]2359; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2360; CHECK-NEXT: ret i8 [[R]]2361;2362 %cmp = icmp sge i8 %x, 1272363 %add = add i8 %x, %y2364 %r = select i1 %cmp, i8 127, i8 %add2365 ret i8 %r2366}2367 2368define i8 @sadd_sat_ugt_int_max(i8 %x, i8 %y) {2369; CHECK-LABEL: @sadd_sat_ugt_int_max(2370; CHECK-NEXT: [[R:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]2371; CHECK-NEXT: ret i8 [[R]]2372;2373 %cmp = icmp sgt i8 %x, 1272374 %add = add i8 %x, %y2375 %r = select i1 %cmp, i8 127, i8 %add2376 ret i8 %r2377}2378 2379define i8 @sadd_sat_eq_int_max(i8 %x) {2380; CHECK-LABEL: @sadd_sat_eq_int_max(2381; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 1)2382; CHECK-NEXT: ret i8 [[R]]2383;2384 %cmp = icmp eq i8 %x, 1272385 %add = add i8 %x, 12386 %r = select i1 %cmp, i8 127, i8 %add2387 ret i8 %r2388}2389 2390define i8 @sadd_sat_constant(i8 %x) {2391; CHECK-LABEL: @sadd_sat_constant(2392; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 10)2393; CHECK-NEXT: ret i8 [[R]]2394;2395 %cmp = icmp sge i8 %x, 1182396 %add = add i8 %x, 102397 %r = select i1 %cmp, i8 127, i8 %add2398 ret i8 %r2399}2400 2401define i8 @sadd_sat_negative_no_fold(i8 %x, i8 %y) {2402; CHECK-LABEL: @sadd_sat_negative_no_fold(2403; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1272404; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y:%.*]]2405; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2406; CHECK-NEXT: ret i8 [[R]]2407;2408 %cmp = icmp sge i8 %x, 1272409 %add = add i8 %x, %y2410 %r = select i1 %cmp, i8 127, i8 %add2411 ret i8 %r2412}2413 2414define i8 @sadd_sat_wrong_predicate(i8 %x, i8 %y) {2415; CHECK-LABEL: @sadd_sat_wrong_predicate(2416; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i8 [[X:%.*]], 1272417; CHECK-NEXT: [[ADD:%.*]] = add i8 [[Y:%.*]], 1272418; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP_NOT]], i8 [[ADD]], i8 1272419; CHECK-NEXT: ret i8 [[R]]2420;2421 %cmp = icmp slt i8 %x, 1272422 %add = add i8 %x, %y2423 %r = select i1 %cmp, i8 127, i8 %add2424 ret i8 %r2425}2426 2427define i8 @sadd_sat_wrong_constant(i8 %x, i8 %y) {2428; CHECK-LABEL: @sadd_sat_wrong_constant(2429; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], 1252430; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y:%.*]]2431; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2432; CHECK-NEXT: ret i8 [[R]]2433;2434 %cmp = icmp sge i8 %x, 1262435 %add = add i8 %x, %y2436 %r = select i1 %cmp, i8 127, i8 %add2437 ret i8 %r2438}2439 2440define <2 x i8> @sadd_sat_vector(<2 x i8> %x, <2 x i8> %y) {2441; CHECK-LABEL: @sadd_sat_vector(2442; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[X:%.*]], splat (i8 127)2443; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], [[Y:%.*]]2444; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i8> splat (i8 127), <2 x i8> [[ADD]]2445; CHECK-NEXT: ret <2 x i8> [[R]]2446;2447 %cmp = icmp sge <2 x i8> %x, <i8 127, i8 127>2448 %add = add <2 x i8> %x, %y2449 %r = select <2 x i1> %cmp, <2 x i8> <i8 127, i8 127>, <2 x i8> %add2450 ret <2 x i8> %r2451}2452 2453define <2 x i8> @sadd_sat_vector_constant(<2 x i8> %x) {2454; CHECK-LABEL: @sadd_sat_vector_constant(2455; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.smin.v2i8(<2 x i8> [[X:%.*]], <2 x i8> <i8 117, i8 107>)2456; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[TMP1]], <i8 10, i8 20>2457; CHECK-NEXT: ret <2 x i8> [[R]]2458;2459 %cmp = icmp sge <2 x i8> %x, <i8 118, i8 108>2460 %add = add <2 x i8> %x, <i8 10, i8 20>2461 %r = select <2 x i1> %cmp, <2 x i8> <i8 127, i8 127>, <2 x i8> %add2462 ret <2 x i8> %r2463}2464 2465define i8 @sadd_sat_int_max_minus_x(i8 %x, i8 %y) {2466; CHECK-LABEL: @sadd_sat_int_max_minus_x(2467; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2468; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SUB]], [[Y:%.*]]2469; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2470; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2471; CHECK-NEXT: ret i8 [[R]]2472;2473 %sub = sub i8 127, %x2474 %cmp = icmp slt i8 %sub, %y2475 %add = add i8 %x, %y2476 %r = select i1 %cmp, i8 127, i8 %add2477 ret i8 %r2478}2479 2480define i8 @sadd_sat_int_max_minus_x_commuted(i8 %x, i8 %y) {2481; CHECK-LABEL: @sadd_sat_int_max_minus_x_commuted(2482; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2483; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[Y:%.*]], [[SUB]]2484; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2485; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2486; CHECK-NEXT: ret i8 [[R]]2487;2488 %sub = sub i8 127, %x2489 %cmp = icmp sgt i8 %y, %sub2490 %add = add i8 %x, %y2491 %r = select i1 %cmp, i8 127, i8 %add2492 ret i8 %r2493}2494 2495define i8 @sadd_sat_int_max_minus_x_nonstrict(i8 %x, i8 %y) {2496; CHECK-LABEL: @sadd_sat_int_max_minus_x_nonstrict(2497; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2498; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i8 [[SUB]], [[Y:%.*]]2499; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2500; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP_NOT]], i8 [[ADD]], i8 1272501; CHECK-NEXT: ret i8 [[R]]2502;2503 %sub = sub i8 127, %x2504 %cmp = icmp sle i8 %sub, %y2505 %add = add i8 %x, %y2506 %r = select i1 %cmp, i8 127, i8 %add2507 ret i8 %r2508}2509 2510define i8 @sadd_sat_int_max_minus_x_commuted_nonstrict(i8 %x, i8 %y) {2511; CHECK-LABEL: @sadd_sat_int_max_minus_x_commuted_nonstrict(2512; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2513; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp slt i8 [[Y:%.*]], [[SUB]]2514; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2515; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP_NOT]], i8 [[ADD]], i8 1272516; CHECK-NEXT: ret i8 [[R]]2517;2518 %sub = sub i8 127, %x2519 %cmp = icmp sge i8 %y, %sub2520 %add = add i8 %x, %y2521 %r = select i1 %cmp, i8 127, i8 %add2522 ret i8 %r2523}2524 2525define i8 @sadd_sat_int_max_minus_x_wrong_constant(i8 %x, i8 %y) {2526; CHECK-LABEL: @sadd_sat_int_max_minus_x_wrong_constant(2527; CHECK-NEXT: [[SUB:%.*]] = sub i8 126, [[X:%.*]]2528; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SUB]], [[Y:%.*]]2529; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2530; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2531; CHECK-NEXT: ret i8 [[R]]2532;2533 %sub = sub i8 126, %x2534 %cmp = icmp slt i8 %sub, %y2535 %add = add i8 %x, %y2536 %r = select i1 %cmp, i8 127, i8 %add2537 ret i8 %r2538}2539 2540define i8 @sadd_sat_int_max_minus_x_wrong_predicate(i8 %x, i8 %y) {2541; CHECK-LABEL: @sadd_sat_int_max_minus_x_wrong_predicate(2542; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2543; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[SUB]], [[Y:%.*]]2544; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2545; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2546; CHECK-NEXT: ret i8 [[R]]2547;2548 %sub = sub i8 127, %x2549 %cmp = icmp sgt i8 %sub, %y2550 %add = add i8 %x, %y2551 %r = select i1 %cmp, i8 127, i8 %add2552 ret i8 %r2553}2554 2555define <2 x i8> @sadd_sat_int_max_minus_x_vector(<2 x i8> %x, <2 x i8> %y) {2556; CHECK-LABEL: @sadd_sat_int_max_minus_x_vector(2557; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> splat (i8 127), [[X:%.*]]2558; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[SUB]], [[Y:%.*]]2559; CHECK-NEXT: [[ADD:%.*]] = add <2 x i8> [[X]], [[Y]]2560; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP]], <2 x i8> splat (i8 127), <2 x i8> [[ADD]]2561; CHECK-NEXT: ret <2 x i8> [[R]]2562;2563 %sub = sub <2 x i8> <i8 127, i8 127>, %x2564 %cmp = icmp slt <2 x i8> %sub, %y2565 %add = add <2 x i8> %x, %y2566 %r = select <2 x i1> %cmp, <2 x i8> <i8 127, i8 127>, <2 x i8> %add2567 ret <2 x i8> %r2568}2569 2570define i8 @sadd_sat_commuted_select(i8 %x, i8 %y) {2571; CHECK-LABEL: @sadd_sat_commuted_select(2572; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1272573; CHECK-NEXT: [[ADD:%.*]] = add i8 [[Y:%.*]], 1272574; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 [[ADD]], i8 1272575; CHECK-NEXT: ret i8 [[R]]2576;2577 %cmp = icmp sge i8 %x, 1272578 %add = add i8 %x, %y2579 %r = select i1 %cmp, i8 %add, i8 1272580 ret i8 %r2581}2582 2583define i8 @sadd_sat_commuted_add(i8 %x, i8 %y) {2584; CHECK-LABEL: @sadd_sat_commuted_add(2585; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1272586; CHECK-NEXT: [[ADD:%.*]] = add i8 [[Y:%.*]], [[X]]2587; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2588; CHECK-NEXT: ret i8 [[R]]2589;2590 %cmp = icmp sge i8 %x, 1272591 %add = add i8 %y, %x2592 %r = select i1 %cmp, i8 127, i8 %add2593 ret i8 %r2594}2595 2596define i8 @sadd_sat_commuted_both(i8 %x, i8 %y) {2597; CHECK-LABEL: @sadd_sat_commuted_both(2598; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[X:%.*]], 1272599; CHECK-NEXT: [[ADD:%.*]] = add i8 [[Y:%.*]], 1272600; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 [[ADD]], i8 1272601; CHECK-NEXT: ret i8 [[R]]2602;2603 %cmp = icmp sge i8 %x, 1272604 %add = add i8 %y, %x2605 %r = select i1 %cmp, i8 %add, i8 1272606 ret i8 %r2607}2608 2609define i8 @sadd_sat_int_max_minus_x_nsw_slt(i8 %x, i8 %y) {2610; CHECK-LABEL: @sadd_sat_int_max_minus_x_nsw_slt(2611; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])2612; CHECK-NEXT: ret i8 [[R]]2613;2614 %sub = sub nsw i8 127, %x2615 %cmp = icmp slt i8 %sub, %y2616 %add = add i8 %x, %y2617 %r = select i1 %cmp, i8 127, i8 %add2618 ret i8 %r2619}2620 2621define i8 @sadd_sat_int_max_minus_x_nsw_sge_commuted(i8 %x, i8 %y) {2622; CHECK-LABEL: @sadd_sat_int_max_minus_x_nsw_sge_commuted(2623; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[X:%.*]], i8 [[Y:%.*]])2624; CHECK-NEXT: ret i8 [[R]]2625;2626 %sub = sub nsw i8 127, %x2627 %cmp = icmp sge i8 %y, %sub2628 %add = add i8 %x, %y2629 %r = select i1 %cmp, i8 127, i8 %add2630 ret i8 %r2631}2632 2633define i8 @sadd_sat_int_max_minus_x_no_nsw_neg(i8 %x, i8 %y) {2634; CHECK-LABEL: @sadd_sat_int_max_minus_x_no_nsw_neg(2635; CHECK-NEXT: [[SUB:%.*]] = sub i8 127, [[X:%.*]]2636; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[SUB]], [[Y:%.*]]2637; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X]], [[Y]]2638; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i8 127, i8 [[ADD]]2639; CHECK-NEXT: ret i8 [[R]]2640;2641 %sub = sub i8 127, %x2642 %cmp = icmp slt i8 %sub, %y2643 %add = add i8 %x, %y2644 %r = select i1 %cmp, i8 127, i8 %add2645 ret i8 %r2646}2647 2648define i8 @neg_no_nsw(i8 %x, i8 %y) {2649; CHECK-LABEL: @neg_no_nsw(2650; CHECK-NEXT: [[ADD:%.*]] = sub i8 127, [[Y:%.*]]2651; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], [[ADD]]2652; CHECK-NEXT: [[D:%.*]] = add i8 [[X]], [[Y]]2653; CHECK-NEXT: [[S:%.*]] = select i1 [[CMP]], i8 127, i8 [[D]]2654; CHECK-NEXT: ret i8 [[S]]2655;2656 %add = sub i8 127, %y2657 %cmp = icmp sgt i8 %x, %add2658 %d = add i8 %x, %y2659 %s = select i1 %cmp, i8 127, i8 %d2660 ret i8 %s2661}2662 2663define i8 @neg_neg_constant(i8 %x, i8 %y) {2664; CHECK-LABEL: @neg_neg_constant(2665; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[X:%.*]], i8 -1)2666; CHECK-NEXT: [[S:%.*]] = and i8 [[TMP1]], 1272667; CHECK-NEXT: ret i8 [[S]]2668;2669 %cmp = icmp sgt i8 %x, -22670 %d = add i8 %x, -1282671 %s = select i1 %cmp, i8 127, i8 %d2672 ret i8 %s2673}2674 2675; Make sure we don't crash in this case.2676define i32 @pr153053_strict_pred_with_nonconstant_rhs(i32 %x, i32 %y) {2677; CHECK-LABEL: @pr153053_strict_pred_with_nonconstant_rhs(2678; CHECK-NEXT: entry:2679; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]2680; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], 12681; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP]], i32 [[ADD]], i32 21474836472682; CHECK-NEXT: ret i32 [[RES]]2683;2684entry:2685 %cmp = icmp slt i32 %x, %y2686 %add = add i32 %x, 12687 %res = select i1 %cmp, i32 %add, i32 21474836472688 ret i32 %res2689}2690