2866 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4target datalayout = "e-p:64:64:64-p1:16:16:16-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"5 6define i32 @sub_constant(i32 %x) {7; CHECK-LABEL: @sub_constant(8; CHECK-NEXT: [[R:%.*]] = add i32 [[X:%.*]], -429; CHECK-NEXT: ret i32 [[R]]10;11 %r = sub i32 %x, 4212 ret i32 %r13}14 15@g = global i32 016 17define i32 @sub_constant_expression(i32 %x) {18; CHECK-LABEL: @sub_constant_expression(19; CHECK-NEXT: [[R:%.*]] = sub i32 [[X:%.*]], ptrtoint (ptr @g to i32)20; CHECK-NEXT: ret i32 [[R]]21;22 %r = sub i32 %x, ptrtoint (ptr @g to i32)23 ret i32 %r24}25 26define <2 x i32> @sub_constant_vec(<2 x i32> %x) {27; CHECK-LABEL: @sub_constant_vec(28; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[X:%.*]], <i32 -42, i32 12>29; CHECK-NEXT: ret <2 x i32> [[R]]30;31 %r = sub <2 x i32> %x, <i32 42, i32 -12>32 ret <2 x i32> %r33}34 35define <3 x i33> @sub_constant_vec_weird_type(<3 x i33> %x) {36; CHECK-LABEL: @sub_constant_vec_weird_type(37; CHECK-NEXT: [[R:%.*]] = add <3 x i33> [[X:%.*]], <i33 42, i33 -42, i33 12>38; CHECK-NEXT: ret <3 x i33> [[R]]39;40 %r = sub <3 x i33> %x, <i33 -42, i33 42, i33 -12>41 ret <3 x i33> %r42}43 44define <4 x i32> @sub_constant_expression_vec(<4 x i32> %x) {45; CHECK-LABEL: @sub_constant_expression_vec(46; CHECK-NEXT: [[R:%.*]] = sub <4 x i32> [[X:%.*]], bitcast (i128 ptrtoint (ptr @g to i128) to <4 x i32>)47; CHECK-NEXT: ret <4 x i32> [[R]]48;49 %r = sub <4 x i32> %x, bitcast (i128 ptrtoint (ptr @g to i128) to <4 x i32>)50 ret <4 x i32> %r51}52 53define i32 @neg_sub(i32 %x, i32 %y) {54; CHECK-LABEL: @neg_sub(55; CHECK-NEXT: [[R:%.*]] = add i32 [[Y:%.*]], [[X:%.*]]56; CHECK-NEXT: ret i32 [[R]]57;58 %neg = sub i32 0, %x59 %r = sub i32 %y, %neg60 ret i32 %r61}62 63define i32 @neg_nsw_sub(i32 %x, i32 %y) {64; CHECK-LABEL: @neg_nsw_sub(65; CHECK-NEXT: [[R:%.*]] = add i32 [[Y:%.*]], [[X:%.*]]66; CHECK-NEXT: ret i32 [[R]]67;68 %neg = sub nsw i32 0, %x69 %r = sub i32 %y, %neg70 ret i32 %r71}72 73define i32 @neg_sub_nsw(i32 %x, i32 %y) {74; CHECK-LABEL: @neg_sub_nsw(75; CHECK-NEXT: [[R:%.*]] = add i32 [[Y:%.*]], [[X:%.*]]76; CHECK-NEXT: ret i32 [[R]]77;78 %neg = sub i32 0, %x79 %r = sub nsw i32 %y, %neg80 ret i32 %r81}82 83define i32 @neg_nsw_sub_nsw(i32 %x, i32 %y) {84; CHECK-LABEL: @neg_nsw_sub_nsw(85; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[Y:%.*]], [[X:%.*]]86; CHECK-NEXT: ret i32 [[R]]87;88 %neg = sub nsw i32 0, %x89 %r = sub nsw i32 %y, %neg90 ret i32 %r91}92 93define <2 x i32> @neg_sub_vec(<2 x i32> %x, <2 x i32> %y) {94; CHECK-LABEL: @neg_sub_vec(95; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]96; CHECK-NEXT: ret <2 x i32> [[R]]97;98 %neg = sub <2 x i32> zeroinitializer, %x99 %r = sub <2 x i32> %y, %neg100 ret <2 x i32> %r101}102 103define <2 x i32> @neg_nsw_sub_vec(<2 x i32> %x, <2 x i32> %y) {104; CHECK-LABEL: @neg_nsw_sub_vec(105; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]106; CHECK-NEXT: ret <2 x i32> [[R]]107;108 %neg = sub nsw <2 x i32> zeroinitializer, %x109 %r = sub <2 x i32> %y, %neg110 ret <2 x i32> %r111}112 113define <2 x i32> @neg_sub_nsw_vec(<2 x i32> %x, <2 x i32> %y) {114; CHECK-LABEL: @neg_sub_nsw_vec(115; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]116; CHECK-NEXT: ret <2 x i32> [[R]]117;118 %neg = sub <2 x i32> zeroinitializer, %x119 %r = sub nsw <2 x i32> %y, %neg120 ret <2 x i32> %r121}122 123define <2 x i32> @neg_nsw_sub_nsw_vec(<2 x i32> %x, <2 x i32> %y) {124; CHECK-LABEL: @neg_nsw_sub_nsw_vec(125; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i32> [[Y:%.*]], [[X:%.*]]126; CHECK-NEXT: ret <2 x i32> [[R]]127;128 %neg = sub nsw <2 x i32> zeroinitializer, %x129 %r = sub nsw <2 x i32> %y, %neg130 ret <2 x i32> %r131}132 133define <2 x i32> @neg_sub_vec_poison(<2 x i32> %x, <2 x i32> %y) {134; CHECK-LABEL: @neg_sub_vec_poison(135; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]136; CHECK-NEXT: ret <2 x i32> [[R]]137;138 %neg = sub <2 x i32> <i32 0, i32 poison>, %x139 %r = sub <2 x i32> %y, %neg140 ret <2 x i32> %r141}142 143define <2 x i32> @neg_nsw_sub_vec_poison(<2 x i32> %x, <2 x i32> %y) {144; CHECK-LABEL: @neg_nsw_sub_vec_poison(145; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]146; CHECK-NEXT: ret <2 x i32> [[R]]147;148 %neg = sub nsw <2 x i32> <i32 poison, i32 0>, %x149 %r = sub <2 x i32> %y, %neg150 ret <2 x i32> %r151}152 153define <2 x i32> @neg_sub_nsw_vec_poison(<2 x i32> %x, <2 x i32> %y) {154; CHECK-LABEL: @neg_sub_nsw_vec_poison(155; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[Y:%.*]], [[X:%.*]]156; CHECK-NEXT: ret <2 x i32> [[R]]157;158 %neg = sub <2 x i32> <i32 poison, i32 0>, %x159 %r = sub nsw <2 x i32> %y, %neg160 ret <2 x i32> %r161}162 163; This should not drop 'nsw'.164 165define <2 x i32> @neg_nsw_sub_nsw_vec_poison(<2 x i32> %x, <2 x i32> %y) {166; CHECK-LABEL: @neg_nsw_sub_nsw_vec_poison(167; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i32> [[Y:%.*]], [[X:%.*]]168; CHECK-NEXT: ret <2 x i32> [[R]]169;170 %neg = sub nsw <2 x i32> <i32 0, i32 poison>, %x171 %r = sub nsw <2 x i32> %y, %neg172 ret <2 x i32> %r173}174 175; (~X) - (~Y) --> Y - X176; Also, show that we can handle extra uses and vectors.177 178declare void @use8(i8)179 180define i8 @notnotsub(i8 %x, i8 %y) {181; CHECK-LABEL: @notnotsub(182; CHECK-NEXT: [[NX:%.*]] = xor i8 [[X:%.*]], -1183; CHECK-NEXT: [[NY:%.*]] = xor i8 [[Y:%.*]], -1184; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[Y]], [[X]]185; CHECK-NEXT: call void @use8(i8 [[NX]])186; CHECK-NEXT: call void @use8(i8 [[NY]])187; CHECK-NEXT: ret i8 [[SUB]]188;189 %nx = xor i8 %x, -1190 %ny = xor i8 %y, -1191 %sub = sub i8 %nx, %ny192 call void @use8(i8 %nx)193 call void @use8(i8 %ny)194 ret i8 %sub195}196 197define <2 x i8> @notnotsub_vec(<2 x i8> %x, <2 x i8> %y) {198; CHECK-LABEL: @notnotsub_vec(199; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[Y:%.*]], [[X:%.*]]200; CHECK-NEXT: ret <2 x i8> [[SUB]]201;202 %nx = xor <2 x i8> %x, <i8 -1, i8 -1>203 %ny = xor <2 x i8> %y, <i8 -1, i8 -1>204 %sub = sub <2 x i8> %nx, %ny205 ret <2 x i8> %sub206}207 208define <2 x i8> @notnotsub_vec_poison_elts(<2 x i8> %x, <2 x i8> %y) {209; CHECK-LABEL: @notnotsub_vec_poison_elts(210; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i8> [[Y:%.*]], [[X:%.*]]211; CHECK-NEXT: ret <2 x i8> [[SUB]]212;213 %nx = xor <2 x i8> %x, <i8 poison, i8 -1>214 %ny = xor <2 x i8> %y, <i8 -1, i8 poison>215 %sub = sub <2 x i8> %nx, %ny216 ret <2 x i8> %sub217}218 219define i32 @test5(i32 %A, i32 %B, i32 %C) {220; CHECK-LABEL: @test5(221; CHECK-NEXT: [[D_NEG:%.*]] = sub i32 [[C:%.*]], [[B:%.*]]222; CHECK-NEXT: [[E:%.*]] = add i32 [[D_NEG]], [[A:%.*]]223; CHECK-NEXT: ret i32 [[E]]224;225 %D = sub i32 %B, %C226 %E = sub i32 %A, %D227 ret i32 %E228}229 230define i32 @test6(i32 %A, i32 %B) {231; CHECK-LABEL: @test6(232; CHECK-NEXT: [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1233; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], [[B_NOT]]234; CHECK-NEXT: ret i32 [[D]]235;236 %C = and i32 %A, %B237 %D = sub i32 %A, %C238 ret i32 %D239}240 241define i32 @test6commuted(i32 %A, i32 %B) {242; CHECK-LABEL: @test6commuted(243; CHECK-NEXT: [[B_NOT:%.*]] = xor i32 [[B:%.*]], -1244; CHECK-NEXT: [[D:%.*]] = and i32 [[A:%.*]], [[B_NOT]]245; CHECK-NEXT: ret i32 [[D]]246;247 %C = and i32 %B, %A248 %D = sub i32 %A, %C249 ret i32 %D250}251 252define i32 @test7(i32 %A) {253; CHECK-LABEL: @test7(254; CHECK-NEXT: [[B:%.*]] = xor i32 [[A:%.*]], -1255; CHECK-NEXT: ret i32 [[B]]256;257 %B = sub i32 -1, %A258 ret i32 %B259}260 261define i32 @test8(i32 %A) {262; CHECK-LABEL: @test8(263; CHECK-NEXT: [[C:%.*]] = shl i32 [[A:%.*]], 3264; CHECK-NEXT: ret i32 [[C]]265;266 %B = mul i32 9, %A267 %C = sub i32 %B, %A268 ret i32 %C269}270 271define i32 @test9(i32 %A) {272; CHECK-LABEL: @test9(273; CHECK-NEXT: [[C:%.*]] = mul i32 [[A:%.*]], -2274; CHECK-NEXT: ret i32 [[C]]275;276 %B = mul i32 3, %A277 %C = sub i32 %A, %B278 ret i32 %C279}280 281define i1 @test11(i8 %A, i8 %B) {282; CHECK-LABEL: @test11(283; CHECK-NEXT: [[D:%.*]] = icmp ne i8 [[A:%.*]], [[B:%.*]]284; CHECK-NEXT: ret i1 [[D]]285;286 %C = sub i8 %A, %B287 %D = icmp ne i8 %C, 0288 ret i1 %D289}290 291define <2 x i1> @test11vec(<2 x i8> %A, <2 x i8> %B) {292; CHECK-LABEL: @test11vec(293; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i8> [[A:%.*]], [[B:%.*]]294; CHECK-NEXT: ret <2 x i1> [[D]]295;296 %C = sub <2 x i8> %A, %B297 %D = icmp ne <2 x i8> %C, zeroinitializer298 ret <2 x i1> %D299}300 301define i32 @test12(i32 %A) {302; CHECK-LABEL: @test12(303; CHECK-NEXT: [[B_NEG:%.*]] = lshr i32 [[A:%.*]], 31304; CHECK-NEXT: ret i32 [[B_NEG]]305;306 %B = ashr i32 %A, 31307 %C = sub i32 0, %B308 ret i32 %C309}310 311define i32 @test13(i32 %A) {312; CHECK-LABEL: @test13(313; CHECK-NEXT: [[B_NEG:%.*]] = ashr i32 [[A:%.*]], 31314; CHECK-NEXT: ret i32 [[B_NEG]]315;316 %B = lshr i32 %A, 31317 %C = sub i32 0, %B318 ret i32 %C319}320 321define <2 x i32> @test12vec(<2 x i32> %A) {322; CHECK-LABEL: @test12vec(323; CHECK-NEXT: [[B_NEG:%.*]] = lshr <2 x i32> [[A:%.*]], splat (i32 31)324; CHECK-NEXT: ret <2 x i32> [[B_NEG]]325;326 %B = ashr <2 x i32> %A, <i32 31, i32 31>327 %C = sub <2 x i32> zeroinitializer, %B328 ret <2 x i32> %C329}330 331define <2 x i32> @test13vec(<2 x i32> %A) {332; CHECK-LABEL: @test13vec(333; CHECK-NEXT: [[B_NEG:%.*]] = ashr <2 x i32> [[A:%.*]], splat (i32 31)334; CHECK-NEXT: ret <2 x i32> [[B_NEG]]335;336 %B = lshr <2 x i32> %A, <i32 31, i32 31>337 %C = sub <2 x i32> zeroinitializer, %B338 ret <2 x i32> %C339}340 341define i32 @test15(i32 %A, i32 %B) {342; CHECK-LABEL: @test15(343; CHECK-NEXT: [[C:%.*]] = sub i32 0, [[A:%.*]]344; CHECK-NEXT: [[D:%.*]] = srem i32 [[B:%.*]], [[C]]345; CHECK-NEXT: ret i32 [[D]]346;347 %C = sub i32 0, %A348 %D = srem i32 %B, %C349 ret i32 %D350}351 352define i32 @test16(i32 %A) {353; CHECK-LABEL: @test16(354; CHECK-NEXT: [[X_NEG:%.*]] = sdiv i32 [[A:%.*]], -1123355; CHECK-NEXT: ret i32 [[X_NEG]]356;357 %X = sdiv i32 %A, 1123358 %Y = sub i32 0, %X359 ret i32 %Y360}361 362; Can't fold subtract here because negation it might oveflow.363; PR3142364define i32 @test17(i32 %A) {365; CHECK-LABEL: @test17(366; CHECK-NEXT: [[B:%.*]] = sub i32 0, [[A:%.*]]367; CHECK-NEXT: [[C:%.*]] = sdiv i32 [[B]], 1234368; CHECK-NEXT: ret i32 [[C]]369;370 %B = sub i32 0, %A371 %C = sdiv i32 %B, 1234372 ret i32 %C373}374 375define i64 @test18(i64 %Y) {376; CHECK-LABEL: @test18(377; CHECK-NEXT: ret i64 0378;379 %i.4 = shl i64 %Y, 2380 %i.12 = shl i64 %Y, 2381 %i.8 = sub i64 %i.4, %i.12382 ret i64 %i.8383}384 385define i1 @test20(i32 %g, i32 %h) {386; CHECK-LABEL: @test20(387; CHECK-NEXT: [[I_4:%.*]] = icmp ne i32 [[H:%.*]], 0388; CHECK-NEXT: ret i1 [[I_4]]389;390 %i.2 = sub i32 %g, %h391 %i.4 = icmp ne i32 %i.2, %g392 ret i1 %i.4393}394 395define i1 @test21(i32 %g, i32 %h) {396; CHECK-LABEL: @test21(397; CHECK-NEXT: [[I_4:%.*]] = icmp ne i32 [[H:%.*]], 0398; CHECK-NEXT: ret i1 [[I_4]]399;400 %i.2 = sub i32 %g, %h401 %i.4 = icmp ne i32 %i.2, %g402 ret i1 %i.4403}404 405; PR2298406define zeroext i1 @test22(i32 %a, i32 %b) nounwind {407; CHECK-LABEL: @test22(408; CHECK-NEXT: [[I5:%.*]] = icmp eq i32 [[B:%.*]], [[A:%.*]]409; CHECK-NEXT: ret i1 [[I5]]410;411 %i2 = sub i32 0, %a412 %i4 = sub i32 0, %b413 %i5 = icmp eq i32 %i2, %i4414 ret i1 %i5415}416 417define i32 @test26(i32 %x) {418; CHECK-LABEL: @test26(419; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i32 -3, [[X:%.*]]420; CHECK-NEXT: ret i32 [[SHL_NEG]]421;422 %shl = shl i32 3, %x423 %neg = sub i32 0, %shl424 ret i32 %neg425}426 427define i64 @test_neg_shl_sub(i64 %a, i64 %b) {428; CHECK-LABEL: @test_neg_shl_sub(429; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]430; CHECK-NEXT: [[MUL_NEG:%.*]] = shl i64 [[SUB_NEG]], 2431; CHECK-NEXT: ret i64 [[MUL_NEG]]432;433 %sub = sub i64 %a, %b434 %mul = shl i64 %sub, 2435 %neg = sub i64 0, %mul436 ret i64 %neg437}438 439define i64 @test_neg_shl_sub_extra_use1(i64 %a, i64 %b, ptr %p) {440; CHECK-LABEL: @test_neg_shl_sub_extra_use1(441; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]442; CHECK-NEXT: store i64 [[SUB]], ptr [[P:%.*]], align 8443; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[SUB]], -4444; CHECK-NEXT: ret i64 [[MUL_NEG]]445;446 %sub = sub i64 %a, %b447 store i64 %sub, ptr %p448 %mul = shl i64 %sub, 2449 %neg = sub i64 0, %mul450 ret i64 %neg451}452 453define i64 @test_neg_shl_sub_extra_use2(i64 %a, i64 %b, ptr %p) {454; CHECK-LABEL: @test_neg_shl_sub_extra_use2(455; CHECK-NEXT: [[SUB:%.*]] = sub i64 [[A:%.*]], [[B:%.*]]456; CHECK-NEXT: [[MUL:%.*]] = shl i64 [[SUB]], 2457; CHECK-NEXT: store i64 [[MUL]], ptr [[P:%.*]], align 8458; CHECK-NEXT: [[NEG:%.*]] = sub i64 0, [[MUL]]459; CHECK-NEXT: ret i64 [[NEG]]460;461 %sub = sub i64 %a, %b462 %mul = shl i64 %sub, 2463 store i64 %mul, ptr %p464 %neg = sub i64 0, %mul465 ret i64 %neg466}467 468define i64 @test_neg_shl_div(i64 %a) {469; CHECK-LABEL: @test_neg_shl_div(470; CHECK-NEXT: [[DIV_NEG:%.*]] = sdiv i64 [[A:%.*]], -3471; CHECK-NEXT: [[SHL_NEG:%.*]] = shl i64 [[DIV_NEG]], 2472; CHECK-NEXT: ret i64 [[SHL_NEG]]473;474 %div = sdiv i64 %a, 3475 %shl = shl i64 %div, 2476 %neg = sub i64 0, %shl477 ret i64 %neg478}479 480define i64 @test_neg_shl_zext_i1(i1 %a, i64 %b) {481; CHECK-LABEL: @test_neg_shl_zext_i1(482; CHECK-NEXT: [[EXT_NEG:%.*]] = sext i1 [[A:%.*]] to i64483; CHECK-NEXT: [[SHL_NEG:%.*]] = shl nsw i64 [[EXT_NEG]], [[B:%.*]]484; CHECK-NEXT: ret i64 [[SHL_NEG]]485;486 %ext = zext i1 %a to i64487 %shl = shl i64 %ext, %b488 %neg = sub i64 0, %shl489 ret i64 %neg490}491 492define i64 @test_neg_shl_sext_i1(i1 %a, i64 %b) {493; CHECK-LABEL: @test_neg_shl_sext_i1(494; CHECK-NEXT: [[EXT_NEG:%.*]] = zext i1 [[A:%.*]] to i64495; CHECK-NEXT: [[SHL_NEG:%.*]] = shl nuw i64 [[EXT_NEG]], [[B:%.*]]496; CHECK-NEXT: ret i64 [[SHL_NEG]]497;498 %ext = sext i1 %a to i64499 %shl = shl i64 %ext, %b500 %neg = sub i64 0, %shl501 ret i64 %neg502}503 504define i64 @test_neg_zext_i1_extra_use(i1 %a, i64 %b, ptr %p) {505; CHECK-LABEL: @test_neg_zext_i1_extra_use(506; CHECK-NEXT: [[EXT_NEG:%.*]] = sext i1 [[A:%.*]] to i64507; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[A]] to i64508; CHECK-NEXT: store i64 [[EXT]], ptr [[P:%.*]], align 8509; CHECK-NEXT: ret i64 [[EXT_NEG]]510;511 %ext = zext i1 %a to i64512 %neg = sub i64 0, %ext513 store i64 %ext, ptr %p514 ret i64 %neg515}516 517define i64 @test_neg_sext_i1_extra_use(i1 %a, i64 %b, ptr %p) {518; CHECK-LABEL: @test_neg_sext_i1_extra_use(519; CHECK-NEXT: [[EXT_NEG:%.*]] = zext i1 [[A:%.*]] to i64520; CHECK-NEXT: [[EXT:%.*]] = sext i1 [[A]] to i64521; CHECK-NEXT: store i64 [[EXT]], ptr [[P:%.*]], align 8522; CHECK-NEXT: ret i64 [[EXT_NEG]]523;524 %ext = sext i1 %a to i64525 %neg = sub i64 0, %ext526 store i64 %ext, ptr %p527 ret i64 %neg528}529 530define i32 @test_neg_trunc_shl_sub(i64 %a, i64 %b) {531; CHECK-LABEL: @test_neg_trunc_shl_sub(532; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]533; CHECK-NEXT: [[SUB_TR_NEG:%.*]] = trunc i64 [[SUB_NEG]] to i32534; CHECK-NEXT: [[TRUNC_NEG:%.*]] = shl i32 [[SUB_TR_NEG]], 2535; CHECK-NEXT: ret i32 [[TRUNC_NEG]]536;537 %sub = sub i64 %a, %b538 %shl = shl i64 %sub, 2539 %trunc = trunc i64 %shl to i32540 %neg = sub i32 0, %trunc541 ret i32 %neg542}543 544define i32 @test_neg_trunc_shl_ashr(i64 %a, i64 %b) {545; CHECK-LABEL: @test_neg_trunc_shl_ashr(546; CHECK-NEXT: [[SHR_NEG:%.*]] = lshr i64 [[A:%.*]], 63547; CHECK-NEXT: [[SHL_NEG:%.*]] = shl nuw i64 [[SHR_NEG]], [[B:%.*]]548; CHECK-NEXT: [[TRUNC_NEG:%.*]] = trunc i64 [[SHL_NEG]] to i32549; CHECK-NEXT: ret i32 [[TRUNC_NEG]]550;551 %shr = ashr i64 %a, 63552 %shl = shl i64 %shr, %b553 %trunc = trunc i64 %shl to i32554 %neg = sub i32 0, %trunc555 ret i32 %neg556}557 558define i32 @test_neg_trunc_shl_lshr(i64 %a, i64 %b) {559; CHECK-LABEL: @test_neg_trunc_shl_lshr(560; CHECK-NEXT: [[SHR_NEG:%.*]] = ashr i64 [[A:%.*]], 63561; CHECK-NEXT: [[SHL_NEG:%.*]] = shl nsw i64 [[SHR_NEG]], [[B:%.*]]562; CHECK-NEXT: [[TRUNC_NEG:%.*]] = trunc i64 [[SHL_NEG]] to i32563; CHECK-NEXT: ret i32 [[TRUNC_NEG]]564;565 %shr = lshr i64 %a, 63566 %shl = shl i64 %shr, %b567 %trunc = trunc i64 %shl to i32568 %neg = sub i32 0, %trunc569 ret i32 %neg570}571 572define i64 @test_neg_mul_sub(i64 %a, i64 %b, i64 %c) {573; CHECK-LABEL: @test_neg_mul_sub(574; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]575; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[SUB_NEG]], [[C:%.*]]576; CHECK-NEXT: ret i64 [[MUL_NEG]]577;578 %sub = sub i64 %a, %b579 %mul = mul i64 %sub, %c580 %neg = sub i64 0, %mul581 ret i64 %neg582}583 584define i64 @test_neg_mul_sub_commuted(i64 %a, i64 %b, i64 %c) {585; CHECK-LABEL: @test_neg_mul_sub_commuted(586; CHECK-NEXT: [[COMPLEX:%.*]] = mul i64 [[C:%.*]], [[C]]587; CHECK-NEXT: [[SUB_NEG:%.*]] = sub i64 [[B:%.*]], [[A:%.*]]588; CHECK-NEXT: [[MUL_NEG:%.*]] = mul i64 [[SUB_NEG]], [[COMPLEX]]589; CHECK-NEXT: ret i64 [[MUL_NEG]]590;591 %complex = mul i64 %c, %c592 %sub = sub i64 %a, %b593 %mul = mul i64 %complex, %sub594 %neg = sub i64 0, %mul595 ret i64 %neg596}597 598define i32 @test27(i32 %x, i32 %y) {599; CHECK-LABEL: @test27(600; CHECK-NEXT: [[MUL_NEG:%.*]] = shl i32 [[Y:%.*]], 3601; CHECK-NEXT: [[SUB:%.*]] = add i32 [[MUL_NEG]], [[X:%.*]]602; CHECK-NEXT: ret i32 [[SUB]]603;604 %mul = mul i32 %y, -8605 %sub = sub i32 %x, %mul606 ret i32 %sub607}608 609define <2 x i32> @test27vec(<2 x i32> %x, <2 x i32> %y) {610; CHECK-LABEL: @test27vec(611; CHECK-NEXT: [[MUL_NEG:%.*]] = mul <2 x i32> [[Y:%.*]], <i32 8, i32 6>612; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]613; CHECK-NEXT: ret <2 x i32> [[SUB]]614;615 %mul = mul <2 x i32> %y, <i32 -8, i32 -6>616 %sub = sub <2 x i32> %x, %mul617 ret <2 x i32> %sub618}619 620define <2 x i32> @test27vecsplat(<2 x i32> %x, <2 x i32> %y) {621; CHECK-LABEL: @test27vecsplat(622; CHECK-NEXT: [[MUL_NEG:%.*]] = shl <2 x i32> [[Y:%.*]], splat (i32 3)623; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]624; CHECK-NEXT: ret <2 x i32> [[SUB]]625;626 %mul = mul <2 x i32> %y, <i32 -8, i32 -8>627 %sub = sub <2 x i32> %x, %mul628 ret <2 x i32> %sub629}630 631define <2 x i32> @test27vecmixed(<2 x i32> %x, <2 x i32> %y) {632; CHECK-LABEL: @test27vecmixed(633; CHECK-NEXT: [[MUL_NEG:%.*]] = mul <2 x i32> [[Y:%.*]], <i32 8, i32 -8>634; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]635; CHECK-NEXT: ret <2 x i32> [[SUB]]636;637 %mul = mul <2 x i32> %y, <i32 -8, i32 8>638 %sub = sub <2 x i32> %x, %mul639 ret <2 x i32> %sub640}641 642define i32 @test27commuted(i32 %x, i32 %y) {643; CHECK-LABEL: @test27commuted(644; CHECK-NEXT: [[MUL_NEG:%.*]] = shl i32 [[Y:%.*]], 3645; CHECK-NEXT: [[SUB:%.*]] = add i32 [[MUL_NEG]], [[X:%.*]]646; CHECK-NEXT: ret i32 [[SUB]]647;648 %mul = mul i32 -8, %y649 %sub = sub i32 %x, %mul650 ret i32 %sub651}652 653define <2 x i32> @test27commutedvec(<2 x i32> %x, <2 x i32> %y) {654; CHECK-LABEL: @test27commutedvec(655; CHECK-NEXT: [[MUL_NEG:%.*]] = mul <2 x i32> [[Y:%.*]], <i32 8, i32 6>656; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]657; CHECK-NEXT: ret <2 x i32> [[SUB]]658;659 %mul = mul <2 x i32> <i32 -8, i32 -6>, %y660 %sub = sub <2 x i32> %x, %mul661 ret <2 x i32> %sub662}663 664define <2 x i32> @test27commutedvecsplat(<2 x i32> %x, <2 x i32> %y) {665; CHECK-LABEL: @test27commutedvecsplat(666; CHECK-NEXT: [[MUL_NEG:%.*]] = shl <2 x i32> [[Y:%.*]], splat (i32 3)667; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]668; CHECK-NEXT: ret <2 x i32> [[SUB]]669;670 %mul = mul <2 x i32> <i32 -8, i32 -8>, %y671 %sub = sub <2 x i32> %x, %mul672 ret <2 x i32> %sub673}674 675define <2 x i32> @test27commutedvecmixed(<2 x i32> %x, <2 x i32> %y) {676; CHECK-LABEL: @test27commutedvecmixed(677; CHECK-NEXT: [[MUL_NEG:%.*]] = mul <2 x i32> [[Y:%.*]], <i32 8, i32 -8>678; CHECK-NEXT: [[SUB:%.*]] = add <2 x i32> [[MUL_NEG]], [[X:%.*]]679; CHECK-NEXT: ret <2 x i32> [[SUB]]680;681 %mul = mul <2 x i32> <i32 -8, i32 8>, %y682 %sub = sub <2 x i32> %x, %mul683 ret <2 x i32> %sub684}685 686define i32 @test28(i32 %x, i32 %y, i32 %z) {687; CHECK-LABEL: @test28(688; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Z:%.*]], [[Y:%.*]]689; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X:%.*]], [[TMP1]]690; CHECK-NEXT: ret i32 [[SUB]]691;692 %neg = sub i32 0, %z693 %mul = mul i32 %neg, %y694 %sub = sub i32 %x, %mul695 ret i32 %sub696}697 698define i32 @test28commuted(i32 %x, i32 %y, i32 %z) {699; CHECK-LABEL: @test28commuted(700; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[Z:%.*]], [[Y:%.*]]701; CHECK-NEXT: [[SUB:%.*]] = add i32 [[X:%.*]], [[TMP1]]702; CHECK-NEXT: ret i32 [[SUB]]703;704 %neg = sub i32 0, %z705 %mul = mul i32 %y, %neg706 %sub = sub i32 %x, %mul707 ret i32 %sub708}709 710define <2 x i64> @test31(<2 x i64> %A) {711; CHECK-LABEL: @test31(712; CHECK-NEXT: [[SUB:%.*]] = add <2 x i64> [[A:%.*]], <i64 3, i64 4>713; CHECK-NEXT: ret <2 x i64> [[SUB]]714;715 %xor = xor <2 x i64> %A, <i64 -1, i64 -1>716 %sub = sub <2 x i64> <i64 2, i64 3>, %xor717 ret <2 x i64> %sub718}719 720define <2 x i64> @test32(<2 x i64> %A) {721; CHECK-LABEL: @test32(722; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i64> <i64 3, i64 4>, [[A:%.*]]723; CHECK-NEXT: ret <2 x i64> [[SUB]]724;725 %add = add <2 x i64> %A, <i64 -1, i64 -1>726 %sub = sub <2 x i64> <i64 2, i64 3>, %add727 ret <2 x i64> %sub728}729 730define <2 x i64> @test35(<2 x i64> %A) {731; CHECK-LABEL: @test35(732; CHECK-NEXT: [[SUB:%.*]] = mul <2 x i64> [[A:%.*]], <i64 -2, i64 -3>733; CHECK-NEXT: ret <2 x i64> [[SUB]]734;735 %mul = mul <2 x i64> %A, <i64 3, i64 4>736 %sub = sub <2 x i64> %A, %mul737 ret <2 x i64> %sub738}739 740define <2 x i64> @test36(<2 x i64> %A) {741; CHECK-LABEL: @test36(742; CHECK-NEXT: [[SUB:%.*]] = mul <2 x i64> [[A:%.*]], <i64 7, i64 15>743; CHECK-NEXT: ret <2 x i64> [[SUB]]744;745 %shl = shl <2 x i64> %A, <i64 3, i64 4>746 %sub = sub <2 x i64> %shl, %A747 ret <2 x i64> %sub748}749 750define <2 x i32> @test37(<2 x i32> %A) {751; CHECK-LABEL: @test37(752; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i32> [[A:%.*]], splat (i32 -2147483648)753; CHECK-NEXT: [[DIV_NEG:%.*]] = sext <2 x i1> [[TMP1]] to <2 x i32>754; CHECK-NEXT: ret <2 x i32> [[DIV_NEG]]755;756 %div = sdiv <2 x i32> %A, <i32 -2147483648, i32 -2147483648>757 %sub = sub nsw <2 x i32> zeroinitializer, %div758 ret <2 x i32> %sub759}760 761define i32 @test38(i32 %A) {762; CHECK-LABEL: @test38(763; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], -2147483648764; CHECK-NEXT: [[DIV_NEG:%.*]] = sext i1 [[TMP1]] to i32765; CHECK-NEXT: ret i32 [[DIV_NEG]]766;767 %div = sdiv i32 %A, -2147483648768 %sub = sub nsw i32 0, %div769 ret i32 %sub770}771 772define i16 @test40(i16 %a, i16 %b) {773; CHECK-LABEL: @test40(774; CHECK-NEXT: [[ASHR:%.*]] = ashr i16 [[A:%.*]], 1775; CHECK-NEXT: [[ASHR1:%.*]] = ashr i16 [[B:%.*]], 1776; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[ASHR]], [[ASHR1]]777; CHECK-NEXT: ret i16 [[SUB]]778;779 %ashr = ashr i16 %a, 1780 %ashr1 = ashr i16 %b, 1781 %sub = sub i16 %ashr, %ashr1782 ret i16 %sub783}784 785define i32 @test41(i16 %a, i16 %b) {786; CHECK-LABEL: @test41(787; CHECK-NEXT: [[CONV:%.*]] = sext i16 [[A:%.*]] to i32788; CHECK-NEXT: [[CONV1:%.*]] = sext i16 [[B:%.*]] to i32789; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[CONV]], [[CONV1]]790; CHECK-NEXT: ret i32 [[SUB]]791;792 %conv = sext i16 %a to i32793 %conv1 = sext i16 %b to i32794 %sub = sub i32 %conv, %conv1795 ret i32 %sub796}797 798define i4 @test42(i4 %x, i4 %y) {799; CHECK-LABEL: @test42(800; CHECK-NEXT: [[A:%.*]] = and i4 [[Y:%.*]], 7801; CHECK-NEXT: [[B:%.*]] = and i4 [[X:%.*]], 7802; CHECK-NEXT: [[C:%.*]] = sub nsw i4 [[A]], [[B]]803; CHECK-NEXT: ret i4 [[C]]804;805 %a = and i4 %y, 7806 %b = and i4 %x, 7807 %c = sub i4 %a, %b808 ret i4 %c809}810 811define i4 @test43(i4 %x, i4 %y) {812; CHECK-LABEL: @test43(813; CHECK-NEXT: [[A:%.*]] = or i4 [[X:%.*]], -8814; CHECK-NEXT: [[B:%.*]] = and i4 [[Y:%.*]], 7815; CHECK-NEXT: [[C:%.*]] = sub nuw i4 [[A]], [[B]]816; CHECK-NEXT: ret i4 [[C]]817;818 %a = or i4 %x, -8819 %b = and i4 %y, 7820 %c = sub i4 %a, %b821 ret i4 %c822}823 824define i32 @test44(i32 %x) {825; CHECK-LABEL: @test44(826; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[X:%.*]], -32768827; CHECK-NEXT: ret i32 [[SUB]]828;829 %sub = sub nsw i32 %x, 32768830 ret i32 %sub831}832 833define <2 x i32> @test44vec(<2 x i32> %x) {834; CHECK-LABEL: @test44vec(835; CHECK-NEXT: [[SUB:%.*]] = add nsw <2 x i32> [[X:%.*]], splat (i32 -32768)836; CHECK-NEXT: ret <2 x i32> [[SUB]]837;838 %sub = sub nsw <2 x i32> %x, <i32 32768, i32 32768>839 ret <2 x i32> %sub840}841 842define <vscale x 2 x i32> @test44scalablevec(<vscale x 2 x i32> %x) {843; CHECK-LABEL: @test44scalablevec(844; CHECK-NEXT: [[SUB:%.*]] = add nsw <vscale x 2 x i32> [[X:%.*]], splat (i32 -32768)845; CHECK-NEXT: ret <vscale x 2 x i32> [[SUB]]846;847 %sub = sub nsw <vscale x 2 x i32> %x, splat (i32 32768)848 ret <vscale x 2 x i32> %sub849}850 851define <2 x i16> @test44vecminval(<2 x i16> %x) {852; CHECK-LABEL: @test44vecminval(853; CHECK-NEXT: [[SUB:%.*]] = xor <2 x i16> [[X:%.*]], splat (i16 -32768)854; CHECK-NEXT: ret <2 x i16> [[SUB]]855;856 %sub = sub nsw <2 x i16> %x, <i16 -32768, i16 -32768>857 ret <2 x i16> %sub858}859 860define <vscale x 2 x i16> @test44scalablevecminval(<vscale x 2 x i16> %x) {861; CHECK-LABEL: @test44scalablevecminval(862; CHECK-NEXT: [[SUB:%.*]] = xor <vscale x 2 x i16> [[X:%.*]], splat (i16 -32768)863; CHECK-NEXT: ret <vscale x 2 x i16> [[SUB]]864;865 %sub = sub nsw <vscale x 2 x i16> %x, splat (i16 -32768)866 ret <vscale x 2 x i16> %sub867}868 869define i32 @test45(i32 %x, i32 %y) {870; CHECK-LABEL: @test45(871; CHECK-NEXT: [[SUB:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]872; CHECK-NEXT: ret i32 [[SUB]]873;874 %or = or i32 %x, %y875 %xor = xor i32 %x, %y876 %sub = sub i32 %or, %xor877 ret i32 %sub878}879 880define i32 @test45commuted(i32 %x, i32 %y) {881; CHECK-LABEL: @test45commuted(882; CHECK-NEXT: [[SUB:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]883; CHECK-NEXT: ret i32 [[SUB]]884;885 %or = or i32 %x, %y886 %xor = xor i32 %y, %x887 %sub = sub i32 %or, %xor888 ret i32 %sub889}890 891define i32 @test46(i32 %x, i32 %y) {892; CHECK-LABEL: @test46(893; CHECK-NEXT: [[X_NOT:%.*]] = xor i32 [[X:%.*]], -1894; CHECK-NEXT: [[SUB:%.*]] = and i32 [[Y:%.*]], [[X_NOT]]895; CHECK-NEXT: ret i32 [[SUB]]896;897 %or = or i32 %x, %y898 %sub = sub i32 %or, %x899 ret i32 %sub900}901 902define i32 @test46commuted(i32 %x, i32 %y) {903; CHECK-LABEL: @test46commuted(904; CHECK-NEXT: [[X_NOT:%.*]] = xor i32 [[X:%.*]], -1905; CHECK-NEXT: [[SUB:%.*]] = and i32 [[Y:%.*]], [[X_NOT]]906; CHECK-NEXT: ret i32 [[SUB]]907;908 %or = or i32 %y, %x909 %sub = sub i32 %or, %x910 ret i32 %sub911}912 913define i32 @test47(i1 %A, i32 %B, i32 %C, i32 %D) {914; CHECK-LABEL: @test47(915; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[D:%.*]], [[C:%.*]]916; CHECK-NEXT: [[SUB:%.*]] = select i1 [[A:%.*]], i32 [[TMP1]], i32 0917; CHECK-NEXT: ret i32 [[SUB]]918;919 %sel0 = select i1 %A, i32 %D, i32 %B920 %sel1 = select i1 %A, i32 %C, i32 %B921 %sub = sub i32 %sel0, %sel1922 ret i32 %sub923}924 925define i32 @test48(i1 %A, i32 %B, i32 %C, i32 %D) {926; CHECK-LABEL: @test48(927; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[D:%.*]], [[C:%.*]]928; CHECK-NEXT: [[SUB:%.*]] = select i1 [[A:%.*]], i32 0, i32 [[TMP1]]929; CHECK-NEXT: ret i32 [[SUB]]930;931 %sel0 = select i1 %A, i32 %B, i32 %D932 %sel1 = select i1 %A, i32 %B, i32 %C933 %sub = sub i32 %sel0, %sel1934 ret i32 %sub935}936 937define i32 @test49(i32 %X) {938; CHECK-LABEL: @test49(939; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[X:%.*]]940; CHECK-NEXT: [[RES:%.*]] = and i32 [[SUB]], 64941; CHECK-NEXT: ret i32 [[RES]]942;943 %sub = sub i32 129, %X944 %res = and i32 %sub, 64945 ret i32 %res946}947 948define i32 @test50(i32 %X) {949; CHECK-LABEL: @test50(950; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[X:%.*]]951; CHECK-NEXT: [[RES:%.*]] = and i32 [[SUB]], 127952; CHECK-NEXT: ret i32 [[RES]]953;954 %sub = sub i32 129, %X955 %res = and i32 %sub, 127956 ret i32 %res957}958 959define i32 @test51(i32 %X) {960; CHECK-LABEL: @test51(961; CHECK-NEXT: [[SUB:%.*]] = sub i32 126, [[X:%.*]]962; CHECK-NEXT: [[RES:%.*]] = and i32 [[SUB]], 64963; CHECK-NEXT: ret i32 [[RES]]964;965 %sub = sub i32 254, %X966 %res = and i32 %sub, 64967 ret i32 %res968}969 970define i32 @test52(i32 %X) {971; CHECK-LABEL: @test52(972; CHECK-NEXT: [[SUB:%.*]] = sub i32 126, [[X:%.*]]973; CHECK-NEXT: [[RES:%.*]] = and i32 [[SUB]], 127974; CHECK-NEXT: ret i32 [[RES]]975;976 %sub = sub i32 254, %X977 %res = and i32 %sub, 127978 ret i32 %res979}980 981define <2 x i1> @test53(<2 x i1> %A, <2 x i1> %B) {982; CHECK-LABEL: @test53(983; CHECK-NEXT: [[SUB:%.*]] = xor <2 x i1> [[B:%.*]], [[A:%.*]]984; CHECK-NEXT: ret <2 x i1> [[SUB]]985;986 %sub = sub <2 x i1> %A, %B987 ret <2 x i1> %sub988}989 990define i32 @test54(i1 %C) {991; CHECK-LABEL: @test54(992; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], i32 -877, i32 113993; CHECK-NEXT: ret i32 [[V]]994;995 %A = select i1 %C, i32 1000, i32 10996 %V = sub i32 123, %A997 ret i32 %V998}999 1000define <2 x i32> @test54vec(i1 %C) {1001; CHECK-LABEL: @test54vec(1002; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> splat (i32 -877), <2 x i32> splat (i32 113)1003; CHECK-NEXT: ret <2 x i32> [[V]]1004;1005 %A = select i1 %C, <2 x i32> <i32 1000, i32 1000>, <2 x i32> <i32 10, i32 10>1006 %V = sub <2 x i32> <i32 123, i32 123>, %A1007 ret <2 x i32> %V1008}1009 1010define <2 x i32> @test54vec2(i1 %C) {1011; CHECK-LABEL: @test54vec2(1012; CHECK-NEXT: [[V:%.*]] = select i1 [[C:%.*]], <2 x i32> <i32 -877, i32 -2167>, <2 x i32> <i32 113, i32 303>1013; CHECK-NEXT: ret <2 x i32> [[V]]1014;1015 %A = select i1 %C, <2 x i32> <i32 1000, i32 2500>, <2 x i32> <i32 10, i32 30>1016 %V = sub <2 x i32> <i32 123, i32 333>, %A1017 ret <2 x i32> %V1018}1019 1020define i32 @test55(i1 %which) {1021; CHECK-LABEL: @test55(1022; CHECK-NEXT: entry:1023; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]1024; CHECK: delay:1025; CHECK-NEXT: br label [[FINAL]]1026; CHECK: final:1027; CHECK-NEXT: [[A_NEG:%.*]] = phi i32 [ -877, [[ENTRY:%.*]] ], [ 113, [[DELAY]] ]1028; CHECK-NEXT: ret i32 [[A_NEG]]1029;1030entry:1031 br i1 %which, label %final, label %delay1032 1033delay:1034 br label %final1035 1036final:1037 %A = phi i32 [ 1000, %entry ], [ 10, %delay ]1038 %value = sub i32 123, %A1039 ret i32 %value1040}1041 1042define <2 x i32> @test55vec(i1 %which) {1043; CHECK-LABEL: @test55vec(1044; CHECK-NEXT: entry:1045; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]1046; CHECK: delay:1047; CHECK-NEXT: br label [[FINAL]]1048; CHECK: final:1049; CHECK-NEXT: [[A_NEG:%.*]] = phi <2 x i32> [ splat (i32 -877), [[ENTRY:%.*]] ], [ splat (i32 113), [[DELAY]] ]1050; CHECK-NEXT: ret <2 x i32> [[A_NEG]]1051;1052entry:1053 br i1 %which, label %final, label %delay1054 1055delay:1056 br label %final1057 1058final:1059 %A = phi <2 x i32> [ <i32 1000, i32 1000>, %entry ], [ <i32 10, i32 10>, %delay ]1060 %value = sub <2 x i32> <i32 123, i32 123>, %A1061 ret <2 x i32> %value1062}1063 1064define <2 x i32> @test55vec2(i1 %which) {1065; CHECK-LABEL: @test55vec2(1066; CHECK-NEXT: entry:1067; CHECK-NEXT: br i1 [[WHICH:%.*]], label [[FINAL:%.*]], label [[DELAY:%.*]]1068; CHECK: delay:1069; CHECK-NEXT: br label [[FINAL]]1070; CHECK: final:1071; CHECK-NEXT: [[A_NEG:%.*]] = phi <2 x i32> [ <i32 -877, i32 -2167>, [[ENTRY:%.*]] ], [ <i32 113, i32 303>, [[DELAY]] ]1072; CHECK-NEXT: ret <2 x i32> [[A_NEG]]1073;1074entry:1075 br i1 %which, label %final, label %delay1076 1077delay:1078 br label %final1079 1080final:1081 %A = phi <2 x i32> [ <i32 1000, i32 2500>, %entry ], [ <i32 10, i32 30>, %delay ]1082 %value = sub <2 x i32> <i32 123, i32 333>, %A1083 ret <2 x i32> %value1084}1085 1086define i32 @test56(i32 %A, i32 %B) {1087; CHECK-LABEL: @test56(1088; CHECK-NEXT: [[Y:%.*]] = sub i32 0, [[B:%.*]]1089; CHECK-NEXT: ret i32 [[Y]]1090;1091 %X = add i32 %A, %B1092 %Y = sub i32 %A, %X1093 ret i32 %Y1094}1095 1096define i32 @test57(i32 %A, i32 %B) {1097; CHECK-LABEL: @test57(1098; CHECK-NEXT: [[Y:%.*]] = sub i32 0, [[B:%.*]]1099; CHECK-NEXT: ret i32 [[Y]]1100;1101 %X = add i32 %B, %A1102 %Y = sub i32 %A, %X1103 ret i32 %Y1104}1105 1106@dummy_global1 = external global ptr1107@dummy_global2 = external global ptr1108 1109define i64 @test58(ptr %foo, i64 %i, i64 %j) {1110; CHECK-LABEL: @test58(1111; CHECK-NEXT: [[GEPDIFF:%.*]] = sub i64 [[I:%.*]], [[J:%.*]]1112; CHECK-NEXT: ret i64 [[GEPDIFF]]1113;1114 %gep1 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 %i1115 %gep2 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 %j1116 %cast1 = ptrtoint ptr %gep1 to i641117 %cast2 = ptrtoint ptr %gep2 to i641118 %sub = sub i64 %cast1, %cast21119 ret i64 %sub1120}1121 1122define i64 @test59(ptr %foo, i64 %i) {1123; CHECK-LABEL: @test59(1124; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i8, ptr [[FOO:%.*]], i64 [[I:%.*]]1125; CHECK-NEXT: [[GEP1:%.*]] = getelementptr i8, ptr [[TMP1]], i64 42001126; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds nuw i8, ptr [[FOO]], i64 42001127; CHECK-NEXT: store ptr [[GEP1]], ptr @dummy_global1, align 81128; CHECK-NEXT: store ptr [[GEP2]], ptr @dummy_global2, align 81129; CHECK-NEXT: ret i64 [[I]]1130;1131; gep1 and gep2 have more than one uses1132 %gep1 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 %i1133 %gep2 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 01134 %cast1 = ptrtoint ptr %gep1 to i641135 %cast2 = ptrtoint ptr %gep2 to i641136 %sub = sub i64 %cast1, %cast21137 store ptr %gep1, ptr @dummy_global11138 store ptr %gep2, ptr @dummy_global21139 ret i64 %sub1140}1141 1142define i64 @test60(ptr %foo, i64 %i, i64 %j) {1143; CHECK-LABEL: @test60(1144; CHECK-NEXT: [[GEP1_SPLIT_IDX:%.*]] = mul nsw i64 [[J:%.*]], 1001145; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[GEP1_SPLIT_IDX]], [[I:%.*]]1146; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[TMP1]]1147; CHECK-NEXT: [[GEPDIFF:%.*]] = add nsw i64 [[TMP1]], -42001148; CHECK-NEXT: store ptr [[GEP1]], ptr @dummy_global1, align 81149; CHECK-NEXT: ret i64 [[GEPDIFF]]1150;1151; gep1 has a non-constant index and more than one uses. Shouldn't duplicate the arithmetic.1152 %gep1 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 %j, i64 %i1153 %gep2 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 01154 %cast1 = ptrtoint ptr %gep1 to i641155 %cast2 = ptrtoint ptr %gep2 to i641156 %sub = sub i64 %cast1, %cast21157 store ptr %gep1, ptr @dummy_global11158 ret i64 %sub1159}1160 1161define i64 @test60_nuw(ptr %foo, i64 %i, i64 %j) {1162; CHECK-LABEL: @test60_nuw(1163; CHECK-NEXT: [[GEP1_SPLIT_IDX:%.*]] = mul nuw i64 [[J:%.*]], 1001164; CHECK-NEXT: [[TMP1:%.*]] = add nuw i64 [[GEP1_SPLIT_IDX]], [[I:%.*]]1165; CHECK-NEXT: [[GEP1:%.*]] = getelementptr nuw i8, ptr [[FOO:%.*]], i64 [[TMP1]]1166; CHECK-NEXT: [[GEPDIFF:%.*]] = add i64 [[TMP1]], -42001167; CHECK-NEXT: store ptr [[GEP1]], ptr @dummy_global1, align 81168; CHECK-NEXT: ret i64 [[GEPDIFF]]1169;1170 %gep1 = getelementptr nuw [100 x [100 x i8]], ptr %foo, i64 0, i64 %j, i64 %i1171 %gep2 = getelementptr nuw [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 01172 %cast1 = ptrtoint ptr %gep1 to i641173 %cast2 = ptrtoint ptr %gep2 to i641174 %sub = sub i64 %cast1, %cast21175 store ptr %gep1, ptr @dummy_global11176 ret i64 %sub1177}1178 1179define i64 @test61(ptr %foo, i64 %i, i64 %j) {1180; CHECK-LABEL: @test61(1181; CHECK-NEXT: [[GEP2_SPLIT_IDX:%.*]] = mul nsw i64 [[J:%.*]], 1001182; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[GEP2_SPLIT_IDX]], [[I:%.*]]1183; CHECK-NEXT: [[GEP2:%.*]] = getelementptr inbounds i8, ptr [[FOO:%.*]], i64 [[TMP1]]1184; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 4200, [[TMP1]]1185; CHECK-NEXT: store ptr [[GEP2]], ptr @dummy_global2, align 81186; CHECK-NEXT: ret i64 [[GEPDIFF]]1187;1188; gep2 has a non-constant index and more than one uses. Shouldn't duplicate the arithmetic.1189 %gep1 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 42, i64 01190 %gep2 = getelementptr inbounds [100 x [100 x i8]], ptr %foo, i64 0, i64 %j, i64 %i1191 %cast1 = ptrtoint ptr %gep1 to i641192 %cast2 = ptrtoint ptr %gep2 to i641193 %sub = sub i64 %cast1, %cast21194 store ptr %gep2, ptr @dummy_global21195 ret i64 %sub1196}1197 1198declare void @use.ptr(ptr)1199 1200define i64 @test_sub_ptradd_multiuse(ptr %p, i64 %idx1, i64 %idx2) {1201; CHECK-LABEL: @test_sub_ptradd_multiuse(1202; CHECK-NEXT: [[P1:%.*]] = getelementptr inbounds i8, ptr [[P:%.*]], i64 [[IDX1:%.*]]1203; CHECK-NEXT: call void @use.ptr(ptr [[P1]])1204; CHECK-NEXT: [[GEPDIFF:%.*]] = sub nsw i64 [[IDX1]], [[IDX2:%.*]]1205; CHECK-NEXT: ret i64 [[GEPDIFF]]1206;1207 %p1 = getelementptr inbounds i8, ptr %p, i64 %idx11208 call void @use.ptr(ptr %p1)1209 %p2 = getelementptr inbounds i8, ptr %p, i64 %idx21210 %p1.int = ptrtoint ptr %p1 to i641211 %p2.int = ptrtoint ptr %p2 to i641212 %sub = sub i64 %p1.int, %p2.int1213 ret i64 %sub1214}1215 1216define i32 @test62(i32 %A) {1217; CHECK-LABEL: @test62(1218; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A:%.*]], 11219; CHECK-NEXT: [[C:%.*]] = sub i32 2, [[TMP1]]1220; CHECK-NEXT: ret i32 [[C]]1221;1222 %B = sub i32 1, %A1223 %C = shl i32 %B, 11224 ret i32 %C1225}1226 1227define <2 x i32> @test62vec(<2 x i32> %A) {1228; CHECK-LABEL: @test62vec(1229; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[A:%.*]], splat (i32 1)1230; CHECK-NEXT: [[C:%.*]] = sub <2 x i32> splat (i32 2), [[TMP1]]1231; CHECK-NEXT: ret <2 x i32> [[C]]1232;1233 %B = sub <2 x i32> <i32 1, i32 1>, %A1234 %C = shl <2 x i32> %B, <i32 1, i32 1>1235 ret <2 x i32> %C1236}1237 1238define i32 @test63(i32 %A) {1239; CHECK-LABEL: @test63(1240; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[A:%.*]], 11241; CHECK-NEXT: ret i32 [[TMP1]]1242;1243 %B = sub i32 1, %A1244 %C = shl i32 %B, 11245 %D = sub i32 2, %C1246 ret i32 %D1247}1248 1249define <2 x i32> @test63vec(<2 x i32> %A) {1250; CHECK-LABEL: @test63vec(1251; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[A:%.*]], splat (i32 1)1252; CHECK-NEXT: ret <2 x i32> [[TMP1]]1253;1254 %B = sub <2 x i32> <i32 1, i32 1>, %A1255 %C = shl <2 x i32> %B, <i32 1, i32 1>1256 %D = sub <2 x i32> <i32 2, i32 2>, %C1257 ret <2 x i32> %D1258}1259 1260define i32 @test64(i32 %x) {1261; CHECK-LABEL: @test64(1262; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.smin.i32(i32 [[X:%.*]], i32 255)1263; CHECK-NEXT: [[DOTNEG:%.*]] = add nsw i32 [[TMP1]], 11264; CHECK-NEXT: ret i32 [[DOTNEG]]1265;1266 %1 = xor i32 %x, -11267 %2 = icmp sgt i32 %1, -2561268 %3 = select i1 %2, i32 %1, i32 -2561269 %res = sub i32 0, %31270 ret i32 %res1271}1272 1273define i32 @test65(i32 %x) {1274; CHECK-LABEL: @test65(1275; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 -256)1276; CHECK-NEXT: [[DOTNEG:%.*]] = add i32 [[TMP1]], 11277; CHECK-NEXT: ret i32 [[DOTNEG]]1278;1279 %1 = xor i32 %x, -11280 %2 = icmp slt i32 %1, 2551281 %3 = select i1 %2, i32 %1, i32 2551282 %res = sub i32 0, %31283 ret i32 %res1284}1285 1286define i32 @test66(i32 %x) {1287; CHECK-LABEL: @test66(1288; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 -101)1289; CHECK-NEXT: [[DOTNEG:%.*]] = add nuw i32 [[TMP1]], 11290; CHECK-NEXT: ret i32 [[DOTNEG]]1291;1292 %1 = xor i32 %x, -11293 %2 = icmp ugt i32 %1, 1001294 %3 = select i1 %2, i32 %1, i32 1001295 %res = sub i32 0, %31296 ret i32 %res1297}1298 1299define i32 @test67(i32 %x) {1300; CHECK-LABEL: @test67(1301; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X:%.*]], i32 100)1302; CHECK-NEXT: [[DOTNEG:%.*]] = add i32 [[TMP1]], 11303; CHECK-NEXT: ret i32 [[DOTNEG]]1304;1305 %1 = xor i32 %x, -11306 %2 = icmp ult i32 %1, -1011307 %3 = select i1 %2, i32 %1, i32 -1011308 %res = sub i32 0, %31309 ret i32 %res1310}1311 1312; Check splat vectors too1313define <2 x i32> @test68(<2 x i32> %x) {1314; CHECK-LABEL: @test68(1315; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> splat (i32 255))1316; CHECK-NEXT: [[DOTNEG:%.*]] = add nsw <2 x i32> [[TMP1]], splat (i32 1)1317; CHECK-NEXT: ret <2 x i32> [[DOTNEG]]1318;1319 %1 = xor <2 x i32> %x, <i32 -1, i32 -1>1320 %2 = icmp sgt <2 x i32> %1, <i32 -256, i32 -256>1321 %3 = select <2 x i1> %2, <2 x i32> %1, <2 x i32> <i32 -256, i32 -256>1322 %res = sub <2 x i32> zeroinitializer, %31323 ret <2 x i32> %res1324}1325 1326; And non-splat constant vectors.1327define <2 x i32> @test69(<2 x i32> %x) {1328; CHECK-LABEL: @test69(1329; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.smin.v2i32(<2 x i32> [[X:%.*]], <2 x i32> <i32 255, i32 127>)1330; CHECK-NEXT: [[DOTNEG:%.*]] = add <2 x i32> [[TMP1]], splat (i32 1)1331; CHECK-NEXT: ret <2 x i32> [[DOTNEG]]1332;1333 %1 = xor <2 x i32> %x, <i32 -1, i32 -1>1334 %2 = icmp sgt <2 x i32> %1, <i32 -256, i32 -128>1335 %3 = select <2 x i1> %2, <2 x i32> %1, <2 x i32> <i32 -256, i32 -128>1336 %res = sub <2 x i32> zeroinitializer, %31337 ret <2 x i32> %res1338}1339 1340; Check (X | Y) - Y --> X & ~Y when Y is a constant1341define i32 @test70(i32 %A) {1342; CHECK-LABEL: @test70(1343; CHECK-NEXT: [[C:%.*]] = and i32 [[A:%.*]], -1241344; CHECK-NEXT: ret i32 [[C]]1345;1346 %B = or i32 %A, 1231347 %C = sub i32 %B, 1231348 ret i32 %C1349}1350 1351; Check (X | Y) - Y --> (X | Y) ^ Y doesn't happen where (X | Y) has multiple uses1352define i32 @test71(i32 %A, i32 %B) {1353; CHECK-LABEL: @test71(1354; CHECK-NEXT: [[C:%.*]] = or i32 [[A:%.*]], [[B:%.*]]1355; CHECK-NEXT: [[D:%.*]] = sub i32 [[C]], [[B]]1356; CHECK-NEXT: [[E:%.*]] = mul i32 [[C]], [[D]]1357; CHECK-NEXT: ret i32 [[E]]1358;1359 %C = or i32 %A, %B1360 %D = sub i32 %C, %B1361 %E = mul i32 %C, %D1362 ret i32 %E1363}1364 1365; Check (X | Y) - Y --> X & ~Y where X and Y are vectors1366define <2 x i32> @test72(<2 x i32> %A, <2 x i32> %B) {1367; CHECK-LABEL: @test72(1368; CHECK-NEXT: [[B_NOT:%.*]] = xor <2 x i32> [[B:%.*]], splat (i32 -1)1369; CHECK-NEXT: [[D:%.*]] = and <2 x i32> [[A:%.*]], [[B_NOT]]1370; CHECK-NEXT: ret <2 x i32> [[D]]1371;1372 %C = or <2 x i32> %A, %B1373 %D = sub <2 x i32> %C, %B1374 ret <2 x i32> %D1375}1376 1377; Check reversing sub operands won't trigger (X | Y) - Y --> X & ~Y1378define i32 @test73(i32 %A, i32 %B) {1379; CHECK-LABEL: @test73(1380; CHECK-NEXT: [[C:%.*]] = or i32 [[A:%.*]], [[B:%.*]]1381; CHECK-NEXT: [[D:%.*]] = sub i32 [[B]], [[C]]1382; CHECK-NEXT: ret i32 [[D]]1383;1384 %C = or i32 %A, %B1385 %D = sub i32 %B, %C1386 ret i32 %D1387}1388 1389define i32 @nsw_inference1(i32 %x, i32 %y) {1390; CHECK-LABEL: @nsw_inference1(1391; CHECK-NEXT: [[X2:%.*]] = or i32 [[X:%.*]], 10241392; CHECK-NEXT: [[Y2:%.*]] = and i32 [[Y:%.*]], 11393; CHECK-NEXT: [[Z:%.*]] = sub nuw nsw i32 [[X2]], [[Y2]]1394; CHECK-NEXT: ret i32 [[Z]]1395;1396 %x2 = or i32 %x, 10241397 %y2 = and i32 %y, 11398 %z = sub i32 %x2, %y21399 ret i32 %z1400}1401 1402define i32 @nsw_inference2(i32 %x, i32 %y) {1403; CHECK-LABEL: @nsw_inference2(1404; CHECK-NEXT: [[X2:%.*]] = and i32 [[X:%.*]], -10251405; CHECK-NEXT: [[Y2:%.*]] = or i32 [[Y:%.*]], -21406; CHECK-NEXT: [[Z:%.*]] = sub nsw i32 [[X2]], [[Y2]]1407; CHECK-NEXT: ret i32 [[Z]]1408;1409 %x2 = and i32 %x, -10251410 %y2 = or i32 %y, -21411 %z = sub i32 %x2, %y21412 ret i32 %z1413}1414 1415define i8 @test74(i8 %x, i8 %y) {1416; CHECK-LABEL: @test74(1417; CHECK-NEXT: [[T0:%.*]] = and i8 [[X:%.*]], [[Y:%.*]]1418; CHECK-NEXT: call void @use8(i8 [[T0]])1419; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]1420; CHECK-NEXT: ret i8 [[T1]]1421;1422 %t0 = and i8 %x, %y1423 call void @use8(i8 %t0)1424 %t1 = sub i8 %x, %t01425 ret i8 %t11426}1427 1428define i8 @test75(i8 %x) {1429; CHECK-LABEL: @test75(1430; CHECK-NEXT: [[T0:%.*]] = and i8 [[X:%.*]], -81431; CHECK-NEXT: call void @use8(i8 [[T0]])1432; CHECK-NEXT: [[T1:%.*]] = and i8 [[X]], 71433; CHECK-NEXT: ret i8 [[T1]]1434;1435 %t0 = and i8 %x, -81436 call void @use8(i8 %t0)1437 %t1 = sub i8 %x, %t01438 ret i8 %t11439}1440 1441; ((w-x) + y) - z --> (w+y) - (x+z)1442 1443define i8 @sub_add_sub_reassoc(i8 %w, i8 %x, i8 %y, i8 %z) {1444; CHECK-LABEL: @sub_add_sub_reassoc(1445; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[W:%.*]], [[Y:%.*]]1446; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X:%.*]], [[Z:%.*]]1447; CHECK-NEXT: [[S2:%.*]] = sub i8 [[TMP1]], [[TMP2]]1448; CHECK-NEXT: ret i8 [[S2]]1449;1450 %s1 = sub i8 %w, %x1451 %a = add i8 %s1, %y1452 %s2 = sub i8 %a, %z1453 ret i8 %s21454}1455 1456; vectors work too.1457 1458define <2 x i8> @sub_add_sub_reassoc_commute(<2 x i8> %w, <2 x i8> %x, <2 x i8> %y, <2 x i8> %z) {1459; CHECK-LABEL: @sub_add_sub_reassoc_commute(1460; CHECK-NEXT: [[D:%.*]] = sdiv <2 x i8> [[Y:%.*]], <i8 42, i8 -42>1461; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i8> [[W:%.*]], [[D]]1462; CHECK-NEXT: [[TMP2:%.*]] = add <2 x i8> [[X:%.*]], [[Z:%.*]]1463; CHECK-NEXT: [[S2:%.*]] = sub <2 x i8> [[TMP1]], [[TMP2]]1464; CHECK-NEXT: ret <2 x i8> [[S2]]1465;1466 %d = sdiv <2 x i8> %y, <i8 42, i8 -42> ; thwart complexity-based canonicalization1467 %s1 = sub <2 x i8> %w, %x1468 %a = add <2 x i8> %d, %s11469 %s2 = sub <2 x i8> %a, %z1470 ret <2 x i8> %s21471}1472 1473; (v-w) + (x-y) - z --> (v+x) - (w+y+z)1474 1475define i8 @sub_add_sub_reassoc_twice(i8 %v, i8 %w, i8 %x, i8 %y, i8 %z) {1476; CHECK-LABEL: @sub_add_sub_reassoc_twice(1477; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[W:%.*]], [[Z:%.*]]1478; CHECK-NEXT: [[TMP2:%.*]] = add i8 [[X:%.*]], [[V:%.*]]1479; CHECK-NEXT: [[TMP3:%.*]] = add i8 [[Y:%.*]], [[TMP1]]1480; CHECK-NEXT: [[S3:%.*]] = sub i8 [[TMP2]], [[TMP3]]1481; CHECK-NEXT: ret i8 [[S3]]1482;1483 %s1 = sub i8 %v, %w1484 %s2 = sub i8 %x, %y1485 %a = add i8 %s1, %s21486 %s3 = sub i8 %a, %z1487 ret i8 %s31488}1489 1490; negative test - uses1491 1492define i8 @sub_add_sub_reassoc_use1(i8 %w, i8 %x, i8 %y, i8 %z) {1493; CHECK-LABEL: @sub_add_sub_reassoc_use1(1494; CHECK-NEXT: [[S1:%.*]] = sub i8 [[W:%.*]], [[X:%.*]]1495; CHECK-NEXT: call void @use8(i8 [[S1]])1496; CHECK-NEXT: [[A:%.*]] = add i8 [[S1]], [[Y:%.*]]1497; CHECK-NEXT: [[S2:%.*]] = sub i8 [[A]], [[Z:%.*]]1498; CHECK-NEXT: ret i8 [[S2]]1499;1500 %s1 = sub i8 %w, %x1501 call void @use8(i8 %s1)1502 %a = add i8 %s1, %y1503 %s2 = sub i8 %a, %z1504 ret i8 %s21505}1506 1507; negative test - uses1508 1509define i8 @sub_add_sub_reassoc_use2(i8 %w, i8 %x, i8 %y, i8 %z) {1510; CHECK-LABEL: @sub_add_sub_reassoc_use2(1511; CHECK-NEXT: [[S1:%.*]] = sub i8 [[W:%.*]], [[X:%.*]]1512; CHECK-NEXT: [[A:%.*]] = add i8 [[S1]], [[Y:%.*]]1513; CHECK-NEXT: call void @use8(i8 [[A]])1514; CHECK-NEXT: [[S2:%.*]] = sub i8 [[A]], [[Z:%.*]]1515; CHECK-NEXT: ret i8 [[S2]]1516;1517 %s1 = sub i8 %w, %x1518 %a = add i8 %s1, %y1519 call void @use8(i8 %a)1520 %s2 = sub i8 %a, %z1521 ret i8 %s21522}1523 1524define i8 @sub_mask_lowbits(i8 %x) {1525; CHECK-LABEL: @sub_mask_lowbits(1526; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X:%.*]], -41527; CHECK-NEXT: [[R:%.*]] = add i8 [[TMP1]], -1081528; CHECK-NEXT: ret i8 [[R]]1529;1530 %a1 = add i8 %x, 148 ; 0x941531 %a2 = and i8 %x, 31532 %r = sub i8 %a1, %a21533 ret i8 %r1534}1535 1536; Negative test - low-bit mask must not overlap with offset1537 1538define i8 @sub_not_mask_lowbits(i8 %x) {1539; CHECK-LABEL: @sub_not_mask_lowbits(1540; CHECK-NEXT: [[A1:%.*]] = add i8 [[X:%.*]], 41541; CHECK-NEXT: [[A2:%.*]] = and i8 [[X]], 71542; CHECK-NEXT: [[R:%.*]] = sub i8 [[A1]], [[A2]]1543; CHECK-NEXT: ret i8 [[R]]1544;1545 %a1 = add i8 %x, 41546 %a2 = and i8 %x, 71547 %r = sub i8 %a1, %a21548 ret i8 %r1549}1550 1551define <2 x i8> @sub_mask_lowbits_splat_extra_use(<2 x i8> %x, ptr %p) {1552; CHECK-LABEL: @sub_mask_lowbits_splat_extra_use(1553; CHECK-NEXT: [[A2:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 10)1554; CHECK-NEXT: store <2 x i8> [[A2]], ptr [[P:%.*]], align 21555; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X]], splat (i8 -11)1556; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[TMP1]], splat (i8 -64)1557; CHECK-NEXT: ret <2 x i8> [[R]]1558;1559 %a1 = add <2 x i8> %x, <i8 192, i8 192> ; 0xc01560 %a2 = and <2 x i8> %x, <i8 10, i8 10> ; 0x0a1561 store <2 x i8> %a2, ptr %p1562 %r = sub <2 x i8> %a1, %a21563 ret <2 x i8> %r1564}1565 1566define i16 @sub_nsw_mul_nsw(i16 %x, i16 %y) {1567; CHECK-LABEL: @sub_nsw_mul_nsw(1568; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i16 [[X:%.*]], [[Y:%.*]]1569; CHECK-NEXT: [[R:%.*]] = shl nsw i16 [[TMP1]], 31570; CHECK-NEXT: ret i16 [[R]]1571;1572 %x8 = mul nsw i16 %x, 81573 %y8 = mul nsw i16 %y, 81574 %r = sub nsw i16 %x8, %y81575 ret i16 %r1576}1577 1578define i16 @sub_nuw_mul_nsw(i16 %x, i16 %y) {1579; CHECK-LABEL: @sub_nuw_mul_nsw(1580; CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[X:%.*]], [[Y:%.*]]1581; CHECK-NEXT: [[R:%.*]] = shl i16 [[TMP1]], 21582; CHECK-NEXT: ret i16 [[R]]1583;1584 %x8 = mul nsw i16 %x, 41585 %y8 = mul nsw i16 %y, 41586 %r = sub nuw i16 %x8, %y81587 ret i16 %r1588}1589 1590define i16 @sub_mul_nsw(i16 %x, i16 %y) {1591; CHECK-LABEL: @sub_mul_nsw(1592; CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[X:%.*]], [[Y:%.*]]1593; CHECK-NEXT: [[R:%.*]] = shl i16 [[TMP1]], 41594; CHECK-NEXT: ret i16 [[R]]1595;1596 %x8 = mul nsw i16 %x, 161597 %y8 = mul nsw i16 %y, 161598 %r = sub i16 %x8, %y81599 ret i16 %r1600}1601 1602define i16 @sub_nsw_mul_nuw(i16 %x, i16 %y) {1603; CHECK-LABEL: @sub_nsw_mul_nuw(1604; CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[X:%.*]], [[Y:%.*]]1605; CHECK-NEXT: [[R:%.*]] = shl i16 [[TMP1]], 31606; CHECK-NEXT: ret i16 [[R]]1607;1608 %x8 = mul nuw i16 %x, 81609 %y8 = mul nuw i16 %y, 81610 %r = sub nsw i16 %x8, %y81611 ret i16 %r1612}1613 1614define i16 @sub_nuw_mul_nuw(i16 %x, i16 %y) {1615; CHECK-LABEL: @sub_nuw_mul_nuw(1616; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i16 [[X:%.*]], [[Y:%.*]]1617; CHECK-NEXT: [[R:%.*]] = shl nuw i16 [[TMP1]], 41618; CHECK-NEXT: ret i16 [[R]]1619;1620 %x8 = mul nuw i16 %x, 161621 %y8 = mul nuw i16 %y, 161622 %r = sub nuw i16 %x8, %y81623 ret i16 %r1624}1625 1626define i16 @sub_mul_nuw(i16 %x, i16 %y) {1627; CHECK-LABEL: @sub_mul_nuw(1628; CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[X:%.*]], [[Y:%.*]]1629; CHECK-NEXT: [[R:%.*]] = shl i16 [[TMP1]], 51630; CHECK-NEXT: ret i16 [[R]]1631;1632 %x8 = mul nuw i16 %x, 321633 %y8 = mul nuw i16 %y, 321634 %r = sub i16 %x8, %y81635 ret i16 %r1636}1637define i32 @and_test(i32 %x, i32 %y) {1638; CHECK-LABEL: @and_test(1639; CHECK-NEXT: [[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]1640; CHECK-NEXT: ret i32 [[R]]1641;1642 %a = add i32 %x, %y1643 %o = or i32 %x, %y1644 %r = sub i32 %a, %o1645 ret i32 %r1646}1647 1648define i32 @and_test2(i32 %x, i32 %y) {1649; CHECK-LABEL: @and_test2(1650; CHECK-NEXT: [[R:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]1651; CHECK-NEXT: ret i32 [[R]]1652;1653 %a = add i32 %x, %y1654 %o = or i32 %y, %x1655 %r = sub i32 %a, %o1656 ret i32 %r1657}1658 1659define i32 @and_test3(i32 %x, i32 %y) {1660; CHECK-LABEL: @and_test3(1661; CHECK-NEXT: [[R:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]1662; CHECK-NEXT: ret i32 [[R]]1663;1664 %a = add i32 %y, %x1665 %o = or i32 %x, %y1666 %r = sub i32 %a, %o1667 ret i32 %r1668}1669 1670 1671define <2 x i8> @and_vec(<2 x i8> %X, <2 x i8> %Y) {1672; CHECK-LABEL: @and_vec(1673; CHECK-NEXT: [[R:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]]1674; CHECK-NEXT: ret <2 x i8> [[R]]1675;1676 %a = add <2 x i8> %X, %Y1677 %o = or <2 x i8> %X, %Y1678 %r = sub <2 x i8> %a, %o1679 ret <2 x i8> %r1680}1681 1682define i32 @or_test(i32 %x, i32 %y) {1683; CHECK-LABEL: @or_test(1684; CHECK-NEXT: [[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]1685; CHECK-NEXT: ret i32 [[R]]1686;1687 %a = add i32 %x, %y1688 %b = and i32 %x, %y1689 %r = sub i32 %a, %b1690 ret i32 %r1691}1692 1693define i32 @or_test2(i32 %x, i32 %y) {1694; CHECK-LABEL: @or_test2(1695; CHECK-NEXT: [[R:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]1696; CHECK-NEXT: ret i32 [[R]]1697;1698 %a = add i32 %x, %y1699 %b = and i32 %y, %x1700 %r = sub i32 %a, %b1701 ret i32 %r1702}1703 1704define i32 @or_test3(i32 %x, i32 %y) {1705; CHECK-LABEL: @or_test3(1706; CHECK-NEXT: [[R:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]1707; CHECK-NEXT: ret i32 [[R]]1708;1709 %a = add i32 %y, %x1710 %b = and i32 %x, %y1711 %r = sub i32 %a, %b1712 ret i32 %r1713}1714 1715define <2 x i8> @or_vec(<2 x i8> %X, <2 x i8> %Y) {1716; CHECK-LABEL: @or_vec(1717; CHECK-NEXT: [[R:%.*]] = or <2 x i8> [[X:%.*]], [[Y:%.*]]1718; CHECK-NEXT: ret <2 x i8> [[R]]1719;1720 %a = add <2 x i8> %X, %Y1721 %b = and <2 x i8> %X, %Y1722 %r = sub <2 x i8> %a, %b1723 ret <2 x i8> %r1724}1725 1726define i32 @pr51584(i32 %a, i32 %b) {1727; CHECK-LABEL: @pr51584(1728; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[B:%.*]], [[A:%.*]]1729; CHECK-NEXT: [[DOTNEG:%.*]] = sub i32 -11, [[TMP1]]1730; CHECK-NEXT: ret i32 [[DOTNEG]]1731;1732 %sub = sub i32 0, %a1733 %add = add nsw i32 11, %b1734 %sub1 = sub i32 %sub, %add1735 ret i32 %sub11736}1737 1738define i8 @sub_srem(i8 noundef %x, i8 %y) {1739; CHECK-LABEL: @sub_srem(1740; CHECK-NEXT: [[REM:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]]1741; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[X]], [[REM]]1742; CHECK-NEXT: ret i8 [[SUB]]1743;1744 %rem = srem i8 %x, %y1745 %sub = sub i8 %x, %rem1746 ret i8 %sub1747}1748 1749define <2 x i5> @sub_urem(<2 x i5> noundef %x, <2 x i5> %y) {1750; CHECK-LABEL: @sub_urem(1751; CHECK-NEXT: [[REM:%.*]] = urem <2 x i5> [[X:%.*]], [[Y:%.*]]1752; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i5> [[X]], [[REM]]1753; CHECK-NEXT: ret <2 x i5> [[SUB]]1754;1755 %rem = urem <2 x i5> %x, %y1756 %sub = sub <2 x i5> %x, %rem1757 ret <2 x i5> %sub1758}1759 1760define <3 x i32> @nuw_const_zext(<3 x i8> %y) {1761; CHECK-LABEL: @nuw_const_zext(1762; CHECK-NEXT: [[ZY:%.*]] = zext <3 x i8> [[Y:%.*]] to <3 x i32>1763; CHECK-NEXT: [[S:%.*]] = sub nuw nsw <3 x i32> <i32 255, i32 128, i32 0>, [[ZY]]1764; CHECK-NEXT: ret <3 x i32> [[S]]1765;1766 %zy = zext <3 x i8> %y to <3 x i32>1767 %s = sub nuw <3 x i32> <i32 255, i32 128, i32 0>, %zy1768 ret <3 x i32> %s1769}1770 1771define i32 @nuw_const_zext_big(i8 %y) {1772; CHECK-LABEL: @nuw_const_zext_big(1773; CHECK-NEXT: [[ZY:%.*]] = zext i8 [[Y:%.*]] to i321774; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i32 257, [[ZY]]1775; CHECK-NEXT: ret i32 [[S]]1776;1777 %zy = zext i8 %y to i321778 %s = sub nuw i32 257, %zy1779 ret i32 %s1780}1781 1782define i32 @nuw_zext_zext(i8 %x, i8 %y) {1783; CHECK-LABEL: @nuw_zext_zext(1784; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i321785; CHECK-NEXT: [[ZY:%.*]] = zext i8 [[Y:%.*]] to i321786; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i32 [[ZX]], [[ZY]]1787; CHECK-NEXT: ret i32 [[S]]1788;1789 %zx = zext i8 %x to i321790 %zy = zext i8 %y to i321791 %s = sub nuw i32 %zx, %zy1792 ret i32 %s1793}1794 1795define <2 x i16> @nuw_zext_sext(<2 x i8> %x, <2 x i8> %y) {1796; CHECK-LABEL: @nuw_zext_sext(1797; CHECK-NEXT: [[ZX:%.*]] = zext <2 x i8> [[X:%.*]] to <2 x i16>1798; CHECK-NEXT: [[SY:%.*]] = sext <2 x i8> [[Y:%.*]] to <2 x i16>1799; CHECK-NEXT: [[S:%.*]] = sub nuw nsw <2 x i16> [[ZX]], [[SY]]1800; CHECK-NEXT: ret <2 x i16> [[S]]1801;1802 %zx = zext <2 x i8> %x to <2 x i16>1803 %sy = sext <2 x i8> %y to <2 x i16>1804 %s = sub nuw <2 x i16> %zx, %sy1805 ret <2 x i16> %s1806}1807 1808define i32 @nuw_sext_zext(i8 %x, i8 %y) {1809; CHECK-LABEL: @nuw_sext_zext(1810; CHECK-NEXT: [[SX:%.*]] = sext i8 [[X:%.*]] to i321811; CHECK-NEXT: [[ZY:%.*]] = zext i8 [[Y:%.*]] to i321812; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i32 [[SX]], [[ZY]]1813; CHECK-NEXT: ret i32 [[S]]1814;1815 %sx = sext i8 %x to i321816 %zy = zext i8 %y to i321817 %s = sub nuw i32 %sx, %zy1818 ret i32 %s1819}1820 1821define i8 @nuw_zext_zext_use1(i5 %x, i5 %y) {1822; CHECK-LABEL: @nuw_zext_zext_use1(1823; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i81824; CHECK-NEXT: call void @use8(i8 [[ZX]])1825; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i81826; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i8 [[ZX]], [[ZY]]1827; CHECK-NEXT: ret i8 [[S]]1828;1829 %zx = zext i5 %x to i81830 call void @use8(i8 %zx)1831 %zy = zext i5 %y to i81832 %s = sub nuw i8 %zx, %zy1833 ret i8 %s1834}1835 1836define i8 @nuw_zext_zext_use2(i5 %x, i5 %y) {1837; CHECK-LABEL: @nuw_zext_zext_use2(1838; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i81839; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i81840; CHECK-NEXT: call void @use8(i8 [[ZY]])1841; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i8 [[ZX]], [[ZY]]1842; CHECK-NEXT: ret i8 [[S]]1843;1844 %zx = zext i5 %x to i81845 %zy = zext i5 %y to i81846 call void @use8(i8 %zy)1847 %s = sub nuw i8 %zx, %zy1848 ret i8 %s1849}1850 1851define i8 @nuw_zext_zext_use3(i5 %x, i5 %y) {1852; CHECK-LABEL: @nuw_zext_zext_use3(1853; CHECK-NEXT: [[ZX:%.*]] = zext i5 [[X:%.*]] to i81854; CHECK-NEXT: call void @use8(i8 [[ZX]])1855; CHECK-NEXT: [[ZY:%.*]] = zext i5 [[Y:%.*]] to i81856; CHECK-NEXT: call void @use8(i8 [[ZY]])1857; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i8 [[ZX]], [[ZY]]1858; CHECK-NEXT: ret i8 [[S]]1859;1860 %zx = zext i5 %x to i81861 call void @use8(i8 %zx)1862 %zy = zext i5 %y to i81863 call void @use8(i8 %zy)1864 %s = sub nuw i8 %zx, %zy1865 ret i8 %s1866}1867 1868define i32 @nuw_zext_zext_different_width(i8 %x, i7 %y) {1869; CHECK-LABEL: @nuw_zext_zext_different_width(1870; CHECK-NEXT: [[ZX:%.*]] = zext i8 [[X:%.*]] to i321871; CHECK-NEXT: [[ZY:%.*]] = zext i7 [[Y:%.*]] to i321872; CHECK-NEXT: [[S:%.*]] = sub nuw nsw i32 [[ZX]], [[ZY]]1873; CHECK-NEXT: ret i32 [[S]]1874;1875 %zx = zext i8 %x to i321876 %zy = zext i7 %y to i321877 %s = sub nuw i32 %zx, %zy1878 ret i32 %s1879}1880 1881define i16 @sext_nsw_noundef(i8 noundef %x, i8 %y) {1882; CHECK-LABEL: @sext_nsw_noundef(1883; CHECK-NEXT: [[Z:%.*]] = sext i8 [[Y:%.*]] to i161884; CHECK-NEXT: ret i16 [[Z]]1885;1886 %d = sub nsw i8 %x, %y1887 %ex = sext i8 %x to i161888 %ed = sext i8 %d to i161889 %z = sub i16 %ex, %ed1890 ret i16 %z1891}1892 1893; negative test - requires noundef1894 1895define i16 @sext_nsw(i8 %x, i8 %y) {1896; CHECK-LABEL: @sext_nsw(1897; CHECK-NEXT: [[D:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]1898; CHECK-NEXT: [[EX:%.*]] = sext i8 [[X]] to i161899; CHECK-NEXT: [[ED:%.*]] = sext i8 [[D]] to i161900; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EX]], [[ED]]1901; CHECK-NEXT: ret i16 [[Z]]1902;1903 %d = sub nsw i8 %x, %y1904 %ex = sext i8 %x to i161905 %ed = sext i8 %d to i161906 %z = sub i16 %ex, %ed1907 ret i16 %z1908}1909 1910; negative test - requires nsw1911 1912define i16 @sext_noundef(i8 noundef %x, i8 %y) {1913; CHECK-LABEL: @sext_noundef(1914; CHECK-NEXT: [[D:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]1915; CHECK-NEXT: [[EX:%.*]] = sext i8 [[X]] to i161916; CHECK-NEXT: [[ED:%.*]] = sext i8 [[D]] to i161917; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EX]], [[ED]]1918; CHECK-NEXT: ret i16 [[Z]]1919;1920 %d = sub i8 %x, %y1921 %ex = sext i8 %x to i161922 %ed = sext i8 %d to i161923 %z = sub i16 %ex, %ed1924 ret i16 %z1925}1926 1927; negative test - must have common operand1928 1929define i16 @sext_nsw_noundef_wrong_val(i8 noundef %x, i8 noundef %y, i8 noundef %q) {1930; CHECK-LABEL: @sext_nsw_noundef_wrong_val(1931; CHECK-NEXT: [[D:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]1932; CHECK-NEXT: [[EQ:%.*]] = sext i8 [[Q:%.*]] to i161933; CHECK-NEXT: [[ED:%.*]] = sext i8 [[D]] to i161934; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EQ]], [[ED]]1935; CHECK-NEXT: ret i16 [[Z]]1936;1937 %d = sub nsw i8 %x, %y1938 %eq = sext i8 %q to i161939 %ed = sext i8 %d to i161940 %z = sub i16 %eq, %ed1941 ret i16 %z1942}1943 1944; two no-wrap analyses combine to allow reduction1945 1946define i16 @srem_sext_noundef(i8 noundef %x, i8 %y) {1947; CHECK-LABEL: @srem_sext_noundef(1948; CHECK-NEXT: [[R:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]]1949; CHECK-NEXT: [[Z:%.*]] = sext i8 [[R]] to i161950; CHECK-NEXT: ret i16 [[Z]]1951;1952 %r = srem i8 %x, %y1953 %d = sub i8 %x, %r1954 %sd = sext i8 %d to i161955 %sx = sext i8 %x to i161956 %z = sub i16 %sx, %sd1957 ret i16 %z1958}1959 1960define i16 @zext_nuw_noundef(i8 noundef %x, i8 %y) {1961; CHECK-LABEL: @zext_nuw_noundef(1962; CHECK-NEXT: [[Z:%.*]] = zext i8 [[Y:%.*]] to i161963; CHECK-NEXT: ret i16 [[Z]]1964;1965 %d = sub nuw i8 %x, %y1966 %ex = zext i8 %x to i161967 %ed = zext i8 %d to i161968 %z = sub i16 %ex, %ed1969 ret i16 %z1970}1971 1972; negative test - requires noundef1973 1974define i16 @zext_nuw(i8 %x, i8 %y) {1975; CHECK-LABEL: @zext_nuw(1976; CHECK-NEXT: [[D:%.*]] = sub nuw i8 [[X:%.*]], [[Y:%.*]]1977; CHECK-NEXT: [[EX:%.*]] = zext i8 [[X]] to i161978; CHECK-NEXT: [[ED:%.*]] = zext i8 [[D]] to i161979; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EX]], [[ED]]1980; CHECK-NEXT: ret i16 [[Z]]1981;1982 %d = sub nuw i8 %x, %y1983 %ex = zext i8 %x to i161984 %ed = zext i8 %d to i161985 %z = sub i16 %ex, %ed1986 ret i16 %z1987}1988 1989; negative test - requires nuw1990 1991define i16 @zext_noundef(i8 noundef %x, i8 %y) {1992; CHECK-LABEL: @zext_noundef(1993; CHECK-NEXT: [[D:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]1994; CHECK-NEXT: [[EX:%.*]] = zext i8 [[X]] to i161995; CHECK-NEXT: [[ED:%.*]] = zext i8 [[D]] to i161996; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EX]], [[ED]]1997; CHECK-NEXT: ret i16 [[Z]]1998;1999 %d = sub i8 %x, %y2000 %ex = zext i8 %x to i162001 %ed = zext i8 %d to i162002 %z = sub i16 %ex, %ed2003 ret i16 %z2004}2005 2006; negative test - must have common operand2007 2008define i16 @zext_nsw_noundef_wrong_val(i8 noundef %x, i8 noundef %y, i8 noundef %q) {2009; CHECK-LABEL: @zext_nsw_noundef_wrong_val(2010; CHECK-NEXT: [[D:%.*]] = sub nuw i8 [[X:%.*]], [[Y:%.*]]2011; CHECK-NEXT: [[EQ:%.*]] = zext i8 [[Q:%.*]] to i162012; CHECK-NEXT: [[ED:%.*]] = zext i8 [[D]] to i162013; CHECK-NEXT: [[Z:%.*]] = sub nsw i16 [[EQ]], [[ED]]2014; CHECK-NEXT: ret i16 [[Z]]2015;2016 %d = sub nuw i8 %x, %y2017 %eq = zext i8 %q to i162018 %ed = zext i8 %d to i162019 %z = sub i16 %eq, %ed2020 ret i16 %z2021}2022 2023; two no-wrap analyses combine to allow reduction2024 2025define i16 @urem_zext_noundef(i8 noundef %x, i8 %y) {2026; CHECK-LABEL: @urem_zext_noundef(2027; CHECK-NEXT: [[R:%.*]] = urem i8 [[X:%.*]], [[Y:%.*]]2028; CHECK-NEXT: [[Z:%.*]] = zext i8 [[R]] to i162029; CHECK-NEXT: ret i16 [[Z]]2030;2031 %r = urem i8 %x, %y2032 %d = sub i8 %x, %r2033 %ed = zext i8 %d to i162034 %ex = zext i8 %x to i162035 %z = sub i16 %ex, %ed2036 ret i16 %z2037}2038 2039; x * y - x --> (y - 1) * x2040; TODO: The mul could retain nsw.2041 2042define i8 @mul_sub_common_factor_commute1(i8 %x, i8 %y) {2043; CHECK-LABEL: @mul_sub_common_factor_commute1(2044; CHECK-NEXT: [[X1:%.*]] = add i8 [[Y:%.*]], -12045; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], [[X1]]2046; CHECK-NEXT: ret i8 [[A]]2047;2048 %m = mul nsw i8 %x, %y2049 %a = sub nsw i8 %m, %x2050 ret i8 %a2051}2052 2053; TODO: The mul could retain nuw.2054 2055define <2 x i8> @mul_sub_common_factor_commute2(<2 x i8> %x, <2 x i8> %y) {2056; CHECK-LABEL: @mul_sub_common_factor_commute2(2057; CHECK-NEXT: [[M1:%.*]] = add <2 x i8> [[Y:%.*]], splat (i8 -1)2058; CHECK-NEXT: [[A:%.*]] = mul <2 x i8> [[M1]], [[X:%.*]]2059; CHECK-NEXT: ret <2 x i8> [[A]]2060;2061 %m = mul nuw <2 x i8> %y, %x2062 %a = sub nuw <2 x i8> %m, %x2063 ret <2 x i8> %a2064}2065 2066; x - (x * y) --> (1 - y) * x2067 2068define i8 @mul_sub_common_factor_commute3(i8 %x, i8 %y) {2069; CHECK-LABEL: @mul_sub_common_factor_commute3(2070; CHECK-NEXT: [[M1:%.*]] = sub i8 1, [[Y:%.*]]2071; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], [[M1]]2072; CHECK-NEXT: ret i8 [[A]]2073;2074 %m = mul nuw i8 %x, %y2075 %a = sub nsw i8 %x, %m2076 ret i8 %a2077}2078 2079define i8 @mul_sub_common_factor_commute4(i8 %x, i8 %y) {2080; CHECK-LABEL: @mul_sub_common_factor_commute4(2081; CHECK-NEXT: [[M1:%.*]] = sub i8 1, [[Y:%.*]]2082; CHECK-NEXT: [[A:%.*]] = mul i8 [[X:%.*]], [[M1]]2083; CHECK-NEXT: ret i8 [[A]]2084;2085 %m = mul nsw i8 %y, %x2086 %a = sub nuw i8 %x, %m2087 ret i8 %a2088}2089 2090; negative test - uses2091 2092define i8 @mul_sub_common_factor_use(i8 %x, i8 %y) {2093; CHECK-LABEL: @mul_sub_common_factor_use(2094; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]2095; CHECK-NEXT: call void @use8(i8 [[M]])2096; CHECK-NEXT: [[A:%.*]] = sub i8 [[M]], [[X]]2097; CHECK-NEXT: ret i8 [[A]]2098;2099 %m = mul i8 %x, %y2100 call void @use8(i8 %m)2101 %a = sub i8 %m, %x2102 ret i8 %a2103}2104 2105define i5 @demand_low_bits_uses(i8 %x, i8 %y) {2106; CHECK-LABEL: @demand_low_bits_uses(2107; CHECK-NEXT: [[M:%.*]] = and i8 [[X:%.*]], 962108; CHECK-NEXT: [[A:%.*]] = sub i8 [[Y:%.*]], [[M]]2109; CHECK-NEXT: call void @use8(i8 [[A]])2110; CHECK-NEXT: [[R:%.*]] = trunc i8 [[Y]] to i52111; CHECK-NEXT: ret i5 [[R]]2112;2113 %m = and i8 %x, 96 ; 0x602114 %a = sub i8 %y, %m2115 call void @use8(i8 %a)2116 %r = trunc i8 %a to i52117 ret i5 %r2118}2119 2120; negative test - demands one more bit2121 2122define i6 @demand_low_bits_uses_extra_bit(i8 %x, i8 %y) {2123; CHECK-LABEL: @demand_low_bits_uses_extra_bit(2124; CHECK-NEXT: [[M:%.*]] = and i8 [[X:%.*]], 962125; CHECK-NEXT: [[A:%.*]] = sub i8 [[Y:%.*]], [[M]]2126; CHECK-NEXT: call void @use8(i8 [[A]])2127; CHECK-NEXT: [[R:%.*]] = trunc i8 [[A]] to i62128; CHECK-NEXT: ret i6 [[R]]2129;2130 %m = and i8 %x, 96 ; 0x602131 %a = sub i8 %y, %m2132 call void @use8(i8 %a)2133 %r = trunc i8 %a to i62134 ret i6 %r2135}2136 2137; negative test - must be operand 12138 2139define i8 @demand_low_bits_uses_commute(i8 %x, i8 %y, i8 %z) {2140; CHECK-LABEL: @demand_low_bits_uses_commute(2141; CHECK-NEXT: [[M:%.*]] = and i8 [[X:%.*]], -642142; CHECK-NEXT: [[A:%.*]] = sub i8 [[M]], [[Y:%.*]]2143; CHECK-NEXT: call void @use8(i8 [[A]])2144; CHECK-NEXT: [[S:%.*]] = sub i8 [[A]], [[Z:%.*]]2145; CHECK-NEXT: [[R:%.*]] = shl i8 [[S]], 22146; CHECK-NEXT: ret i8 [[R]]2147;2148 %m = and i8 %x, -64 ; 0xC02149 %a = sub i8 %m, %y2150 call void @use8(i8 %a)2151 %s = sub i8 %a, %z2152 %r = shl i8 %s, 22153 ret i8 %r2154}2155 2156; sub becomes negate and combines with shl2157 2158define i8 @shrink_sub_from_constant_lowbits(i8 %x) {2159; CHECK-LABEL: @shrink_sub_from_constant_lowbits(2160; CHECK-NEXT: [[X000_NEG:%.*]] = mul i8 [[X:%.*]], -82161; CHECK-NEXT: ret i8 [[X000_NEG]]2162;2163 %x000 = shl i8 %x, 3 ; 3 low bits are known zero2164 %sub = sub i8 7, %x0002165 %r = and i8 %sub, -8 ; 3 low bits are not demanded2166 ret i8 %r2167}2168 2169; negative test - extra use prevents shrinking '7'2170 2171define i8 @shrink_sub_from_constant_lowbits_uses(i8 %x) {2172; CHECK-LABEL: @shrink_sub_from_constant_lowbits_uses(2173; CHECK-NEXT: [[X000:%.*]] = shl i8 [[X:%.*]], 32174; CHECK-NEXT: [[SUB:%.*]] = sub i8 7, [[X000]]2175; CHECK-NEXT: call void @use8(i8 [[SUB]])2176; CHECK-NEXT: [[R:%.*]] = and i8 [[SUB]], -82177; CHECK-NEXT: ret i8 [[R]]2178;2179 %x000 = shl i8 %x, 3 ; 3 low bits are known zero2180 %sub = sub i8 7, %x0002181 call void @use8(i8 %sub)2182 %r = and i8 %sub, -8 ; 3 low bits are not demanded2183 ret i8 %r2184}2185 2186; safe to clear 3 low bits (2 higher bits remain set)2187 2188define i8 @shrink_sub_from_constant_lowbits2(i8 %x) {2189; CHECK-LABEL: @shrink_sub_from_constant_lowbits2(2190; CHECK-NEXT: [[X000:%.*]] = and i8 [[X:%.*]], -82191; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 24, [[X000]]2192; CHECK-NEXT: [[R:%.*]] = and i8 [[SUB]], -162193; CHECK-NEXT: ret i8 [[R]]2194;2195 %x000 = and i8 %x, -8 ; 3 low bits are known zero2196 %sub = sub nsw i8 30, %x000 ; 0b0001_11102197 %r = and i8 %sub, -16 ; 4 low bits are not demanded2198 ret i8 %r2199}2200 2201; safe to clear 3 low bits (2 higher bits remain set)2202 2203define <2 x i8> @shrink_sub_from_constant_lowbits3(<2 x i8> %x) {2204; CHECK-LABEL: @shrink_sub_from_constant_lowbits3(2205; CHECK-NEXT: [[X0000:%.*]] = shl <2 x i8> [[X:%.*]], splat (i8 4)2206; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i8> splat (i8 24), [[X0000]]2207; CHECK-NEXT: [[R:%.*]] = lshr exact <2 x i8> [[SUB]], splat (i8 3)2208; CHECK-NEXT: ret <2 x i8> [[R]]2209;2210 %x0000 = shl <2 x i8> %x, <i8 4, i8 4> ; 4 low bits are known zero2211 %sub = sub nuw <2 x i8> <i8 31, i8 31>, %x00002212 %r = lshr <2 x i8> %sub, <i8 3, i8 3> ; 3 low bits are not demanded2213 ret <2 x i8> %r2214}2215 2216; eliminate the mask of y or the mask of the result2217 2218define i8 @demand_sub_from_variable_lowbits(i8 %x, i8 %y) {2219; CHECK-LABEL: @demand_sub_from_variable_lowbits(2220; CHECK-NEXT: [[X000:%.*]] = shl i8 [[X:%.*]], 32221; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[Y:%.*]], [[X000]]2222; CHECK-NEXT: [[R:%.*]] = and i8 [[SUB]], -82223; CHECK-NEXT: ret i8 [[R]]2224;2225 %x000 = shl i8 %x, 3 ; 3 low bits are known zero2226 %y000 = and i8 %y, -82227 %sub = sub i8 %y000, %x0002228 %r = and i8 %sub, -8 ; 3 low bits are not demanded2229 ret i8 %r2230}2231 2232; setting the low 3 bits of y doesn't change anything2233 2234define i8 @demand_sub_from_variable_lowbits2(i8 %x, i8 %y) {2235; CHECK-LABEL: @demand_sub_from_variable_lowbits2(2236; CHECK-NEXT: [[X0000:%.*]] = shl i8 [[X:%.*]], 42237; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i8 [[Y:%.*]], [[X0000]]2238; CHECK-NEXT: [[R:%.*]] = lshr i8 [[SUB]], 42239; CHECK-NEXT: ret i8 [[R]]2240;2241 %x0000 = shl i8 %x, 4 ; 4 low bits are known zero2242 %y111 = or i8 %y, 72243 %sub = sub nsw nuw i8 %y111, %x00002244 %r = lshr i8 %sub, 4 ; 4 low bits are not demanded2245 ret i8 %r2246}2247 2248; negative test - the mask of y removes an extra bit, so that instruction is needed2249 2250define i8 @demand_sub_from_variable_lowbits3(i8 %x, i8 %y) {2251; CHECK-LABEL: @demand_sub_from_variable_lowbits3(2252; CHECK-NEXT: [[X0000:%.*]] = shl i8 [[X:%.*]], 42253; CHECK-NEXT: [[Y00000:%.*]] = and i8 [[Y:%.*]], -322254; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[Y00000]], [[X0000]]2255; CHECK-NEXT: [[R:%.*]] = lshr exact i8 [[SUB]], 42256; CHECK-NEXT: ret i8 [[R]]2257;2258 %x0000 = shl i8 %x, 4 ; 4 low bits are known zero2259 %y00000 = and i8 %y, -322260 %sub = sub i8 %y00000, %x00002261 %r = lshr i8 %sub, 4 ; 4 low bits are not demanded2262 ret i8 %r2263}2264 2265; C - ((C3 - X) & C2) --> (C - (C2 & C3)) + (X & C2) when:2266; (C3 - ((C2 & C3) - 1)) is pow22267; ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)2268; C2 is negative pow22269define i10 @sub_to_and_nuw(i10 %x) {2270; CHECK-LABEL: @sub_to_and_nuw(2271; CHECK-NEXT: [[TMP1:%.*]] = and i10 [[X:%.*]], 1202272; CHECK-NEXT: [[R:%.*]] = add nuw nsw i10 [[TMP1]], 3792273; CHECK-NEXT: ret i10 [[R]]2274;2275 %sub = sub nuw i10 71, %x2276 %and = and i10 %sub, 1202277 %r = sub i10 443, %and2278 ret i10 %r2279}2280 2281; C - ((C3 -nuw X) & C2) --> (C - (C2 & C3)) + (X & C2) when:2282; (C3 - ((C2 & C3) - 1)) is pow22283; ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)2284define i10 @sub_to_and_negpow2(i10 %x) {2285; CHECK-LABEL: @sub_to_and_negpow2(2286; CHECK-NEXT: [[TMP1:%.*]] = and i10 [[X:%.*]], -82287; CHECK-NEXT: [[R:%.*]] = add i10 [[TMP1]], -312288; CHECK-NEXT: ret i10 [[R]]2289;2290 %sub = sub i10 71, %x2291 %and = and i10 %sub, -82292 %r = sub i10 33, %and2293 ret i10 %r2294}2295 2296; TODO:2297; C + ((C3 -nuw X) & C2) --> (C + (C2 & C3)) - (X & C2) when:2298define i10 @add_to_and_nuw(i10 %x) {2299; CHECK-LABEL: @add_to_and_nuw(2300; CHECK-NEXT: [[SUB:%.*]] = sub nuw i10 71, [[X:%.*]]2301; CHECK-NEXT: [[AND:%.*]] = and i10 [[SUB]], 1202302; CHECK-NEXT: [[R:%.*]] = add nuw nsw i10 [[AND]], 2242303; CHECK-NEXT: ret i10 [[R]]2304;2305 %sub = sub nuw i10 71, %x2306 %and = and i10 %sub, 1202307 %r = add i10 224, %and2308 ret i10 %r2309}2310 2311; (C3 - (C2 & C3) + 1) is not pow22312define i10 @sub_to_and_negative1(i10 %x) {2313; CHECK-LABEL: @sub_to_and_negative1(2314; CHECK-NEXT: [[SUB:%.*]] = sub i10 71, [[X:%.*]]2315; CHECK-NEXT: [[AND:%.*]] = and i10 [[SUB]], 2482316; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i10 444, [[AND]]2317; CHECK-NEXT: ret i10 [[R]]2318;2319 %sub = sub nuw i10 327, %x2320 %and = and i10 %sub, 2482321 %r = sub i10 444, %and2322 ret i10 %r2323}2324 2325; ((C2 + C3) & ((C2 & C3) - 1)) == ((C2 & C3) - 1)2326define i10 @sub_to_and_negative2(i10 %x) {2327; CHECK-LABEL: @sub_to_and_negative2(2328; CHECK-NEXT: [[SUB:%.*]] = sub nuw i10 71, [[X:%.*]]2329; CHECK-NEXT: [[AND:%.*]] = and i10 [[SUB]], 882330; CHECK-NEXT: [[R:%.*]] = sub nsw i10 64, [[AND]]2331; CHECK-NEXT: ret i10 [[R]]2332;2333 %sub = sub nuw i10 71, %x2334 %and = and i10 %sub, 882335 %r = sub i10 64, %and2336 ret i10 %r2337}2338 2339; no nuw && C2 is not neg-pow22340define i10 @sub_to_and_negative3(i10 %x) {2341; CHECK-LABEL: @sub_to_and_negative3(2342; CHECK-NEXT: [[SUB:%.*]] = sub i10 71, [[X:%.*]]2343; CHECK-NEXT: [[AND:%.*]] = and i10 [[SUB]], 1202344; CHECK-NEXT: [[R:%.*]] = sub nsw i10 64, [[AND]]2345; CHECK-NEXT: ret i10 [[R]]2346;2347 %sub = sub i10 71, %x2348 %and = and i10 %sub, 1202349 %r = sub i10 64, %and2350 ret i10 %r2351}2352 2353declare void @use10(i10)2354 2355; and is not one-use2356define i10 @sub_to_and_negative4(i10 %x) {2357; CHECK-LABEL: @sub_to_and_negative4(2358; CHECK-NEXT: [[SUB:%.*]] = sub i10 71, [[X:%.*]]2359; CHECK-NEXT: [[AND:%.*]] = and i10 [[SUB]], 1202360; CHECK-NEXT: [[R:%.*]] = sub nsw i10 64, [[AND]]2361; CHECK-NEXT: call void @use10(i10 [[AND]])2362; CHECK-NEXT: ret i10 [[R]]2363;2364 %sub = sub i10 71, %x2365 %and = and i10 %sub, 1202366 %r = sub i10 64, %and2367 call void @use10(i10 %and)2368 ret i10 %r2369}2370 2371 2372define <2 x i8> @sub_to_and_vector1(<2 x i8> %x) {2373; CHECK-LABEL: @sub_to_and_vector1(2374; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], splat (i8 120)2375; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i8> [[TMP1]], splat (i8 -9)2376; CHECK-NEXT: ret <2 x i8> [[R]]2377;2378 %sub = sub nuw <2 x i8> <i8 71, i8 71>, %x2379 %and = and <2 x i8> %sub, <i8 120, i8 120>2380 %r = sub <2 x i8> <i8 55, i8 55>, %and2381 ret <2 x i8> %r2382}2383 2384 2385define <2 x i8> @sub_to_and_vector2(<2 x i8> %x) {2386; CHECK-LABEL: @sub_to_and_vector2(2387; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i8> <i8 71, i8 poison>, [[X:%.*]]2388; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[SUB]], splat (i8 120)2389; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> splat (i8 77), [[AND]]2390; CHECK-NEXT: ret <2 x i8> [[R]]2391;2392 %sub = sub nuw <2 x i8> <i8 71, i8 poison>, %x2393 %and = and <2 x i8> %sub, <i8 120, i8 120>2394 %r = sub <2 x i8> <i8 77, i8 77>, %and2395 ret <2 x i8> %r2396}2397 2398 2399define <2 x i8> @sub_to_and_vector3(<2 x i8> %x) {2400; CHECK-LABEL: @sub_to_and_vector3(2401; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i8> splat (i8 71), [[X:%.*]]2402; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[SUB]], <i8 120, i8 poison>2403; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> splat (i8 44), [[AND]]2404; CHECK-NEXT: ret <2 x i8> [[R]]2405;2406 %sub = sub nuw <2 x i8> <i8 71, i8 71>, %x2407 %and = and <2 x i8> %sub, <i8 120, i8 poison>2408 %r = sub <2 x i8> <i8 44, i8 44>, %and2409 ret <2 x i8> %r2410}2411 2412 2413define <2 x i8> @sub_to_and_vector4(<2 x i8> %x) {2414; CHECK-LABEL: @sub_to_and_vector4(2415; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i8> splat (i8 71), [[X:%.*]]2416; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[SUB]], splat (i8 120)2417; CHECK-NEXT: [[R:%.*]] = sub nsw <2 x i8> <i8 88, i8 poison>, [[AND]]2418; CHECK-NEXT: ret <2 x i8> [[R]]2419;2420 %sub = sub nuw <2 x i8> <i8 71, i8 71>, %x2421 %and = and <2 x i8> %sub, <i8 120, i8 120>2422 %r = sub <2 x i8> <i8 88, i8 poison>, %and2423 ret <2 x i8> %r2424}2425 2426; (X * X) - (Y * Y) --> (X + Y) * (X - Y)2427 2428define i8 @diff_of_squares(i8 %x, i8 %y) {2429; CHECK-LABEL: @diff_of_squares(2430; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]2431; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X]], [[Y]]2432; CHECK-NEXT: [[R:%.*]] = mul i8 [[ADD]], [[SUB]]2433; CHECK-NEXT: ret i8 [[R]]2434;2435 %x2 = mul i8 %x, %x2436 %y2 = mul i8 %y, %y2437 %r = sub i8 %x2, %y22438 ret i8 %r2439}2440 2441; All-or-nothing for propagation of no-wrap flags (possibly conservative)2442 2443define i5 @diff_of_squares_nuw(i5 %x, i5 %y) {2444; CHECK-LABEL: @diff_of_squares_nuw(2445; CHECK-NEXT: [[ADD:%.*]] = add nuw i5 [[X:%.*]], [[Y:%.*]]2446; CHECK-NEXT: [[SUB:%.*]] = sub nuw i5 [[X]], [[Y]]2447; CHECK-NEXT: [[R:%.*]] = mul nuw i5 [[ADD]], [[SUB]]2448; CHECK-NEXT: ret i5 [[R]]2449;2450 %x2 = mul nuw i5 %x, %x2451 %y2 = mul nuw i5 %y, %y2452 %r = sub nuw i5 %x2, %y22453 ret i5 %r2454}2455 2456; All-or-nothing for propagation of no-wrap flags (possibly conservative)2457 2458define i5 @diff_of_squares_partial_nuw(i5 %x, i5 %y) {2459; CHECK-LABEL: @diff_of_squares_partial_nuw(2460; CHECK-NEXT: [[ADD:%.*]] = add i5 [[X:%.*]], [[Y:%.*]]2461; CHECK-NEXT: [[SUB:%.*]] = sub i5 [[X]], [[Y]]2462; CHECK-NEXT: [[R:%.*]] = mul i5 [[ADD]], [[SUB]]2463; CHECK-NEXT: ret i5 [[R]]2464;2465 %x2 = mul nuw i5 %x, %x2466 %y2 = mul nuw i5 %y, %y2467 %r = sub i5 %x2, %y22468 ret i5 %r2469}2470 2471; All-or-nothing for propagation of no-wrap flags (possibly conservative)2472 2473define <2 x i5> @diff_of_squares_nsw(<2 x i5> %x, <2 x i5> %y) {2474; CHECK-LABEL: @diff_of_squares_nsw(2475; CHECK-NEXT: [[ADD:%.*]] = add nsw <2 x i5> [[X:%.*]], [[Y:%.*]]2476; CHECK-NEXT: [[SUB:%.*]] = sub nsw <2 x i5> [[X]], [[Y]]2477; CHECK-NEXT: [[R:%.*]] = mul nsw <2 x i5> [[ADD]], [[SUB]]2478; CHECK-NEXT: ret <2 x i5> [[R]]2479;2480 %x2 = mul nsw <2 x i5> %x, %x2481 %y2 = mul nsw <2 x i5> %y, %y2482 %r = sub nsw <2 x i5> %x2, %y22483 ret <2 x i5> %r2484}2485 2486; All-or-nothing for propagation of no-wrap flags (possibly conservative)2487 2488define <2 x i5> @diff_of_squares_partial_nsw(<2 x i5> %x, <2 x i5> %y) {2489; CHECK-LABEL: @diff_of_squares_partial_nsw(2490; CHECK-NEXT: [[ADD:%.*]] = add <2 x i5> [[X:%.*]], [[Y:%.*]]2491; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i5> [[X]], [[Y]]2492; CHECK-NEXT: [[R:%.*]] = mul <2 x i5> [[ADD]], [[SUB]]2493; CHECK-NEXT: ret <2 x i5> [[R]]2494;2495 %x2 = mul nsw <2 x i5> %x, %x2496 %y2 = mul <2 x i5> %y, %y2497 %r = sub nsw <2 x i5> %x2, %y22498 ret <2 x i5> %r2499}2500 2501define i1 @diff_of_squares_nsw_i1(i1 %x, i1 %y) {2502; CHECK-LABEL: @diff_of_squares_nsw_i1(2503; CHECK-NEXT: ret i1 false2504;2505 %x2 = mul nsw i1 %x, %x2506 %y2 = mul nsw i1 %y, %y2507 %r = sub nsw i1 %x2, %y22508 ret i1 %r2509}2510 2511define i1 @diff_of_squares_nuw_i1(i1 %x, i1 %y) {2512; CHECK-LABEL: @diff_of_squares_nuw_i1(2513; CHECK-NEXT: [[R:%.*]] = xor i1 [[Y:%.*]], [[X:%.*]]2514; CHECK-NEXT: ret i1 [[R]]2515;2516 %x2 = mul nuw i1 %x, %x2517 %y2 = mul nuw i1 %y, %y2518 %r = sub nuw i1 %x2, %y22519 ret i1 %r2520}2521 2522; It is not correct to propagate nsw.2523; TODO: This should reduce more.2524 2525define i2 @diff_of_squares_nsw_i2(i2 %x, i2 %y) {2526; CHECK-LABEL: @diff_of_squares_nsw_i2(2527; CHECK-NEXT: [[ADD:%.*]] = add i2 [[X:%.*]], [[Y:%.*]]2528; CHECK-NEXT: [[SUB:%.*]] = sub i2 [[X]], [[Y]]2529; CHECK-NEXT: [[R:%.*]] = mul i2 [[ADD]], [[SUB]]2530; CHECK-NEXT: ret i2 [[R]]2531;2532 %x2 = mul nsw i2 %x, %x2533 %y2 = mul nsw i2 %y, %y2534 %r = sub nsw i2 %x2, %y22535 ret i2 %r2536}2537 2538; TODO: This should reduce more.2539 2540define i2 @diff_of_squares_nuw_i2(i2 %x, i2 %y) {2541; CHECK-LABEL: @diff_of_squares_nuw_i2(2542; CHECK-NEXT: [[ADD:%.*]] = add nuw i2 [[X:%.*]], [[Y:%.*]]2543; CHECK-NEXT: [[SUB:%.*]] = sub nuw i2 [[X]], [[Y]]2544; CHECK-NEXT: [[R:%.*]] = mul nuw i2 [[ADD]], [[SUB]]2545; CHECK-NEXT: ret i2 [[R]]2546;2547 %x2 = mul nuw i2 %x, %x2548 %y2 = mul nuw i2 %y, %y2549 %r = sub nuw i2 %x2, %y22550 ret i2 %r2551}2552 2553; negative test2554 2555define i8 @diff_of_squares_use1(i8 %x, i8 %y) {2556; CHECK-LABEL: @diff_of_squares_use1(2557; CHECK-NEXT: [[X2:%.*]] = mul i8 [[X:%.*]], [[X]]2558; CHECK-NEXT: call void @use8(i8 [[X2]])2559; CHECK-NEXT: [[Y2:%.*]] = mul i8 [[Y:%.*]], [[Y]]2560; CHECK-NEXT: [[R:%.*]] = sub i8 [[X2]], [[Y2]]2561; CHECK-NEXT: ret i8 [[R]]2562;2563 %x2 = mul i8 %x, %x2564 call void @use8(i8 %x2)2565 %y2 = mul i8 %y, %y2566 %r = sub i8 %x2, %y22567 ret i8 %r2568}2569 2570; negative test2571 2572define i8 @diff_of_squares_use2(i8 %x, i8 %y) {2573; CHECK-LABEL: @diff_of_squares_use2(2574; CHECK-NEXT: [[X2:%.*]] = mul i8 [[X:%.*]], [[X]]2575; CHECK-NEXT: [[Y2:%.*]] = mul i8 [[Y:%.*]], [[Y]]2576; CHECK-NEXT: call void @use8(i8 [[Y2]])2577; CHECK-NEXT: [[R:%.*]] = sub i8 [[X2]], [[Y2]]2578; CHECK-NEXT: ret i8 [[R]]2579;2580 %x2 = mul i8 %x, %x2581 %y2 = mul i8 %y, %y2582 call void @use8(i8 %y2)2583 %r = sub i8 %x2, %y22584 ret i8 %r2585}2586 2587; negative test - must be squares2588 2589define i8 @diff_of_muls1(i8 %x, i8 %y, i8 %z) {2590; CHECK-LABEL: @diff_of_muls1(2591; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[Z:%.*]]2592; CHECK-NEXT: [[Y2:%.*]] = mul i8 [[Y:%.*]], [[Y]]2593; CHECK-NEXT: [[R:%.*]] = sub i8 [[M]], [[Y2]]2594; CHECK-NEXT: ret i8 [[R]]2595;2596 %m = mul i8 %x, %z2597 %y2 = mul i8 %y, %y2598 %r = sub i8 %m, %y22599 ret i8 %r2600}2601 2602; negative test - must be squares2603 2604define i8 @diff_of_muls2(i8 %x, i8 %y, i8 %z) {2605; CHECK-LABEL: @diff_of_muls2(2606; CHECK-NEXT: [[X2:%.*]] = mul i8 [[X:%.*]], [[X]]2607; CHECK-NEXT: [[M:%.*]] = mul i8 [[Y:%.*]], [[Z:%.*]]2608; CHECK-NEXT: [[R:%.*]] = sub i8 [[X2]], [[M]]2609; CHECK-NEXT: ret i8 [[R]]2610;2611 %x2 = mul i8 %x, %x2612 %m = mul i8 %y, %z2613 %r = sub i8 %x2, %m2614 ret i8 %r2615}2616 2617define i8 @sub_of_adds_2xz_multiuse(i8 %x, i8 %y, i8 %z) {2618; CHECK-LABEL: @sub_of_adds_2xz_multiuse(2619; CHECK-NEXT: [[XZ:%.*]] = add i8 [[X:%.*]], [[Z:%.*]]2620; CHECK-NEXT: [[YZ:%.*]] = add i8 [[Z]], [[Y:%.*]]2621; CHECK-NEXT: [[R:%.*]] = sub i8 [[X]], [[Y]]2622; CHECK-NEXT: call void @use8(i8 [[XZ]])2623; CHECK-NEXT: call void @use8(i8 [[YZ]])2624; CHECK-NEXT: ret i8 [[R]]2625;2626 %xz = add i8 %x, %z2627 %yz = add i8 %z, %y2628 %r = sub i8 %xz, %yz2629 call void @use8(i8 %xz)2630 call void @use8(i8 %yz)2631 ret i8 %r2632}2633 2634define i8 @sub_of_adds_2xc_multiuse2_fail(i8 %x, i8 %y) {2635; CHECK-LABEL: @sub_of_adds_2xc_multiuse2_fail(2636; CHECK-NEXT: [[XC:%.*]] = add i8 [[X:%.*]], 102637; CHECK-NEXT: [[YC:%.*]] = add i8 [[Y:%.*]], 112638; CHECK-NEXT: [[R:%.*]] = sub i8 [[XC]], [[YC]]2639; CHECK-NEXT: call void @use8(i8 [[XC]])2640; CHECK-NEXT: call void @use8(i8 [[YC]])2641; CHECK-NEXT: ret i8 [[R]]2642;2643 %xc = add i8 %x, 102644 %yc = add i8 %y, 112645 %r = sub i8 %xc, %yc2646 call void @use8(i8 %xc)2647 call void @use8(i8 %yc)2648 ret i8 %r2649}2650 2651define i8 @sub_of_adds_2xc(i8 %x, i8 %y) {2652; CHECK-LABEL: @sub_of_adds_2xc(2653; CHECK-NEXT: [[TMP1:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]2654; CHECK-NEXT: [[R:%.*]] = add i8 [[TMP1]], 22655; CHECK-NEXT: ret i8 [[R]]2656;2657 %xc = add i8 %x, 102658 %yc = add i8 %y, 82659 %r = sub i8 %xc, %yc2660 ret i8 %r2661}2662 2663define i32 @sub_infer_nuw_from_domcond(i32 %x, i32 %y) {2664; CHECK-LABEL: @sub_infer_nuw_from_domcond(2665; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]2666; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]2667; CHECK: if.then:2668; CHECK-NEXT: [[SUB:%.*]] = sub nuw i32 [[X]], [[Y]]2669; CHECK-NEXT: ret i32 [[SUB]]2670; CHECK: if.else:2671; CHECK-NEXT: ret i32 02672;2673 %cond = icmp uge i32 %x, %y2674 br i1 %cond, label %if.then, label %if.else2675 2676if.then:2677 %sub = sub i32 %x, %y2678 ret i32 %sub2679 2680if.else:2681 ret i32 02682}2683 2684define i1 @sub_infer_nuw_from_domcond_fold1(i32 %x, i32 %y) {2685; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold1(2686; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]2687; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]2688; CHECK: if.then:2689; CHECK-NEXT: ret i1 false2690; CHECK: if.else:2691; CHECK-NEXT: ret i1 false2692;2693 %cond = icmp uge i32 %x, %y2694 br i1 %cond, label %if.then, label %if.else2695 2696if.then:2697 %ext0 = zext i32 %y to i642698 %ext1 = zext i32 %x to i642699 %sub = sub i32 %x, %y2700 %ext2 = zext i32 %sub to i642701 %add = add nuw nsw i64 %ext2, %ext02702 %cmp = icmp ugt i64 %add, %ext12703 ret i1 %cmp2704 2705if.else:2706 ret i1 false2707}2708 2709define i64 @sub_infer_nuw_from_domcond_fold2(i32 range(i32 0, 2147483648) %x, i32 range(i32 0, 2147483648) %y) {2710; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold2(2711; CHECK-NEXT: [[COND_NOT:%.*]] = icmp samesign ult i32 [[X:%.*]], [[Y:%.*]]2712; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]2713; CHECK: if.then:2714; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i32 [[X]], [[Y]]2715; CHECK-NEXT: [[EXT:%.*]] = zext nneg i32 [[SUB]] to i642716; CHECK-NEXT: ret i64 [[EXT]]2717; CHECK: if.else:2718; CHECK-NEXT: ret i64 02719;2720 %cond = icmp uge i32 %x, %y2721 br i1 %cond, label %if.then, label %if.else2722 2723if.then:2724 %sub = sub i32 %x, %y2725 %ext = zext i32 %sub to i642726 ret i64 %ext2727 2728if.else:2729 ret i64 02730}2731 2732define i1 @sub_infer_nuw_from_domcond_fold3(i16 %xx, i32 range(i32 0, 12) %y) {2733; CHECK-LABEL: @sub_infer_nuw_from_domcond_fold3(2734; CHECK-NEXT: [[X:%.*]] = zext i16 [[XX:%.*]] to i322735; CHECK-NEXT: [[COND:%.*]] = icmp samesign ugt i32 [[Y:%.*]], [[X]]2736; CHECK-NEXT: br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]2737; CHECK: if.then:2738; CHECK-NEXT: ret i1 false2739; CHECK: if.else:2740; CHECK-NEXT: ret i1 false2741;2742 %x = zext i16 %xx to i322743 %cond = icmp ult i32 %x, %y2744 br i1 %cond, label %if.then, label %if.else2745 2746if.then:2747 %sub = sub nsw i32 %y, %x2748 %cmp = icmp eq i32 %sub, -12749 ret i1 %cmp2750 2751if.else:2752 ret i1 false2753}2754 2755; negative tests2756 2757define i32 @sub_infer_nuw_from_domcond_wrong_pred(i32 %x, i32 %y) {2758; CHECK-LABEL: @sub_infer_nuw_from_domcond_wrong_pred(2759; CHECK-NEXT: [[COND_NOT:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]2760; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]]2761; CHECK: if.then:2762; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]2763; CHECK-NEXT: ret i32 [[SUB]]2764; CHECK: if.else:2765; CHECK-NEXT: ret i32 02766;2767 %cond = icmp sge i32 %x, %y2768 br i1 %cond, label %if.then, label %if.else2769 2770if.then:2771 %sub = sub i32 %x, %y2772 ret i32 %sub2773 2774if.else:2775 ret i32 02776}2777 2778define i32 @sub_infer_nuw_from_domcond_lhs_is_false(i32 %x, i32 %y) {2779; CHECK-LABEL: @sub_infer_nuw_from_domcond_lhs_is_false(2780; CHECK-NEXT: [[COND_NOT:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]2781; CHECK-NEXT: br i1 [[COND_NOT]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]2782; CHECK: if.then:2783; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X]], [[Y]]2784; CHECK-NEXT: ret i32 [[SUB]]2785; CHECK: if.else:2786; CHECK-NEXT: ret i32 02787;2788 %cond = icmp uge i32 %x, %y2789 br i1 %cond, label %if.else, label %if.then2790 2791if.then:2792 %sub = sub i32 %x, %y2793 ret i32 %sub2794 2795if.else:2796 ret i32 02797}2798 2799define i32 @fold_sub_and_into_andn(i32 %x) {2800; CHECK-LABEL: @fold_sub_and_into_andn(2801; CHECK-NEXT: entry:2802; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[X:%.*]], 632803; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP0]], 632804; CHECK-NEXT: ret i32 [[AND]]2805;2806entry:2807 %sub = sub i32 63, %x2808 %and = and i32 %sub, 632809 ret i32 %and2810}2811 2812define i1 @fold_sub_and_into_andn_icmp(i32 %x) {2813; CHECK-LABEL: @fold_sub_and_into_andn_icmp(2814; CHECK-NEXT: entry:2815; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[X:%.*]], 632816; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 632817; CHECK-NEXT: ret i1 [[CMP]]2818;2819entry:2820 %sub = sub i32 63, %x2821 %and = and i32 %sub, 632822 %cmp = icmp eq i32 %and, 02823 ret i1 %cmp2824}2825 2826define i32 @fold_sub_and_into_andn_subset(i32 %x) {2827; CHECK-LABEL: @fold_sub_and_into_andn_subset(2828; CHECK-NEXT: entry:2829; CHECK-NEXT: [[TMP0:%.*]] = and i32 [[X:%.*]], 312830; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP0]], 312831; CHECK-NEXT: ret i32 [[AND]]2832;2833entry:2834 %sub = sub i32 63, %x2835 %and = and i32 %sub, 312836 ret i32 %and2837}2838 2839; Negative tests2840 2841define i32 @fold_sub_and_into_andn_nonmask(i32 %x, i32 %y) {2842; CHECK-LABEL: @fold_sub_and_into_andn_nonmask(2843; CHECK-NEXT: entry:2844; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]]2845; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], 632846; CHECK-NEXT: ret i32 [[AND]]2847;2848entry:2849 %sub = sub i32 %y, %x2850 %and = and i32 %sub, 632851 ret i32 %and2852}2853 2854define i32 @fold_sub_and_into_andn_superset(i32 %x) {2855; CHECK-LABEL: @fold_sub_and_into_andn_superset(2856; CHECK-NEXT: entry:2857; CHECK-NEXT: [[SUB:%.*]] = sub i32 63, [[X:%.*]]2858; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], 1272859; CHECK-NEXT: ret i32 [[AND]]2860;2861entry:2862 %sub = sub i32 63, %x2863 %and = and i32 %sub, 1272864 ret i32 %and2865}2866