631 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare i32 @callee()5 6declare void @use(i64)7 8define i64 @sext_sext_add(i32 %A) {9; CHECK-LABEL: @sext_sext_add(10; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 711; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 912; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]13; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i6414; CHECK-NEXT: ret i64 [[F]]15;16 %B = ashr i32 %A, 717 %C = ashr i32 %A, 918 %D = sext i32 %B to i6419 %E = sext i32 %C to i6420 %F = add i64 %D, %E21 ret i64 %F22}23 24; Negative test25 26define i64 @sext_zext_add_mismatched_exts(i32 %A) {27; CHECK-LABEL: @sext_zext_add_mismatched_exts(28; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 729; CHECK-NEXT: [[C:%.*]] = lshr i32 [[A]], 930; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i6431; CHECK-NEXT: [[E:%.*]] = zext nneg i32 [[C]] to i6432; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]33; CHECK-NEXT: ret i64 [[F]]34;35 %B = ashr i32 %A, 736 %C = lshr i32 %A, 937 %D = sext i32 %B to i6438 %E = zext i32 %C to i6439 %F = add i64 %D, %E40 ret i64 %F41}42 43; Negative test44 45define i64 @sext_sext_add_mismatched_types(i16 %A, i32 %x) {46; CHECK-LABEL: @sext_sext_add_mismatched_types(47; CHECK-NEXT: [[B:%.*]] = ashr i16 [[A:%.*]], 748; CHECK-NEXT: [[C:%.*]] = ashr i32 [[X:%.*]], 949; CHECK-NEXT: [[D:%.*]] = sext i16 [[B]] to i6450; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i6451; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]52; CHECK-NEXT: ret i64 [[F]]53;54 %B = ashr i16 %A, 755 %C = ashr i32 %x, 956 %D = sext i16 %B to i6457 %E = sext i32 %C to i6458 %F = add i64 %D, %E59 ret i64 %F60}61 62define i64 @sext_sext_add_extra_use1(i32 %A) {63; CHECK-LABEL: @sext_sext_add_extra_use1(64; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 765; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 966; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i6467; CHECK-NEXT: call void @use(i64 [[D]])68; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]69; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i6470; CHECK-NEXT: ret i64 [[F]]71;72 %B = ashr i32 %A, 773 %C = ashr i32 %A, 974 %D = sext i32 %B to i6475 call void @use(i64 %D)76 %E = sext i32 %C to i6477 %F = add i64 %D, %E78 ret i64 %F79}80 81define i64 @sext_sext_add_extra_use2(i32 %A) {82; CHECK-LABEL: @sext_sext_add_extra_use2(83; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 784; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 985; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i6486; CHECK-NEXT: call void @use(i64 [[E]])87; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[B]], [[C]]88; CHECK-NEXT: [[F:%.*]] = sext i32 [[NARROW]] to i6489; CHECK-NEXT: ret i64 [[F]]90;91 %B = ashr i32 %A, 792 %C = ashr i32 %A, 993 %D = sext i32 %B to i6494 %E = sext i32 %C to i6495 call void @use(i64 %E)96 %F = add i64 %D, %E97 ret i64 %F98}99 100; Negative test - if both extends have extra uses, we need an extra instruction.101 102define i64 @sext_sext_add_extra_use3(i32 %A) {103; CHECK-LABEL: @sext_sext_add_extra_use3(104; CHECK-NEXT: [[B:%.*]] = ashr i32 [[A:%.*]], 7105; CHECK-NEXT: [[C:%.*]] = ashr i32 [[A]], 9106; CHECK-NEXT: [[D:%.*]] = sext i32 [[B]] to i64107; CHECK-NEXT: call void @use(i64 [[D]])108; CHECK-NEXT: [[E:%.*]] = sext i32 [[C]] to i64109; CHECK-NEXT: call void @use(i64 [[E]])110; CHECK-NEXT: [[F:%.*]] = add nsw i64 [[D]], [[E]]111; CHECK-NEXT: ret i64 [[F]]112;113 %B = ashr i32 %A, 7114 %C = ashr i32 %A, 9115 %D = sext i32 %B to i64116 call void @use(i64 %D)117 %E = sext i32 %C to i64118 call void @use(i64 %E)119 %F = add i64 %D, %E120 ret i64 %F121}122 123define i64 @test1(i32 %V) {124; CHECK-LABEL: @test1(125; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0:![0-9]+]]126; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]127; CHECK-NEXT: [[NARROW:%.*]] = add nuw nsw i32 [[CALL1]], [[CALL2]]128; CHECK-NEXT: [[ADD:%.*]] = zext nneg i32 [[NARROW]] to i64129; CHECK-NEXT: ret i64 [[ADD]]130;131 %call1 = call i32 @callee(), !range !0132 %call2 = call i32 @callee(), !range !0133 %zext1 = sext i32 %call1 to i64134 %zext2 = sext i32 %call2 to i64135 %add = add i64 %zext1, %zext2136 ret i64 %add137}138 139define i64 @test2(i32 %V) {140; CHECK-LABEL: @test2(141; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0]]142; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]143; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i32 [[CALL1]], [[CALL2]]144; CHECK-NEXT: [[ZEXT:%.*]] = zext nneg i32 [[ADD]] to i64145; CHECK-NEXT: ret i64 [[ZEXT]]146;147 %call1 = call i32 @callee(), !range !0148 %call2 = call i32 @callee(), !range !0149 %add = add i32 %call1, %call2150 %zext = sext i32 %add to i64151 ret i64 %zext152}153 154define i64 @test3(i32 %V) {155; CHECK-LABEL: @test3(156; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0]]157; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]158; CHECK-NEXT: [[NARROW:%.*]] = mul nuw nsw i32 [[CALL1]], [[CALL2]]159; CHECK-NEXT: [[ADD:%.*]] = zext nneg i32 [[NARROW]] to i64160; CHECK-NEXT: ret i64 [[ADD]]161;162 %call1 = call i32 @callee(), !range !0163 %call2 = call i32 @callee(), !range !0164 %zext1 = sext i32 %call1 to i64165 %zext2 = sext i32 %call2 to i64166 %add = mul i64 %zext1, %zext2167 ret i64 %add168}169 170define i64 @test4(i32 %V) {171; CHECK-LABEL: @test4(172; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0]]173; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]174; CHECK-NEXT: [[ADD:%.*]] = mul nuw nsw i32 [[CALL1]], [[CALL2]]175; CHECK-NEXT: [[ZEXT:%.*]] = zext nneg i32 [[ADD]] to i64176; CHECK-NEXT: ret i64 [[ZEXT]]177;178 %call1 = call i32 @callee(), !range !0179 %call2 = call i32 @callee(), !range !0180 %add = mul i32 %call1, %call2181 %zext = sext i32 %add to i64182 ret i64 %zext183}184 185define i64 @test5(i32 %V) {186; CHECK-LABEL: @test5(187; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1188; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[ASHR]], 1073741823189; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64190; CHECK-NEXT: ret i64 [[ADD]]191;192 %ashr = ashr i32 %V, 1193 %sext = sext i32 %ashr to i64194 %add = add i64 %sext, 1073741823195 ret i64 %add196}197 198; Negative test - extra use means we'd have more instructions than we started with.199 200define i64 @sext_add_constant_extra_use(i32 %V) {201; CHECK-LABEL: @sext_add_constant_extra_use(202; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1203; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[ASHR]] to i64204; CHECK-NEXT: call void @use(i64 [[SEXT]])205; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[SEXT]], 1073741823206; CHECK-NEXT: ret i64 [[ADD]]207;208 %ashr = ashr i32 %V, 1209 %sext = sext i32 %ashr to i64210 call void @use(i64 %sext)211 %add = add i64 %sext, 1073741823212 ret i64 %add213}214 215define <2 x i64> @test5_splat(<2 x i32> %V) {216; CHECK-LABEL: @test5_splat(217; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)218; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], splat (i32 1073741823)219; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>220; CHECK-NEXT: ret <2 x i64> [[ADD]]221;222 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>223 %sext = sext <2 x i32> %ashr to <2 x i64>224 %add = add <2 x i64> %sext, <i64 1073741823, i64 1073741823>225 ret <2 x i64> %add226}227 228define <2 x i64> @test5_vec(<2 x i32> %V) {229; CHECK-LABEL: @test5_vec(230; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)231; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 1, i32 2>232; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>233; CHECK-NEXT: ret <2 x i64> [[ADD]]234;235 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>236 %sext = sext <2 x i32> %ashr to <2 x i64>237 %add = add <2 x i64> %sext, <i64 1, i64 2>238 ret <2 x i64> %add239}240 241define i64 @test6(i32 %V) {242; CHECK-LABEL: @test6(243; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1244; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[ASHR]], -1073741824245; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64246; CHECK-NEXT: ret i64 [[ADD]]247;248 %ashr = ashr i32 %V, 1249 %sext = sext i32 %ashr to i64250 %add = add i64 %sext, -1073741824251 ret i64 %add252}253 254define <2 x i64> @test6_splat(<2 x i32> %V) {255; CHECK-LABEL: @test6_splat(256; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)257; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], splat (i32 -1073741824)258; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>259; CHECK-NEXT: ret <2 x i64> [[ADD]]260;261 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>262 %sext = sext <2 x i32> %ashr to <2 x i64>263 %add = add <2 x i64> %sext, <i64 -1073741824, i64 -1073741824>264 ret <2 x i64> %add265}266 267define <2 x i64> @test6_vec(<2 x i32> %V) {268; CHECK-LABEL: @test6_vec(269; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)270; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 -1, i32 -2>271; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>272; CHECK-NEXT: ret <2 x i64> [[ADD]]273;274 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>275 %sext = sext <2 x i32> %ashr to <2 x i64>276 %add = add <2 x i64> %sext, <i64 -1, i64 -2>277 ret <2 x i64> %add278}279 280define <2 x i64> @test6_vec2(<2 x i32> %V) {281; CHECK-LABEL: @test6_vec2(282; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)283; CHECK-NEXT: [[NARROW:%.*]] = add nsw <2 x i32> [[ASHR]], <i32 -1, i32 1>284; CHECK-NEXT: [[ADD:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>285; CHECK-NEXT: ret <2 x i64> [[ADD]]286;287 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>288 %sext = sext <2 x i32> %ashr to <2 x i64>289 %add = add <2 x i64> %sext, <i64 -1, i64 1>290 ret <2 x i64> %add291}292 293define i64 @test7(i32 %V) {294; CHECK-LABEL: @test7(295; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1296; CHECK-NEXT: [[NARROW:%.*]] = add nuw i32 [[LSHR]], 2147483647297; CHECK-NEXT: [[ADD:%.*]] = zext i32 [[NARROW]] to i64298; CHECK-NEXT: ret i64 [[ADD]]299;300 %lshr = lshr i32 %V, 1301 %zext = zext i32 %lshr to i64302 %add = add i64 %zext, 2147483647303 ret i64 %add304}305 306define <2 x i64> @test7_splat(<2 x i32> %V) {307; CHECK-LABEL: @test7_splat(308; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], splat (i32 1)309; CHECK-NEXT: [[NARROW:%.*]] = add nuw <2 x i32> [[LSHR]], splat (i32 2147483647)310; CHECK-NEXT: [[ADD:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>311; CHECK-NEXT: ret <2 x i64> [[ADD]]312;313 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>314 %zext = zext <2 x i32> %lshr to <2 x i64>315 %add = add <2 x i64> %zext, <i64 2147483647, i64 2147483647>316 ret <2 x i64> %add317}318 319define <2 x i64> @test7_vec(<2 x i32> %V) {320; CHECK-LABEL: @test7_vec(321; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], splat (i32 1)322; CHECK-NEXT: [[NARROW:%.*]] = add nuw <2 x i32> [[LSHR]], <i32 1, i32 2>323; CHECK-NEXT: [[ADD:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>324; CHECK-NEXT: ret <2 x i64> [[ADD]]325;326 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>327 %zext = zext <2 x i32> %lshr to <2 x i64>328 %add = add <2 x i64> %zext, <i64 1, i64 2>329 ret <2 x i64> %add330}331 332define i64 @test8(i32 %V) {333; CHECK-LABEL: @test8(334; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 16335; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[ASHR]], 32767336; CHECK-NEXT: [[MUL:%.*]] = sext i32 [[NARROW]] to i64337; CHECK-NEXT: ret i64 [[MUL]]338;339 %ashr = ashr i32 %V, 16340 %sext = sext i32 %ashr to i64341 %mul = mul i64 %sext, 32767342 ret i64 %mul343}344 345define <2 x i64> @test8_splat(<2 x i32> %V) {346; CHECK-LABEL: @test8_splat(347; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 16)348; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], splat (i32 32767)349; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>350; CHECK-NEXT: ret <2 x i64> [[MUL]]351;352 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>353 %sext = sext <2 x i32> %ashr to <2 x i64>354 %mul = mul <2 x i64> %sext, <i64 32767, i64 32767>355 ret <2 x i64> %mul356}357 358define <2 x i64> @test8_vec(<2 x i32> %V) {359; CHECK-LABEL: @test8_vec(360; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 16)361; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 32767, i32 16384>362; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>363; CHECK-NEXT: ret <2 x i64> [[MUL]]364;365 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>366 %sext = sext <2 x i32> %ashr to <2 x i64>367 %mul = mul <2 x i64> %sext, <i64 32767, i64 16384>368 ret <2 x i64> %mul369}370 371define <2 x i64> @test8_vec2(<2 x i32> %V) {372; CHECK-LABEL: @test8_vec2(373; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 16)374; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 32767, i32 -32767>375; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>376; CHECK-NEXT: ret <2 x i64> [[MUL]]377;378 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>379 %sext = sext <2 x i32> %ashr to <2 x i64>380 %mul = mul <2 x i64> %sext, <i64 32767, i64 -32767>381 ret <2 x i64> %mul382}383 384define i64 @test9(i32 %V) {385; CHECK-LABEL: @test9(386; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 16387; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[ASHR]], -32767388; CHECK-NEXT: [[MUL:%.*]] = sext i32 [[NARROW]] to i64389; CHECK-NEXT: ret i64 [[MUL]]390;391 %ashr = ashr i32 %V, 16392 %sext = sext i32 %ashr to i64393 %mul = mul i64 %sext, -32767394 ret i64 %mul395}396 397define <2 x i64> @test9_splat(<2 x i32> %V) {398; CHECK-LABEL: @test9_splat(399; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 16)400; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], splat (i32 -32767)401; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>402; CHECK-NEXT: ret <2 x i64> [[MUL]]403;404 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>405 %sext = sext <2 x i32> %ashr to <2 x i64>406 %mul = mul <2 x i64> %sext, <i64 -32767, i64 -32767>407 ret <2 x i64> %mul408}409 410define <2 x i64> @test9_vec(<2 x i32> %V) {411; CHECK-LABEL: @test9_vec(412; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 16)413; CHECK-NEXT: [[NARROW:%.*]] = mul nsw <2 x i32> [[ASHR]], <i32 -32767, i32 -10>414; CHECK-NEXT: [[MUL:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>415; CHECK-NEXT: ret <2 x i64> [[MUL]]416;417 %ashr = ashr <2 x i32> %V, <i32 16, i32 16>418 %sext = sext <2 x i32> %ashr to <2 x i64>419 %mul = mul <2 x i64> %sext, <i64 -32767, i64 -10>420 ret <2 x i64> %mul421}422 423define i64 @test10(i32 %V) {424; CHECK-LABEL: @test10(425; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 16426; CHECK-NEXT: [[NARROW:%.*]] = mul nuw i32 [[LSHR]], 65535427; CHECK-NEXT: [[MUL:%.*]] = zext i32 [[NARROW]] to i64428; CHECK-NEXT: ret i64 [[MUL]]429;430 %lshr = lshr i32 %V, 16431 %zext = zext i32 %lshr to i64432 %mul = mul i64 %zext, 65535433 ret i64 %mul434}435 436define <2 x i64> @test10_splat(<2 x i32> %V) {437; CHECK-LABEL: @test10_splat(438; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], splat (i32 16)439; CHECK-NEXT: [[NARROW:%.*]] = mul nuw <2 x i32> [[LSHR]], splat (i32 65535)440; CHECK-NEXT: [[MUL:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>441; CHECK-NEXT: ret <2 x i64> [[MUL]]442;443 %lshr = lshr <2 x i32> %V, <i32 16, i32 16>444 %zext = zext <2 x i32> %lshr to <2 x i64>445 %mul = mul <2 x i64> %zext, <i64 65535, i64 65535>446 ret <2 x i64> %mul447}448 449define <2 x i64> @test10_vec(<2 x i32> %V) {450; CHECK-LABEL: @test10_vec(451; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], splat (i32 16)452; CHECK-NEXT: [[NARROW:%.*]] = mul nuw <2 x i32> [[LSHR]], <i32 65535, i32 2>453; CHECK-NEXT: [[MUL:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>454; CHECK-NEXT: ret <2 x i64> [[MUL]]455;456 %lshr = lshr <2 x i32> %V, <i32 16, i32 16>457 %zext = zext <2 x i32> %lshr to <2 x i64>458 %mul = mul <2 x i64> %zext, <i64 65535, i64 2>459 ret <2 x i64> %mul460}461 462define i64 @test11(i32 %V) {463; CHECK-LABEL: @test11(464; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG1:![0-9]+]]465; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG1]]466; CHECK-NEXT: [[NARROW:%.*]] = add nsw i32 [[CALL1]], [[CALL2]]467; CHECK-NEXT: [[ADD:%.*]] = sext i32 [[NARROW]] to i64468; CHECK-NEXT: ret i64 [[ADD]]469;470 %call1 = call i32 @callee(), !range !1471 %call2 = call i32 @callee(), !range !1472 %sext1 = sext i32 %call1 to i64473 %sext2 = sext i32 %call2 to i64474 %add = add i64 %sext1, %sext2475 ret i64 %add476}477 478define i64 @test12(i32 %V) {479; CHECK-LABEL: @test12(480; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG1]]481; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG1]]482; CHECK-NEXT: [[NARROW:%.*]] = mul nsw i32 [[CALL1]], [[CALL2]]483; CHECK-NEXT: [[ADD:%.*]] = zext nneg i32 [[NARROW]] to i64484; CHECK-NEXT: ret i64 [[ADD]]485;486 %call1 = call i32 @callee(), !range !1487 %call2 = call i32 @callee(), !range !1488 %sext1 = sext i32 %call1 to i64489 %sext2 = sext i32 %call2 to i64490 %add = mul i64 %sext1, %sext2491 ret i64 %add492}493 494define i64 @test13(i32 %V) {495; CHECK-LABEL: @test13(496; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG2:![0-9]+]]497; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG3:![0-9]+]]498; CHECK-NEXT: [[NARROW:%.*]] = sub nsw i32 [[CALL1]], [[CALL2]]499; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[NARROW]] to i64500; CHECK-NEXT: ret i64 [[SUB]]501;502 %call1 = call i32 @callee(), !range !2503 %call2 = call i32 @callee(), !range !3504 %sext1 = sext i32 %call1 to i64505 %sext2 = sext i32 %call2 to i64506 %sub = sub i64 %sext1, %sext2507 ret i64 %sub508}509 510define i64 @test14(i32 %V) {511; CHECK-LABEL: @test14(512; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG2]]513; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]514; CHECK-NEXT: [[NARROW:%.*]] = sub nuw nsw i32 [[CALL1]], [[CALL2]]515; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[NARROW]] to i64516; CHECK-NEXT: ret i64 [[SUB]]517;518 %call1 = call i32 @callee(), !range !2519 %call2 = call i32 @callee(), !range !0520 %zext1 = zext i32 %call1 to i64521 %zext2 = zext i32 %call2 to i64522 %sub = sub i64 %zext1, %zext2523 ret i64 %sub524}525 526define i64 @test15(i32 %V) {527; CHECK-LABEL: @test15(528; CHECK-NEXT: [[ASHR:%.*]] = ashr i32 [[V:%.*]], 1529; CHECK-NEXT: [[NARROW:%.*]] = sub nsw i32 8, [[ASHR]]530; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[NARROW]] to i64531; CHECK-NEXT: ret i64 [[SUB]]532;533 %ashr = ashr i32 %V, 1534 %sext = sext i32 %ashr to i64535 %sub = sub i64 8, %sext536 ret i64 %sub537}538 539define <2 x i64> @test15vec(<2 x i32> %V) {540; CHECK-LABEL: @test15vec(541; CHECK-NEXT: [[ASHR:%.*]] = ashr <2 x i32> [[V:%.*]], splat (i32 1)542; CHECK-NEXT: [[NARROW:%.*]] = sub nsw <2 x i32> splat (i32 8), [[ASHR]]543; CHECK-NEXT: [[SUB:%.*]] = sext <2 x i32> [[NARROW]] to <2 x i64>544; CHECK-NEXT: ret <2 x i64> [[SUB]]545;546 %ashr = ashr <2 x i32> %V, <i32 1, i32 1>547 %sext = sext <2 x i32> %ashr to <2 x i64>548 %sub = sub <2 x i64> <i64 8, i64 8>, %sext549 ret <2 x i64> %sub550}551 552define i64 @test16(i32 %V) {553; CHECK-LABEL: @test16(554; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[V:%.*]], 1555; CHECK-NEXT: [[NARROW:%.*]] = sub nuw i32 -2, [[LSHR]]556; CHECK-NEXT: [[SUB:%.*]] = zext i32 [[NARROW]] to i64557; CHECK-NEXT: ret i64 [[SUB]]558;559 %lshr = lshr i32 %V, 1560 %zext = zext i32 %lshr to i64561 %sub = sub i64 4294967294, %zext562 ret i64 %sub563}564 565define <2 x i64> @test16vec(<2 x i32> %V) {566; CHECK-LABEL: @test16vec(567; CHECK-NEXT: [[LSHR:%.*]] = lshr <2 x i32> [[V:%.*]], splat (i32 1)568; CHECK-NEXT: [[NARROW:%.*]] = sub nuw <2 x i32> splat (i32 -2), [[LSHR]]569; CHECK-NEXT: [[SUB:%.*]] = zext <2 x i32> [[NARROW]] to <2 x i64>570; CHECK-NEXT: ret <2 x i64> [[SUB]]571;572 %lshr = lshr <2 x i32> %V, <i32 1, i32 1>573 %zext = zext <2 x i32> %lshr to <2 x i64>574 %sub = sub <2 x i64> <i64 4294967294, i64 4294967294>, %zext575 ret <2 x i64> %sub576}577 578; Negative test. Both have the same range so we can't guarantee the subtract579; won't wrap.580define i64 @test17(i32 %V) {581; CHECK-LABEL: @test17(582; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0]]583; CHECK-NEXT: [[CALL2:%.*]] = call i32 @callee(), !range [[RNG0]]584; CHECK-NEXT: [[SEXT1:%.*]] = zext nneg i32 [[CALL1]] to i64585; CHECK-NEXT: [[SEXT2:%.*]] = zext nneg i32 [[CALL2]] to i64586; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]587; CHECK-NEXT: ret i64 [[SUB]]588;589 %call1 = call i32 @callee(), !range !0590 %call2 = call i32 @callee(), !range !0591 %sext1 = zext i32 %call1 to i64592 %sext2 = zext i32 %call2 to i64593 %sub = sub i64 %sext1, %sext2594 ret i64 %sub595}596 597; Negative test. LHS is large positive 32-bit number. Range of callee can598; cause overflow.599define i64 @test18(i32 %V) {600; CHECK-LABEL: @test18(601; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG1]]602; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[CALL1]] to i64603; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 2147481648, [[SEXT1]]604; CHECK-NEXT: ret i64 [[SUB]]605;606 %call1 = call i32 @callee(), !range !1607 %sext1 = sext i32 %call1 to i64608 %sub = sub i64 2147481648, %sext1609 ret i64 %sub610}611 612; Negative test. LHS is large negative 32-bit number. Range of callee can613; cause overflow.614define i64 @test19(i32 %V) {615; CHECK-LABEL: @test19(616; CHECK-NEXT: [[CALL1:%.*]] = call i32 @callee(), !range [[RNG0]]617; CHECK-NEXT: [[SEXT1:%.*]] = zext nneg i32 [[CALL1]] to i64618; CHECK-NEXT: [[SUB:%.*]] = sub nuw nsw i64 -2147481648, [[SEXT1]]619; CHECK-NEXT: ret i64 [[SUB]]620;621 %call1 = call i32 @callee(), !range !0622 %sext1 = sext i32 %call1 to i64623 %sub = sub i64 -2147481648, %sext1624 ret i64 %sub625}626 627!0 = !{ i32 0, i32 2000 }628!1 = !{ i32 -2000, i32 0 }629!2 = !{ i32 -512, i32 -255 }630!3 = !{ i32 -128, i32 0 }631