brintos

brintos / llvm-project-archived public Read only

0
0
Text · 40.0 KiB · fa81040 Raw
1067 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4declare { i8, i1 } @llvm.uadd.with.overflow.i8(i8, i8) nounwind readnone5declare { i8, i1 } @llvm.sadd.with.overflow.i8(i8, i8) nounwind readnone6declare { i8, i1 } @llvm.usub.with.overflow.i8(i8, i8) nounwind readnone7declare { i8, i1 } @llvm.ssub.with.overflow.i8(i8, i8) nounwind readnone8declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone9declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone10declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) nounwind readnone11declare { i32, i1 } @llvm.uadd.with.overflow.i32(i32, i32) nounwind readnone12declare { i32, i1 } @llvm.ssub.with.overflow.i32(i32, i32) nounwind readnone13declare { i32, i1 } @llvm.usub.with.overflow.i32(i32, i32) nounwind readnone14declare { i32, i1 } @llvm.smul.with.overflow.i32(i32, i32) nounwind readnone15declare { i32, i1 } @llvm.umul.with.overflow.i32(i32, i32) nounwind readnone16 17define i8 @uaddtest1(i8 %A, i8 %B) {18; CHECK-LABEL: @uaddtest1(19; CHECK-NEXT:    [[Y:%.*]] = add i8 [[A:%.*]], [[B:%.*]]20; CHECK-NEXT:    ret i8 [[Y]]21;22  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)23  %y = extractvalue { i8, i1 } %x, 024  ret i8 %y25}26 27define i8 @uaddtest2(i8 %A, i8 %B, ptr %overflowPtr) {28; CHECK-LABEL: @uaddtest2(29; CHECK-NEXT:    [[AND_A:%.*]] = and i8 [[A:%.*]], 12730; CHECK-NEXT:    [[AND_B:%.*]] = and i8 [[B:%.*]], 12731; CHECK-NEXT:    [[X:%.*]] = add nuw i8 [[AND_A]], [[AND_B]]32; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 133; CHECK-NEXT:    ret i8 [[X]]34;35  %and.A = and i8 %A, 12736  %and.B = and i8 %B, 12737  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %and.A, i8 %and.B)38  %y = extractvalue { i8, i1 } %x, 039  %z = extractvalue { i8, i1 } %x, 140  store i1 %z, ptr %overflowPtr41  ret i8 %y42}43 44define i8 @uaddtest3(i8 %A, i8 %B, ptr %overflowPtr) {45; CHECK-LABEL: @uaddtest3(46; CHECK-NEXT:    [[OR_A:%.*]] = or i8 [[A:%.*]], -12847; CHECK-NEXT:    [[OR_B:%.*]] = or i8 [[B:%.*]], -12848; CHECK-NEXT:    [[X:%.*]] = add i8 [[OR_A]], [[OR_B]]49; CHECK-NEXT:    store i1 true, ptr [[OVERFLOWPTR:%.*]], align 150; CHECK-NEXT:    ret i8 [[X]]51;52  %or.A = or i8 %A, -12853  %or.B = or i8 %B, -12854  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %or.A, i8 %or.B)55  %y = extractvalue { i8, i1 } %x, 056  %z = extractvalue { i8, i1 } %x, 157  store i1 %z, ptr %overflowPtr58  ret i8 %y59}60 61define i8 @uaddtest4(i8 %A, ptr %overflowPtr) {62; CHECK-LABEL: @uaddtest4(63; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 164; CHECK-NEXT:    ret i8 -165;66  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 undef, i8 %A)67  %y = extractvalue { i8, i1 } %x, 068  %z = extractvalue { i8, i1 } %x, 169  store i1 %z, ptr %overflowPtr70  ret i8 %y71}72 73define i8 @uaddtest5(i8 %A, ptr %overflowPtr) {74; CHECK-LABEL: @uaddtest5(75; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 176; CHECK-NEXT:    ret i8 [[A:%.*]]77;78  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 0, i8 %A)79  %y = extractvalue { i8, i1 } %x, 080  %z = extractvalue { i8, i1 } %x, 181  store i1 %z, ptr %overflowPtr82  ret i8 %y83}84 85define i1 @uaddtest6(i8 %A, i8 %B) {86; CHECK-LABEL: @uaddtest6(87; CHECK-NEXT:    [[Z:%.*]] = icmp ugt i8 [[A:%.*]], 388; CHECK-NEXT:    ret i1 [[Z]]89;90  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 -4)91  %z = extractvalue { i8, i1 } %x, 192  ret i1 %z93}94 95define i8 @uaddtest7(i8 %A, i8 %B) {96; CHECK-LABEL: @uaddtest7(97; CHECK-NEXT:    [[Z:%.*]] = add i8 [[A:%.*]], [[B:%.*]]98; CHECK-NEXT:    ret i8 [[Z]]99;100  %x = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %A, i8 %B)101  %z = extractvalue { i8, i1 } %x, 0102  ret i8 %z103}104 105; PR20194106define { i32, i1 } @saddtest_nsw(i8 %a, i8 %b) {107; CHECK-LABEL: @saddtest_nsw(108; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32109; CHECK-NEXT:    [[BB:%.*]] = sext i8 [[B:%.*]] to i32110; CHECK-NEXT:    [[X:%.*]] = add nsw i32 [[AA]], [[BB]]111; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0112; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]113;114  %aa = sext i8 %a to i32115  %bb = sext i8 %b to i32116  %x = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %aa, i32 %bb)117  ret { i32, i1 } %x118}119 120define { i32, i1 } @uaddtest_nuw(i32 %a, i32 %b) {121; CHECK-LABEL: @uaddtest_nuw(122; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 2147483647123; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 2147483647124; CHECK-NEXT:    [[X:%.*]] = add nuw i32 [[AA]], [[BB]]125; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0126; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]127;128  %aa = and i32 %a, 2147483647129  %bb = and i32 %b, 2147483647130  %x = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %aa, i32 %bb)131  ret { i32, i1 } %x132}133 134define { i32, i1 } @ssubtest_nsw(i8 %a, i8 %b) {135; CHECK-LABEL: @ssubtest_nsw(136; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32137; CHECK-NEXT:    [[BB:%.*]] = sext i8 [[B:%.*]] to i32138; CHECK-NEXT:    [[X:%.*]] = sub nsw i32 [[AA]], [[BB]]139; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0140; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]141;142  %aa = sext i8 %a to i32143  %bb = sext i8 %b to i32144  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %aa, i32 %bb)145  ret { i32, i1 } %x146}147 148define { i32, i1 } @usubtest_nuw(i32 %a, i32 %b) {149; CHECK-LABEL: @usubtest_nuw(150; CHECK-NEXT:    [[AA:%.*]] = or i32 [[A:%.*]], -2147483648151; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 2147483647152; CHECK-NEXT:    [[X:%.*]] = sub nuw i32 [[AA]], [[BB]]153; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0154; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]155;156  %aa = or i32 %a, 2147483648157  %bb = and i32 %b, 2147483647158  %x = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 %aa, i32 %bb)159  ret { i32, i1 } %x160}161 162define { i32, i1 } @smultest1_nsw(i32 %a, i32 %b) {163; CHECK-LABEL: @smultest1_nsw(164; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 4095165; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 524287166; CHECK-NEXT:    [[X:%.*]] = mul nuw nsw i32 [[AA]], [[BB]]167; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0168; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]169;170  %aa = and i32 %a, 4095 ; 0xfff171  %bb = and i32 %b, 524287; 0x7ffff172  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)173  ret { i32, i1 } %x174}175 176define { i32, i1 } @smultest2_nsw(i32 %a, i32 %b) {177; CHECK-LABEL: @smultest2_nsw(178; CHECK-NEXT:    [[AA:%.*]] = ashr i32 [[A:%.*]], 16179; CHECK-NEXT:    [[BB:%.*]] = ashr i32 [[B:%.*]], 16180; CHECK-NEXT:    [[X:%.*]] = mul nsw i32 [[AA]], [[BB]]181; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0182; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]183;184  %aa = ashr i32 %a, 16185  %bb = ashr i32 %b, 16186  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)187  ret { i32, i1 } %x188}189 190define { i32, i1 } @smultest3_sw(i32 %a, i32 %b) {191; CHECK-LABEL: @smultest3_sw(192; CHECK-NEXT:    [[AA:%.*]] = ashr i32 [[A:%.*]], 16193; CHECK-NEXT:    [[BB:%.*]] = ashr i32 [[B:%.*]], 15194; CHECK-NEXT:    [[X:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[AA]], i32 [[BB]])195; CHECK-NEXT:    ret { i32, i1 } [[X]]196;197  %aa = ashr i32 %a, 16198  %bb = ashr i32 %b, 15199  %x = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %aa, i32 %bb)200  ret { i32, i1 } %x201}202 203define { i32, i1 } @umultest_nuw(i32 %a, i32 %b) {204; CHECK-LABEL: @umultest_nuw(205; CHECK-NEXT:    [[AA:%.*]] = and i32 [[A:%.*]], 65535206; CHECK-NEXT:    [[BB:%.*]] = and i32 [[B:%.*]], 65535207; CHECK-NEXT:    [[X:%.*]] = mul nuw i32 [[AA]], [[BB]]208; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0209; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]210;211  %aa = and i32 %a, 65535 ; 0xffff212  %bb = and i32 %b, 65535 ; 0xffff213  %x = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %aa, i32 %bb)214  ret { i32, i1 } %x215}216 217define i8 @umultest1(i8 %A, ptr %overflowPtr) {218; CHECK-LABEL: @umultest1(219; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1220; CHECK-NEXT:    ret i8 0221;222  %x = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 0, i8 %A)223  %y = extractvalue { i8, i1 } %x, 0224  %z = extractvalue { i8, i1 } %x, 1225  store i1 %z, ptr %overflowPtr226  ret i8 %y227}228 229define i8 @umultest2(i8 %A, ptr %overflowPtr) {230; CHECK-LABEL: @umultest2(231; CHECK-NEXT:    store i1 false, ptr [[OVERFLOWPTR:%.*]], align 1232; CHECK-NEXT:    ret i8 [[A:%.*]]233;234  %x = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 1, i8 %A)235  %y = extractvalue { i8, i1 } %x, 0236  %z = extractvalue { i8, i1 } %x, 1237  store i1 %z, ptr %overflowPtr238  ret i8 %y239}240 241define i32 @umultest3(i32 %n) nounwind {242; CHECK-LABEL: @umultest3(243; CHECK-NEXT:    [[SHR:%.*]] = lshr i32 [[N:%.*]], 2244; CHECK-NEXT:    [[MUL:%.*]] = mul nuw i32 [[SHR]], 3245; CHECK-NEXT:    ret i32 [[MUL]]246;247  %shr = lshr i32 %n, 2248  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %shr, i32 3)249  %ov = extractvalue { i32, i1 } %mul, 1250  %res = extractvalue { i32, i1 } %mul, 0251  %ret = select i1 %ov, i32 -1, i32 %res252  ret i32 %ret253}254 255define i32 @umultest4(i32 %n) nounwind {256; CHECK-LABEL: @umultest4(257; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[N:%.*]], 1258; CHECK-NEXT:    [[RES:%.*]] = and i32 [[TMP1]], -4259; CHECK-NEXT:    [[OV_INV:%.*]] = icmp sgt i32 [[N]], -1260; CHECK-NEXT:    [[RET:%.*]] = select i1 [[OV_INV]], i32 [[RES]], i32 -1261; CHECK-NEXT:    ret i32 [[RET]]262;263  %shr = lshr i32 %n, 1264  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %shr, i32 4)265  %ov = extractvalue { i32, i1 } %mul, 1266  %res = extractvalue { i32, i1 } %mul, 0267  %ret = select i1 %ov, i32 -1, i32 %res268  ret i32 %ret269}270 271define { i32, i1 } @umultest5(i32 %x, i32 %y) nounwind {272; CHECK-LABEL: @umultest5(273; CHECK-NEXT:    [[OR_X:%.*]] = or i32 [[X:%.*]], -2147483648274; CHECK-NEXT:    [[OR_Y:%.*]] = or i32 [[Y:%.*]], -2147483648275; CHECK-NEXT:    [[MUL:%.*]] = mul i32 [[OR_X]], [[OR_Y]]276; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 true }, i32 [[MUL]], 0277; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]278;279  %or_x = or i32 %x, 2147483648280  %or_y = or i32 %y, 2147483648281  %mul = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %or_x, i32 %or_y)282  ret { i32, i1 } %mul283}284 285define i1 @overflow_div_add(i32 %v1, i32 %v2) nounwind {286; CHECK-LABEL: @overflow_div_add(287; CHECK-NEXT:    ret i1 false288;289  %div = sdiv i32 %v1, 2290  %t = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %div, i32 1)291  %obit = extractvalue { i32, i1 } %t, 1292  ret i1 %obit293}294 295define i1 @overflow_div_sub(i32 %v1, i32 %v2) nounwind {296  ; Check cases where the known sign bits are larger than the word size.297; CHECK-LABEL: @overflow_div_sub(298; CHECK-NEXT:    ret i1 false299;300  %a = ashr i32 %v1, 18301  %div = sdiv i32 %a, 65536302  %t = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %div, i32 1)303  %obit = extractvalue { i32, i1 } %t, 1304  ret i1 %obit305}306 307define i1 @overflow_mod_mul(i32 %v1, i32 %v2) nounwind {308; CHECK-LABEL: @overflow_mod_mul(309; CHECK-NEXT:    ret i1 false310;311  %rem = srem i32 %v1, 1000312  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)313  %obit = extractvalue { i32, i1 } %t, 1314  ret i1 %obit315}316 317define i1 @overflow_mod_overflow_mul(i32 %v1, i32 %v2) nounwind {318; CHECK-LABEL: @overflow_mod_overflow_mul(319; CHECK-NEXT:    [[REM:%.*]] = srem i32 [[V1:%.*]], 65537320; CHECK-NEXT:    [[T:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[REM]], i32 [[REM]])321; CHECK-NEXT:    [[OBIT:%.*]] = extractvalue { i32, i1 } [[T]], 1322; CHECK-NEXT:    ret i1 [[OBIT]]323;324  %rem = srem i32 %v1, 65537325  ; This may overflow because the result of the mul operands may be greater than 16bits326  ; and the result greater than 32.327  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)328  %obit = extractvalue { i32, i1 } %t, 1329  ret i1 %obit330}331 332define i1 @overflow_mod_mul2(i16 %v1, i32 %v2) nounwind {333; CHECK-LABEL: @overflow_mod_mul2(334; CHECK-NEXT:    ret i1 false335;336  %a = sext i16 %v1 to i32337  %rem = srem i32 %a, %v2338  %t = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 %rem, i32 %rem)339  %obit = extractvalue { i32, i1 } %t, 1340  ret i1 %obit341}342 343define { i32, i1 } @ssubtest_reorder(i8 %a) {344; CHECK-LABEL: @ssubtest_reorder(345; CHECK-NEXT:    [[AA:%.*]] = sext i8 [[A:%.*]] to i32346; CHECK-NEXT:    [[X:%.*]] = sub nsw i32 0, [[AA]]347; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[X]], 0348; CHECK-NEXT:    ret { i32, i1 } [[TMP1]]349;350  %aa = sext i8 %a to i32351  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 0, i32 %aa)352  ret { i32, i1 } %x353}354 355define { i32, i1 } @never_overflows_ssub_test0(i32 %a) {356; CHECK-LABEL: @never_overflows_ssub_test0(357; CHECK-NEXT:    [[X:%.*]] = insertvalue { i32, i1 } { i32 poison, i1 false }, i32 [[A:%.*]], 0358; CHECK-NEXT:    ret { i32, i1 } [[X]]359;360  %x = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 %a, i32 0)361  ret { i32, i1 } %x362}363 364define i1 @uadd_res_ult_x(i32 %x, i32 %y, ptr %p) nounwind {365; CHECK-LABEL: @uadd_res_ult_x(366; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])367; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1368; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1369; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1370; CHECK-NEXT:    ret i1 [[D]]371;372  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)373  %b = extractvalue { i32, i1 } %a, 1374  store i1 %b, ptr %p375  %c = extractvalue { i32, i1 } %a, 0376  %d = icmp ult i32 %c, %x377  ret i1 %d378}379 380define i1 @uadd_res_ult_y(i32 %x, i32 %y, ptr %p) nounwind {381; CHECK-LABEL: @uadd_res_ult_y(382; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])383; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1384; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1385; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1386; CHECK-NEXT:    ret i1 [[D]]387;388  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)389  %b = extractvalue { i32, i1 } %a, 1390  store i1 %b, ptr %p391  %c = extractvalue { i32, i1 } %a, 0392  %d = icmp ult i32 %c, %y393  ret i1 %d394}395 396define i1 @uadd_res_ugt_x(i32 %xx, i32 %y, ptr %p) nounwind {397; CHECK-LABEL: @uadd_res_ugt_x(398; CHECK-NEXT:    [[X:%.*]] = urem i32 42, [[XX:%.*]]399; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X]], i32 [[Y:%.*]])400; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1401; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1402; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1403; CHECK-NEXT:    ret i1 [[D]]404;405  %x = urem i32 42, %xx ; Thwart complexity-based canonicalization406  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)407  %b = extractvalue { i32, i1 } %a, 1408  store i1 %b, ptr %p409  %c = extractvalue { i32, i1 } %a, 0410  %d = icmp ugt i32 %x, %c411  ret i1 %d412}413 414define i1 @uadd_res_ugt_y(i32 %x, i32 %yy, ptr %p) nounwind {415; CHECK-LABEL: @uadd_res_ugt_y(416; CHECK-NEXT:    [[Y:%.*]] = urem i32 42, [[YY:%.*]]417; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 [[Y]])418; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1419; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1420; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1421; CHECK-NEXT:    ret i1 [[D]]422;423  %y = urem i32 42, %yy ; Thwart complexity-based canonicalization424  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 %y)425  %b = extractvalue { i32, i1 } %a, 1426  store i1 %b, ptr %p427  %c = extractvalue { i32, i1 } %a, 0428  %d = icmp ugt i32 %y, %c429  ret i1 %d430}431 432define i1 @uadd_res_ult_const(i32 %x, ptr %p) nounwind {433; CHECK-LABEL: @uadd_res_ult_const(434; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 42)435; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1436; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1437; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1438; CHECK-NEXT:    ret i1 [[D]]439;440  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 42)441  %b = extractvalue { i32, i1 } %a, 1442  store i1 %b, ptr %p443  %c = extractvalue { i32, i1 } %a, 0444  %d = icmp ult i32 %c, 42445  ret i1 %d446}447 448define i1 @uadd_res_ult_const_one(i32 %x, ptr %p) nounwind {449; CHECK-LABEL: @uadd_res_ult_const_one(450; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1)451; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1452; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1453; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1454; CHECK-NEXT:    ret i1 [[D]]455;456  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 1)457  %b = extractvalue { i32, i1 } %a, 1458  store i1 %b, ptr %p459  %c = extractvalue { i32, i1 } %a, 0460  %d = icmp ult i32 %c, 1461  ret i1 %d462}463 464define i1 @uadd_res_ult_const_minus_one(i32 %x, ptr %p) nounwind {465; CHECK-LABEL: @uadd_res_ult_const_minus_one(466; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 -1)467; CHECK-NEXT:    [[B:%.*]] = extractvalue { i32, i1 } [[A]], 1468; CHECK-NEXT:    store i1 [[B]], ptr [[P:%.*]], align 1469; CHECK-NEXT:    [[D:%.*]] = extractvalue { i32, i1 } [[A]], 1470; CHECK-NEXT:    ret i1 [[D]]471;472  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 %x, i32 -1)473  %b = extractvalue { i32, i1 } %a, 1474  store i1 %b, ptr %p475  %c = extractvalue { i32, i1 } %a, 0476  %d = icmp ult i32 %c, -1477  ret i1 %d478}479 480define { i32, i1 } @sadd_canonicalize_constant_arg0(i32 %x) nounwind {481; CHECK-LABEL: @sadd_canonicalize_constant_arg0(482; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 [[X:%.*]], i32 42)483; CHECK-NEXT:    ret { i32, i1 } [[A]]484;485  %a = call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 42, i32 %x)486  ret { i32, i1 } %a487}488 489define { i32, i1 } @uadd_canonicalize_constant_arg0(i32 %x) nounwind {490; CHECK-LABEL: @uadd_canonicalize_constant_arg0(491; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 42)492; CHECK-NEXT:    ret { i32, i1 } [[A]]493;494  %a = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 42, i32 %x)495  ret { i32, i1 } %a496}497 498define { i32, i1 } @ssub_no_canonicalize_constant_arg0(i32 %x) nounwind {499; CHECK-LABEL: @ssub_no_canonicalize_constant_arg0(500; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 42, i32 [[X:%.*]])501; CHECK-NEXT:    ret { i32, i1 } [[A]]502;503  %a = call { i32, i1 } @llvm.ssub.with.overflow.i32(i32 42, i32 %x)504  ret { i32, i1 } %a505}506 507define { i32, i1 } @usub_no_canonicalize_constant_arg0(i32 %x) nounwind {508; CHECK-LABEL: @usub_no_canonicalize_constant_arg0(509; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 42, i32 [[X:%.*]])510; CHECK-NEXT:    ret { i32, i1 } [[A]]511;512  %a = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 42, i32 %x)513  ret { i32, i1 } %a514}515 516define { i32, i1 } @smul_canonicalize_constant_arg0(i32 %x) nounwind {517; CHECK-LABEL: @smul_canonicalize_constant_arg0(518; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 [[X:%.*]], i32 42)519; CHECK-NEXT:    ret { i32, i1 } [[A]]520;521  %a = call { i32, i1 } @llvm.smul.with.overflow.i32(i32 42, i32 %x)522  ret { i32, i1 } %a523}524 525define { i32, i1 } @umul_canonicalize_constant_arg0(i32 %x) nounwind {526; CHECK-LABEL: @umul_canonicalize_constant_arg0(527; CHECK-NEXT:    [[A:%.*]] = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 [[X:%.*]], i32 42)528; CHECK-NEXT:    ret { i32, i1 } [[A]]529;530  %a = call { i32, i1 } @llvm.umul.with.overflow.i32(i32 42, i32 %x)531  ret { i32, i1 } %a532}533 534; Always overflow tests535 536define { i8, i1 } @uadd_always_overflow(i8 %x) nounwind {537; CHECK-LABEL: @uadd_always_overflow(538; CHECK-NEXT:    [[A:%.*]] = and i8 [[X:%.*]], 63539; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0540; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]541;542  %y = or i8 %x, 192543  %a = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 %y, i8 64)544  ret { i8, i1 } %a545}546 547define { i8, i1 } @usub_always_overflow(i8 %x) nounwind {548; CHECK-LABEL: @usub_always_overflow(549; CHECK-NEXT:    [[Y:%.*]] = or i8 [[X:%.*]], 64550; CHECK-NEXT:    [[A:%.*]] = sub nsw i8 63, [[Y]]551; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0552; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]553;554  %y = or i8 %x, 64555  %a = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 63, i8 %y)556  ret { i8, i1 } %a557}558 559define { i8, i1 } @umul_always_overflow(i8 %x) nounwind {560; CHECK-LABEL: @umul_always_overflow(561; CHECK-NEXT:    [[A:%.*]] = shl i8 [[X:%.*]], 1562; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0563; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]564;565  %y = or i8 %x, 128566  %a = call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %y, i8 2)567  ret { i8, i1 } %a568}569 570define { i8, i1 } @sadd_always_overflow(i8 %x) nounwind {571; CHECK-LABEL: @sadd_always_overflow(572; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 100)573; CHECK-NEXT:    [[A:%.*]] = add nuw i8 [[Y]], 28574; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0575; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]576;577  %c = icmp sgt i8 %x, 100578  %y = select i1 %c, i8 %x, i8 100579  %a = call { i8, i1 } @llvm.sadd.with.overflow.i8(i8 %y, i8 28)580  ret { i8, i1 } %a581}582 583define { i8, i1 } @ssub_always_overflow(i8 %x) nounwind {584; CHECK-LABEL: @ssub_always_overflow(585; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 29)586; CHECK-NEXT:    [[A:%.*]] = sub nuw i8 -100, [[Y]]587; CHECK-NEXT:    [[TMP1:%.*]] = insertvalue { i8, i1 } { i8 poison, i1 true }, i8 [[A]], 0588; CHECK-NEXT:    ret { i8, i1 } [[TMP1]]589;590  %c = icmp sgt i8 %x, 29591  %y = select i1 %c, i8 %x, i8 29592  %a = call { i8, i1 } @llvm.ssub.with.overflow.i8(i8 -100, i8 %y)593  ret { i8, i1 } %a594}595 596define { i8, i1 } @smul_always_overflow(i8 %x) nounwind {597; CHECK-LABEL: @smul_always_overflow(598; CHECK-NEXT:    [[Y:%.*]] = call i8 @llvm.smax.i8(i8 [[X:%.*]], i8 100)599; CHECK-NEXT:    [[A:%.*]] = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[Y]], i8 2)600; CHECK-NEXT:    ret { i8, i1 } [[A]]601;602  %c = icmp sgt i8 %x, 100603  %y = select i1 %c, i8 %x, i8 100604  %a = call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %y, i8 2)605  ret { i8, i1 } %a606}607 608declare { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8>, <4 x i8>)609declare { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8>, <4 x i8>)610declare { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8>, <4 x i8>)611declare { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8>, <4 x i8>)612declare { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8>, <4 x i8>)613declare { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8>, <4 x i8>)614 615; Always overflow616 617define { <4 x i8>, <4 x i1> } @always_sadd_const_vector() nounwind {618; CHECK-LABEL: @always_sadd_const_vector(619; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -128), <4 x i1> splat (i1 true) }620;621  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)622  ret { <4 x i8>, <4 x i1> } %x623}624 625define { <4 x i8>, <4 x i1> } @always_uadd_const_vector() nounwind {626; CHECK-LABEL: @always_uadd_const_vector(627; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> zeroinitializer, <4 x i1> splat (i1 true) }628;629  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)630  ret { <4 x i8>, <4 x i1> } %x631}632 633define { <4 x i8>, <4 x i1> } @always_ssub_const_vector() nounwind {634; CHECK-LABEL: @always_ssub_const_vector(635; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 127), <4 x i1> splat (i1 true) }636;637  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 -128, i8 -128, i8 -128, i8 -128>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)638  ret { <4 x i8>, <4 x i1> } %x639}640 641define { <4 x i8>, <4 x i1> } @always_usub_const_vector() nounwind {642; CHECK-LABEL: @always_usub_const_vector(643; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -1), <4 x i1> splat (i1 true) }644;645  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 0, i8 0, i8 0, i8 0>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)646  ret { <4 x i8>, <4 x i1> } %x647}648 649; NOTE: LLVM doesn't (yet) detect the multiplication always results in a overflow650define { <4 x i8>, <4 x i1> } @always_smul_const_vector() nounwind {651; CHECK-LABEL: @always_smul_const_vector(652; CHECK-NEXT:    [[X:%.*]] = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> splat (i8 127), <4 x i8> splat (i8 3))653; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } [[X]]654;655  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 127, i8 127, i8 127, i8 127>, <4 x i8> <i8 3, i8 3, i8 3, i8 3>)656  ret { <4 x i8>, <4 x i1> } %x657}658 659define { <4 x i8>, <4 x i1> } @always_umul_const_vector() nounwind {660; CHECK-LABEL: @always_umul_const_vector(661; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> splat (i8 -3), <4 x i1> splat (i1 true) }662;663  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 3, i8 3, i8 3, i8 3>)664  ret { <4 x i8>, <4 x i1> } %x665}666 667; Never overflow668 669define { <4 x i8>, <4 x i1> } @never_sadd_const_vector() nounwind {670; CHECK-LABEL: @never_sadd_const_vector(671; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -50, i8 -10, i8 0, i8 60>, <4 x i1> zeroinitializer }672;673  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 -10, i8 -20, i8 30, i8 40>, <4 x i8> <i8 -40, i8 10, i8 -30, i8 20>)674  ret { <4 x i8>, <4 x i1> } %x675}676 677define { <4 x i8>, <4 x i1> } @never_uadd_const_vector() nounwind {678; CHECK-LABEL: @never_uadd_const_vector(679; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 32, i8 64, i8 96, i8 48>, <4 x i1> zeroinitializer }680;681  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 0, i8 32, i8 64, i8 16>, <4 x i8> <i8 32, i8 32, i8 32, i8 32>)682  ret { <4 x i8>, <4 x i1> } %x683}684 685define { <4 x i8>, <4 x i1> } @never_ssub_const_vector() nounwind {686; CHECK-LABEL: @never_ssub_const_vector(687; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 0, i8 10, i8 20, i8 30>, <4 x i1> zeroinitializer }688;689  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 -10, i8 -10, i8 -10, i8 -10>, <4 x i8> <i8 -10, i8 -20, i8 -30, i8 -40>)690  ret { <4 x i8>, <4 x i1> } %x691}692 693define { <4 x i8>, <4 x i1> } @never_usub_const_vector() nounwind {694; CHECK-LABEL: @never_usub_const_vector(695; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 127, i8 -1, i8 0, i8 -2>, <4 x i1> zeroinitializer }696;697  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 255, i8 255, i8 255, i8 255>, <4 x i8> <i8 128, i8 0, i8 255, i8 1>)698  ret { <4 x i8>, <4 x i1> } %x699}700 701define { <4 x i8>, <4 x i1> } @never_smul_const_vector() nounwind {702; CHECK-LABEL: @never_smul_const_vector(703; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -54, i8 -18, i8 -60, i8 -90>, <4 x i1> zeroinitializer }704;705  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 -6, i8 -6, i8 -6, i8 -6>, <4 x i8> <i8 9, i8 3, i8 10, i8 15>)706  ret { <4 x i8>, <4 x i1> } %x707}708 709define { <4 x i8>, <4 x i1> } @never_umul_const_vector() nounwind {710; CHECK-LABEL: @never_umul_const_vector(711; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 -31, i8 120, i8 60, i8 30>, <4 x i1> zeroinitializer }712;713  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 15, i8 15, i8 15, i8 15>, <4 x i8> <i8 15, i8 8, i8 4, i8 2>)714  ret { <4 x i8>, <4 x i1> } %x715}716 717; Neutral value718 719define { <4 x i8>, <4 x i1> } @neutral_sadd_const_vector() nounwind {720; CHECK-LABEL: @neutral_sadd_const_vector(721; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }722;723  %x = call { <4 x i8>, <4 x i1> } @llvm.sadd.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)724  ret { <4 x i8>, <4 x i1> } %x725}726 727define { <4 x i8>, <4 x i1> } @neutral_uadd_const_vector() nounwind {728; CHECK-LABEL: @neutral_uadd_const_vector(729; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }730;731  %x = call { <4 x i8>, <4 x i1> } @llvm.uadd.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)732  ret { <4 x i8>, <4 x i1> } %x733}734 735define { <4 x i8>, <4 x i1> } @neutral_ssub_const_vector() nounwind {736; CHECK-LABEL: @neutral_ssub_const_vector(737; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }738;739  %x = call { <4 x i8>, <4 x i1> } @llvm.ssub.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)740  ret { <4 x i8>, <4 x i1> } %x741}742 743define { <4 x i8>, <4 x i1> } @neutral_usub_const_vector() nounwind {744; CHECK-LABEL: @neutral_usub_const_vector(745; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }746;747  %x = call { <4 x i8>, <4 x i1> } @llvm.usub.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 0, i8 0, i8 0, i8 0>)748  ret { <4 x i8>, <4 x i1> } %x749}750 751define { <4 x i8>, <4 x i1> } @neutral_smul_const_vector() nounwind {752; CHECK-LABEL: @neutral_smul_const_vector(753; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }754;755  %x = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)756  ret { <4 x i8>, <4 x i1> } %x757}758 759define { <4 x i8>, <4 x i1> } @neutral_umul_const_vector() nounwind {760; CHECK-LABEL: @neutral_umul_const_vector(761; CHECK-NEXT:    ret { <4 x i8>, <4 x i1> } { <4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i1> zeroinitializer }762;763  %x = call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> <i8 1, i8 2, i8 3, i8 4>, <4 x i8> <i8 1, i8 1, i8 1, i8 1>)764  ret { <4 x i8>, <4 x i1> } %x765}766 767define i8 @smul_neg1(i8 %x, ptr %p) {768; CHECK-LABEL: @smul_neg1(769; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[X:%.*]]770; CHECK-NEXT:    [[OV:%.*]] = icmp eq i8 [[X]], -128771; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1772; CHECK-NEXT:    ret i8 [[R]]773;774  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 -1)775  %r = extractvalue { i8, i1 } %m, 0776  %ov = extractvalue { i8, i1 } %m, 1777  store i1 %ov, ptr %p778  ret i8 %r779}780 781define <4 x i8> @smul_neg1_vec(<4 x i8> %x, ptr %p) {782; CHECK-LABEL: @smul_neg1_vec(783; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]784; CHECK-NEXT:    [[OV:%.*]] = icmp eq <4 x i8> [[X]], splat (i8 -128)785; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1786; CHECK-NEXT:    ret <4 x i8> [[R]]787;788  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>)789  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0790  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1791  store <4 x i1> %ov, ptr %p792  ret <4 x i8> %r793}794 795define <4 x i8> @smul_neg1_vec_poison(<4 x i8> %x, ptr %p) {796; CHECK-LABEL: @smul_neg1_vec_poison(797; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]798; CHECK-NEXT:    [[OV:%.*]] = icmp eq <4 x i8> [[X]], splat (i8 -128)799; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1800; CHECK-NEXT:    ret <4 x i8> [[R]]801;802  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 poison, i8 -1>)803  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0804  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1805  store <4 x i1> %ov, ptr %p806  ret <4 x i8> %r807}808 809define i8 @smul_neg2(i8 %x, ptr %p) {810; CHECK-LABEL: @smul_neg2(811; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 -2)812; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 0813; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 1814; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1815; CHECK-NEXT:    ret i8 [[R]]816;817  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 -2)818  %r = extractvalue { i8, i1 } %m, 0819  %ov = extractvalue { i8, i1 } %m, 1820  store i1 %ov, ptr %p821  ret i8 %r822}823 824define i8 @umul_neg1(i8 %x, ptr %p) {825; CHECK-LABEL: @umul_neg1(826; CHECK-NEXT:    [[R:%.*]] = sub i8 0, [[X:%.*]]827; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 1828; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1829; CHECK-NEXT:    ret i8 [[R]]830;831  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 -1)832  %r = extractvalue { i8, i1 } %m, 0833  %ov = extractvalue { i8, i1 } %m, 1834  store i1 %ov, ptr %p835  ret i8 %r836}837 838define <4 x i8> @umul_neg1_vec(<4 x i8> %x, ptr %p) {839; CHECK-LABEL: @umul_neg1_vec(840; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]841; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 1)842; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1843; CHECK-NEXT:    ret <4 x i8> [[R]]844;845  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -1, i8 -1, i8 -1, i8 -1>)846  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0847  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1848  store <4 x i1> %ov, ptr %p849  ret <4 x i8> %r850}851 852define <4 x i8> @umul_neg1_vec_poison(<4 x i8> %x, ptr %p) {853; CHECK-LABEL: @umul_neg1_vec_poison(854; CHECK-NEXT:    [[R:%.*]] = sub <4 x i8> zeroinitializer, [[X:%.*]]855; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 1)856; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1857; CHECK-NEXT:    ret <4 x i8> [[R]]858;859  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 -1, i8 -1, i8 poison>)860  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0861  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1862  store <4 x i1> %ov, ptr %p863  ret <4 x i8> %r864}865 866define <4 x i1> @smul_not_neg1_vec(<4 x i8> %x) {867; CHECK-LABEL: @smul_not_neg1_vec(868; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i8> [[X:%.*]], splat (i8 -43)869; CHECK-NEXT:    [[OV:%.*]] = icmp ult <4 x i8> [[TMP1]], splat (i8 -85)870; CHECK-NEXT:    ret <4 x i1> [[OV]]871;872  %m = call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 -3, i8 -3, i8 poison, i8 -3>)873  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1874  ret <4 x i1> %ov875}876 877; issue #54053878 879define i8 @umul_neg1_select(i8 %x) {880; CHECK-LABEL: @umul_neg1_select(881; CHECK-NEXT:    [[TMP1:%.*]] = icmp ne i8 [[X:%.*]], 0882; CHECK-NEXT:    [[R:%.*]] = sext i1 [[TMP1]] to i8883; CHECK-NEXT:    ret i8 [[R]]884;885  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 -1)886  %m0 = extractvalue { i8, i1 } %m, 0887  %m1 = extractvalue { i8, i1 } %m, 1888  %r = select i1 %m1, i8 -1, i8 %m0889  ret i8 %r890}891 892define i8 @umul_2(i8 %x, ptr %p) {893; CHECK-LABEL: @umul_2(894; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 1895; CHECK-NEXT:    [[OV:%.*]] = icmp slt i8 [[X]], 0896; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1897; CHECK-NEXT:    ret i8 [[R]]898;899  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 2)900  %r = extractvalue { i8, i1 } %m, 0901  %ov = extractvalue { i8, i1 } %m, 1902  store i1 %ov, ptr %p903  ret i8 %r904}905 906define i8 @umul_8(i8 %x, ptr %p) {907; CHECK-LABEL: @umul_8(908; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 3909; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 31910; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1911; CHECK-NEXT:    ret i8 [[R]]912;913  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 8)914  %r = extractvalue { i8, i1 } %m, 0915  %ov = extractvalue { i8, i1 } %m, 1916  store i1 %ov, ptr %p917  ret i8 %r918}919 920define i8 @umul_64(i8 %x, ptr %p) {921; CHECK-LABEL: @umul_64(922; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 6923; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 3924; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1925; CHECK-NEXT:    ret i8 [[R]]926;927  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 64)928  %r = extractvalue { i8, i1 } %m, 0929  %ov = extractvalue { i8, i1 } %m, 1930  store i1 %ov, ptr %p931  ret i8 %r932}933 934define i8 @umul_256(i8 %x, ptr %p) {935; CHECK-LABEL: @umul_256(936; CHECK-NEXT:    store i1 false, ptr [[P:%.*]], align 1937; CHECK-NEXT:    ret i8 0938;939  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 256)940  %r = extractvalue { i8, i1 } %m, 0941  %ov = extractvalue { i8, i1 } %m, 1942  store i1 %ov, ptr %p943  ret i8 %r944}945 946define <4 x i8> @umul_4_vec_poison(<4 x i8> %x, ptr %p) {947; CHECK-LABEL: @umul_4_vec_poison(948; CHECK-NEXT:    [[R:%.*]] = shl <4 x i8> [[X:%.*]], splat (i8 2)949; CHECK-NEXT:    [[OV:%.*]] = icmp ugt <4 x i8> [[X]], splat (i8 63)950; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 1951; CHECK-NEXT:    ret <4 x i8> [[R]]952;953  %m = tail call { <4 x i8>, <4 x i1> } @llvm.umul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 4, i8 4, i8 poison>)954  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 0955  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 1956  store <4 x i1> %ov, ptr %p957  ret <4 x i8> %r958}959 960; Negative test: not PowerOf2961 962define i8 @umul_3(i8 %x, ptr %p) {963; CHECK-LABEL: @umul_3(964; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 [[X:%.*]], i8 3)965; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 0966; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 1967; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1968; CHECK-NEXT:    ret i8 [[R]]969;970  %m = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %x, i8 3)971  %r = extractvalue { i8, i1 } %m, 0972  %ov = extractvalue { i8, i1 } %m, 1973  store i1 %ov, ptr %p974  ret i8 %r975}976 977define i8 @smul_4(i8 %x, ptr %p) {978; CHECK-LABEL: @smul_4(979; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 2980; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -32981; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -64982; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1983; CHECK-NEXT:    ret i8 [[R]]984;985  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 4)986  %r = extractvalue { i8, i1 } %m, 0987  %ov = extractvalue { i8, i1 } %m, 1988  store i1 %ov, ptr %p989  ret i8 %r990}991 992define i8 @smul_16(i8 %x, ptr %p) {993; CHECK-LABEL: @smul_16(994; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 4995; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -8996; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -16997; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 1998; CHECK-NEXT:    ret i8 [[R]]999;1000  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 16)1001  %r = extractvalue { i8, i1 } %m, 01002  %ov = extractvalue { i8, i1 } %m, 11003  store i1 %ov, ptr %p1004  ret i8 %r1005}1006 1007define i8 @smul_32(i8 %x, ptr %p) {1008; CHECK-LABEL: @smul_32(1009; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 51010; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[X]], -41011; CHECK-NEXT:    [[OV:%.*]] = icmp ult i8 [[TMP1]], -81012; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 11013; CHECK-NEXT:    ret i8 [[R]]1014;1015  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 32)1016  %r = extractvalue { i8, i1 } %m, 01017  %ov = extractvalue { i8, i1 } %m, 11018  store i1 %ov, ptr %p1019  ret i8 %r1020}1021 1022define i8 @smul_128(i8 %x, ptr %p) {1023; CHECK-LABEL: @smul_128(1024; CHECK-NEXT:    [[R:%.*]] = shl i8 [[X:%.*]], 71025; CHECK-NEXT:    [[OV:%.*]] = icmp ugt i8 [[X]], 11026; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 11027; CHECK-NEXT:    ret i8 [[R]]1028;1029  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 128)1030  %r = extractvalue { i8, i1 } %m, 01031  %ov = extractvalue { i8, i1 } %m, 11032  store i1 %ov, ptr %p1033  ret i8 %r1034}1035 1036define <4 x i8> @smul_2_vec_poison(<4 x i8> %x, ptr %p) {1037; CHECK-LABEL: @smul_2_vec_poison(1038; CHECK-NEXT:    [[R:%.*]] = shl <4 x i8> [[X:%.*]], splat (i8 1)1039; CHECK-NEXT:    [[TMP1:%.*]] = add <4 x i8> [[X]], splat (i8 64)1040; CHECK-NEXT:    [[OV:%.*]] = icmp slt <4 x i8> [[TMP1]], zeroinitializer1041; CHECK-NEXT:    store <4 x i1> [[OV]], ptr [[P:%.*]], align 11042; CHECK-NEXT:    ret <4 x i8> [[R]]1043;1044  %m = tail call { <4 x i8>, <4 x i1> } @llvm.smul.with.overflow.v4i8(<4 x i8> %x, <4 x i8> <i8 poison, i8 2, i8 2, i8 poison>)1045  %r = extractvalue { <4 x i8>, <4 x i1> } %m, 01046  %ov = extractvalue { <4 x i8>, <4 x i1> } %m, 11047  store <4 x i1> %ov, ptr %p1048  ret <4 x i8> %r1049}1050 1051; Negative test: not PowerOf21052 1053define i8 @smul_7(i8 %x, ptr %p) {1054; CHECK-LABEL: @smul_7(1055; CHECK-NEXT:    [[M:%.*]] = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 [[X:%.*]], i8 7)1056; CHECK-NEXT:    [[R:%.*]] = extractvalue { i8, i1 } [[M]], 01057; CHECK-NEXT:    [[OV:%.*]] = extractvalue { i8, i1 } [[M]], 11058; CHECK-NEXT:    store i1 [[OV]], ptr [[P:%.*]], align 11059; CHECK-NEXT:    ret i8 [[R]]1060;1061  %m = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %x, i8 7)1062  %r = extractvalue { i8, i1 } %m, 01063  %ov = extractvalue { i8, i1 } %m, 11064  store i1 %ov, ptr %p1065  ret i8 %r1066}1067