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