933 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=licm < %s | FileCheck %s3 4; Hoist ADD and remove old op if unused.5define void @add_one_use(i64 %c1, i64 %c2) {6; CHECK-LABEL: @add_one_use(7; CHECK-NEXT: entry:8; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]9; CHECK-NEXT: br label [[LOOP:%.*]]10; CHECK: loop:11; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]12; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]13; CHECK-NEXT: br label [[LOOP]]14;15entry:16 br label %loop17 18loop:19 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]20 %step.add = add i64 %index, %c121 %index.next = add i64 %step.add, %c222 br label %loop23}24 25; Don't hoist ADD if the op has more than one use.26define void @add_two_uses(i64 %c1, i64 %c2) {27; CHECK-LABEL: @add_two_uses(28; CHECK-NEXT: entry:29; CHECK-NEXT: br label [[LOOP:%.*]]30; CHECK: loop:31; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]32; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]33; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])34; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]]35; CHECK-NEXT: call void @use(i64 [[INDEX_NEXT]])36; CHECK-NEXT: br label [[LOOP]]37;38entry:39 br label %loop40 41loop:42 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]43 %step.add = add i64 %index, %c144 call void @use(i64 %step.add)45 %index.next = add i64 %step.add, %c246 call void @use(i64 %index.next)47 br label %loop48}49 50; Hoist MUL and remove old op if unused.51define void @mul_one_use(i64 %c1, i64 %c2) {52; CHECK-LABEL: @mul_one_use(53; CHECK-NEXT: entry:54; CHECK-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[C1:%.*]], [[C2:%.*]]55; CHECK-NEXT: br label [[LOOP:%.*]]56; CHECK: loop:57; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[STEP_ADD_REASS:%.*]], [[LOOP]] ]58; CHECK-NEXT: [[STEP_ADD_REASS]] = mul i64 [[INDEX]], [[FACTOR_OP_MUL]]59; CHECK-NEXT: br label [[LOOP]]60;61entry:62 br label %loop63 64loop:65 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]66 %step.add = mul i64 %index, %c167 %index.next = mul i64 %step.add, %c268 br label %loop69}70 71; Hoist ADD and copy NUW if both ops have it.72define void @add_nuw(i64 %c1, i64 %c2) {73; CHECK-LABEL: @add_nuw(74; CHECK-NEXT: entry:75; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]76; CHECK-NEXT: br label [[LOOP:%.*]]77; CHECK: loop:78; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]79; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]80; CHECK-NEXT: br label [[LOOP]]81;82entry:83 br label %loop84 85loop:86 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]87 %step.add = add nuw i64 %index, %c188 %index.next = add nuw i64 %step.add, %c289 br label %loop90}91 92; Hoist ADD and copy NUW if both ops have it.93; Version where operands are commuted.94define void @add_nuw_comm(i64 %c1, i64 %c2) {95; CHECK-LABEL: @add_nuw_comm(96; CHECK-NEXT: entry:97; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]98; CHECK-NEXT: br label [[LOOP:%.*]]99; CHECK: loop:100; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]101; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]102; CHECK-NEXT: br label [[LOOP]]103;104entry:105 br label %loop106 107loop:108 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]109 %step.add = add nuw i64 %c1, %index110 %index.next = add nuw i64 %step.add, %c2111 br label %loop112}113 114; Hoist ADD and copy NUW if both ops have it.115; Another version where operands are commuted.116define void @add_nuw_comm2(i64 %c1, i64 %c2) {117; CHECK-LABEL: @add_nuw_comm2(118; CHECK-NEXT: entry:119; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]120; CHECK-NEXT: br label [[LOOP:%.*]]121; CHECK: loop:122; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]123; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]124; CHECK-NEXT: br label [[LOOP]]125;126entry:127 br label %loop128 129loop:130 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]131 %step.add = add nuw i64 %index, %c1132 %index.next = add nuw i64 %c2, %step.add133 br label %loop134}135 136; Hoist ADD and copy NUW if both ops have it.137; Another version where operands are commuted.138define void @add_nuw_comm3(i64 %c1, i64 %c2) {139; CHECK-LABEL: @add_nuw_comm3(140; CHECK-NEXT: entry:141; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2:%.*]]142; CHECK-NEXT: br label [[LOOP:%.*]]143; CHECK: loop:144; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]145; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]146; CHECK-NEXT: br label [[LOOP]]147;148entry:149 br label %loop150 151loop:152 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]153 %step.add = add nuw i64 %c1, %index154 %index.next = add nuw i64 %c2, %step.add155 br label %loop156}157 158; Hoist ADD and copy NUW if both ops have it.159; A version where the LHS and RHS of the outer BinOp are BinOps.160define void @add_nuw_twobinops(i64 %c1, i64 %c2) {161; CHECK-LABEL: @add_nuw_twobinops(162; CHECK-NEXT: entry:163; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw i64 [[C2:%.*]], 2164; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw i64 [[C1:%.*]], [[C2_PLUS_2]]165; CHECK-NEXT: br label [[LOOP:%.*]]166; CHECK: loop:167; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]168; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw i64 [[INDEX]], [[INVARIANT_OP]]169; CHECK-NEXT: br label [[LOOP]]170;171entry:172 br label %loop173 174loop:175 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]176 %step.add = add nuw i64 %c1, %index177 %c2.plus.2 = add nuw i64 %c2, 2178 %index.next = add nuw i64 %step.add, %c2.plus.2179 br label %loop180}181 182; Hoist MUL and drop NUW even if both ops have it.183define void @mul_nuw(<2 x i64> %c1, <2 x i64> %c2) {184; CHECK-LABEL: @mul_nuw(185; CHECK-NEXT: entry:186; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]187; CHECK-NEXT: br label [[LOOP:%.*]]188; CHECK: loop:189; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]190; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]]191; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])192; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]193; CHECK-NEXT: br label [[LOOP]]194;195entry:196 br label %loop197 198loop:199 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]200 %step.add = mul nuw <2 x i64> %index, %c1201 call void @use(<2 x i64> %step.add)202 %index.next = mul nuw <2 x i64> %step.add, %c2203 br label %loop204}205 206; Hoist MUL and drop NUW even if both ops have it.207; Version where operands are commuted.208define void @mul_nuw_comm(<2 x i64> %c1, <2 x i64> %c2) {209; CHECK-LABEL: @mul_nuw_comm(210; CHECK-NEXT: entry:211; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]212; CHECK-NEXT: br label [[LOOP:%.*]]213; CHECK: loop:214; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]215; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]216; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])217; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]218; CHECK-NEXT: br label [[LOOP]]219;220entry:221 br label %loop222 223loop:224 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]225 %step.add = mul nuw <2 x i64> %c1, %index226 call void @use(<2 x i64> %step.add)227 %index.next = mul nuw <2 x i64> %step.add, %c2228 br label %loop229}230 231; Hoist MUL and drop NUW even if both ops have it.232; Another version where operands are commuted.233define void @mul_nuw_comm2(<2 x i64> %c1, <2 x i64> %c2) {234; CHECK-LABEL: @mul_nuw_comm2(235; CHECK-NEXT: entry:236; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]237; CHECK-NEXT: br label [[LOOP:%.*]]238; CHECK: loop:239; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]240; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[INDEX]], [[C1]]241; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])242; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]243; CHECK-NEXT: br label [[LOOP]]244;245entry:246 br label %loop247 248loop:249 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]250 %step.add = mul nuw <2 x i64> %index, %c1251 call void @use(<2 x i64> %step.add)252 %index.next = mul nuw <2 x i64> %c2, %step.add253 br label %loop254}255 256; Hoist MUL and drop NUW even if both ops have it.257; Another version where operands are commuted.258define void @mul_nuw_comm3(<2 x i64> %c1, <2 x i64> %c2) {259; CHECK-LABEL: @mul_nuw_comm3(260; CHECK-NEXT: entry:261; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]262; CHECK-NEXT: br label [[LOOP:%.*]]263; CHECK: loop:264; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]265; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]266; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])267; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]268; CHECK-NEXT: br label [[LOOP]]269;270entry:271 br label %loop272 273loop:274 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]275 %step.add = mul nuw <2 x i64> %c1, %index276 call void @use(<2 x i64> %step.add)277 %index.next = mul nuw <2 x i64> %c2, %step.add278 br label %loop279}280 281; Hoist MUL and drop NUW even if both ops have it.282; A version where the LHS and RHS of the outer BinOp are BinOps.283define void @mul_nuw_twobinops(<2 x i64> %c1, <2 x i64> %c2) {284; CHECK-LABEL: @mul_nuw_twobinops(285; CHECK-NEXT: entry:286; CHECK-NEXT: [[C2_PLUS_2:%.*]] = add nuw <2 x i64> [[C2:%.*]], splat (i64 2)287; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2_PLUS_2]]288; CHECK-NEXT: br label [[LOOP:%.*]]289; CHECK: loop:290; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]291; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nuw <2 x i64> [[C1]], [[INDEX]]292; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])293; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]294; CHECK-NEXT: br label [[LOOP]]295;296entry:297 br label %loop298 299loop:300 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]301 %step.add = mul nuw <2 x i64> %c1, %index302 call void @use(<2 x i64> %step.add)303 %c2.plus.2 = add nuw <2 x i64> %c2, <i64 2, i64 2>304 %index.next = mul nuw <2 x i64> %step.add, %c2.plus.2305 br label %loop306}307 308; Hoist ADD but don't copy NUW if only one op has it.309define void @add_no_nuw(i64 %c1, i64 %c2) {310; CHECK-LABEL: @add_no_nuw(311; CHECK-NEXT: entry:312; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]313; CHECK-NEXT: br label [[LOOP:%.*]]314; CHECK: loop:315; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]316; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]317; CHECK-NEXT: br label [[LOOP]]318;319entry:320 br label %loop321 322loop:323 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]324 %step.add = add i64 %index, %c1325 %index.next = add nuw i64 %step.add, %c2326 br label %loop327}328 329; Hoist ADD but don't copy NSW if one op has it.330define void @add_no_nsw(i64 %c1, i64 %c2) {331; CHECK-LABEL: @add_no_nsw(332; CHECK-NEXT: entry:333; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]334; CHECK-NEXT: br label [[LOOP:%.*]]335; CHECK: loop:336; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]337; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]338; CHECK-NEXT: br label [[LOOP]]339;340entry:341 br label %loop342 343loop:344 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]345 %step.add = add i64 %index, %c1346 %index.next = add nsw i64 %step.add, %c2347 br label %loop348}349 350; Hoist ADD but don't copy NSW even if both ops have it.351define void @add_no_nsw_2(i64 %c1, i64 %c2) {352; CHECK-LABEL: @add_no_nsw_2(353; CHECK-NEXT: entry:354; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]355; CHECK-NEXT: br label [[LOOP:%.*]]356; CHECK: loop:357; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]358; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]359; CHECK-NEXT: br label [[LOOP]]360;361entry:362 br label %loop363 364loop:365 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]366 %step.add = add nsw i64 %index, %c1367 %index.next = add nsw i64 %step.add, %c2368 br label %loop369}370 371; FIXME: Hoist ADD and copy NUW NSW if both ops have it.372define void @add_nuw_nsw(i64 %c1, i64 %c2) {373; CHECK-LABEL: @add_nuw_nsw(374; CHECK-NEXT: entry:375; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add nuw nsw i64 [[C1:%.*]], [[C2:%.*]]376; CHECK-NEXT: br label [[LOOP:%.*]]377; CHECK: loop:378; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]379; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add nuw nsw i64 [[INDEX]], [[INVARIANT_OP]]380; CHECK-NEXT: br label [[LOOP]]381;382entry:383 br label %loop384 385loop:386 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]387 %step.add = add nuw nsw i64 %index, %c1388 %index.next = add nuw nsw i64 %step.add, %c2389 br label %loop390}391 392define void @add_both_nsw_first_nuw(i64 %c1, i64 %c2) {393; CHECK-LABEL: @add_both_nsw_first_nuw(394; CHECK-NEXT: entry:395; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]396; CHECK-NEXT: br label [[LOOP:%.*]]397; CHECK: loop:398; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]399; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]400; CHECK-NEXT: br label [[LOOP]]401;402entry:403 br label %loop404 405loop:406 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]407 %step.add = add nuw nsw i64 %index, %c1408 %index.next = add nsw i64 %step.add, %c2409 br label %loop410}411 412define void @add_both_nsw_second_nuw(i64 %c1, i64 %c2) {413; CHECK-LABEL: @add_both_nsw_second_nuw(414; CHECK-NEXT: entry:415; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add i64 [[C1:%.*]], [[C2:%.*]]416; CHECK-NEXT: br label [[LOOP:%.*]]417; CHECK: loop:418; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]419; CHECK-NEXT: [[INDEX_NEXT_REASS]] = add i64 [[INDEX]], [[INVARIANT_OP]]420; CHECK-NEXT: br label [[LOOP]]421;422entry:423 br label %loop424 425loop:426 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]427 %step.add = add nsw i64 %index, %c1428 %index.next = add nuw nsw i64 %step.add, %c2429 br label %loop430}431 432;433; Hoist MUL and drop NSW even if both ops have it.434define void @mul_no_nsw_2(<2 x i64> %c1, <2 x i64> %c2) {435; CHECK-LABEL: @mul_no_nsw_2(436; CHECK-NEXT: entry:437; CHECK-NEXT: [[INVARIANT_OP:%.*]] = mul <2 x i64> [[C1:%.*]], [[C2:%.*]]438; CHECK-NEXT: br label [[LOOP:%.*]]439; CHECK: loop:440; CHECK-NEXT: [[INDEX:%.*]] = phi <2 x i64> [ zeroinitializer, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]441; CHECK-NEXT: [[STEP_ADD:%.*]] = mul nsw <2 x i64> [[INDEX]], [[C1]]442; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])443; CHECK-NEXT: [[INDEX_NEXT_REASS]] = mul <2 x i64> [[INDEX]], [[INVARIANT_OP]]444; CHECK-NEXT: br label [[LOOP]]445;446entry:447 br label %loop448 449loop:450 %index = phi <2 x i64> [ zeroinitializer, %entry ], [ %index.next, %loop ]451 %step.add = mul nsw <2 x i64> %index, %c1452 call void @use(<2 x i64> %step.add)453 %index.next = mul nsw <2 x i64> %step.add, %c2454 br label %loop455}456 457; Don't hoist if the ops are different (even if they are both associative).458define void @diff_ops(i64 %c1, i64 %c2) {459; CHECK-LABEL: @diff_ops(460; CHECK-NEXT: entry:461; CHECK-NEXT: br label [[LOOP:%.*]]462; CHECK: loop:463; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]464; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]465; CHECK-NEXT: [[INDEX_NEXT]] = mul i64 [[STEP_ADD]], [[C2:%.*]]466; CHECK-NEXT: br label [[LOOP]]467;468entry:469 br label %loop470 471loop:472 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]473 %step.add = add i64 %index, %c1474 %index.next = mul i64 %step.add, %c2475 br label %loop476}477 478; Don't hoist if the ops are not associative.479define void @noassoc_ops(i64 %c1, i64 %c2) {480; CHECK-LABEL: @noassoc_ops(481; CHECK-NEXT: entry:482; CHECK-NEXT: br label [[LOOP:%.*]]483; CHECK: loop:484; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]485; CHECK-NEXT: [[STEP_ADD:%.*]] = sub i64 [[INDEX]], [[C1:%.*]]486; CHECK-NEXT: [[INDEX_NEXT]] = sub i64 [[STEP_ADD]], [[C2:%.*]]487; CHECK-NEXT: br label [[LOOP]]488;489entry:490 br label %loop491 492loop:493 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]494 %step.add = sub i64 %index, %c1495 %index.next = sub i64 %step.add, %c2496 br label %loop497}498 499; The simple case. Hoist if fast is present on both instructions.500define void @fadd_fast(float %c1, float %c2) {501; CHECK-LABEL: @fadd_fast(502; CHECK-NEXT: entry:503; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fadd fast float [[C1:%.*]], [[C2:%.*]]504; CHECK-NEXT: br label [[LOOP:%.*]]505; CHECK: loop:506; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]507; CHECK-NEXT: [[STEP_ADD:%.*]] = fadd fast float [[INDEX]], [[C1]]508; CHECK-NEXT: call void @use(float [[STEP_ADD]])509; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fadd fast float [[INDEX]], [[INVARIANT_OP]]510; CHECK-NEXT: br label [[LOOP]]511;512entry:513 br label %loop514 515loop:516 %index = phi float [ 0., %entry ], [ %index.next, %loop ]517 %step.add = fadd fast float %index, %c1518 call void @use(float %step.add)519 %index.next = fadd fast float %step.add, %c2520 br label %loop521}522 523; The simple case. Hoist if fast is present on both instructions.524define void @fmul_fast(float %c1, float %c2) {525; CHECK-LABEL: @fmul_fast(526; CHECK-NEXT: entry:527; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fmul fast float [[C1:%.*]], [[C2:%.*]]528; CHECK-NEXT: br label [[LOOP:%.*]]529; CHECK: loop:530; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]531; CHECK-NEXT: [[STEP_ADD:%.*]] = fmul fast float [[INDEX]], [[C1]]532; CHECK-NEXT: call void @use(float [[STEP_ADD]])533; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fmul fast float [[INDEX]], [[INVARIANT_OP]]534; CHECK-NEXT: br label [[LOOP]]535;536entry:537 br label %loop538 539loop:540 %index = phi float [ 0., %entry ], [ %index.next, %loop ]541 %step.add = fmul fast float %index, %c1542 call void @use(float %step.add)543 %index.next = fmul fast float %step.add, %c2544 br label %loop545}546 547; The minimum case.548; Hoist if reasassoc and nsz are present on both instructions.549define void @fadd_reassoc_nsz(float %c1, float %c2) {550; CHECK-LABEL: @fadd_reassoc_nsz(551; CHECK-NEXT: entry:552; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fadd reassoc nsz float [[C1:%.*]], [[C2:%.*]]553; CHECK-NEXT: br label [[LOOP:%.*]]554; CHECK: loop:555; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]556; CHECK-NEXT: [[STEP_ADD:%.*]] = fadd reassoc nsz float [[INDEX]], [[C1]]557; CHECK-NEXT: call void @use(float [[STEP_ADD]])558; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fadd reassoc nsz float [[INDEX]], [[INVARIANT_OP]]559; CHECK-NEXT: br label [[LOOP]]560;561entry:562 br label %loop563 564loop:565 %index = phi float [ 0., %entry ], [ %index.next, %loop ]566 %step.add = fadd reassoc nsz float %index, %c1567 call void @use(float %step.add)568 %index.next = fadd reassoc nsz float %step.add, %c2569 br label %loop570}571 572; The minimum case.573; Hoist if reasassoc and nsz are present on both instructions.574define void @fmul_reassoc_nsz(float %c1, float %c2) {575; CHECK-LABEL: @fmul_reassoc_nsz(576; CHECK-NEXT: entry:577; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fmul reassoc nsz float [[C1:%.*]], [[C2:%.*]]578; CHECK-NEXT: br label [[LOOP:%.*]]579; CHECK: loop:580; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]581; CHECK-NEXT: [[STEP_ADD:%.*]] = fmul reassoc nsz float [[INDEX]], [[C1]]582; CHECK-NEXT: call void @use(float [[STEP_ADD]])583; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fmul reassoc nsz float [[INDEX]], [[INVARIANT_OP]]584; CHECK-NEXT: br label [[LOOP]]585;586entry:587 br label %loop588 589loop:590 %index = phi float [ 0., %entry ], [ %index.next, %loop ]591 %step.add = fmul reassoc nsz float %index, %c1592 call void @use(float %step.add)593 %index.next = fmul reassoc nsz float %step.add, %c2594 br label %loop595}596 597; Don't hoist if both reassoc and nsz aren't present on both instructions.598define void @fadd_nonassoc(float %c1, float %c2) {599; CHECK-LABEL: @fadd_nonassoc(600; CHECK-NEXT: entry:601; CHECK-NEXT: br label [[LOOP:%.*]]602; CHECK: loop:603; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]604; CHECK-NEXT: [[STEP_ADD:%.*]] = fadd reassoc float [[INDEX]], [[C1:%.*]]605; CHECK-NEXT: call void @use(float [[STEP_ADD]])606; CHECK-NEXT: [[INDEX_NEXT]] = fadd reassoc nsz float [[STEP_ADD]], [[C2:%.*]]607; CHECK-NEXT: br label [[LOOP]]608;609entry:610 br label %loop611 612loop:613 %index = phi float [ 0., %entry ], [ %index.next, %loop ]614 %step.add = fadd reassoc float %index, %c1615 call void @use(float %step.add)616 %index.next = fadd reassoc nsz float %step.add, %c2617 br label %loop618}619 620; Don't hoist if both reassoc and nsz aren't present on both instructions.621define void @fmul_noassoc(float %c1, float %c2) {622; CHECK-LABEL: @fmul_noassoc(623; CHECK-NEXT: entry:624; CHECK-NEXT: br label [[LOOP:%.*]]625; CHECK: loop:626; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]627; CHECK-NEXT: [[STEP_ADD:%.*]] = fmul reassoc nsz float [[INDEX]], [[C1:%.*]]628; CHECK-NEXT: call void @use(float [[STEP_ADD]])629; CHECK-NEXT: [[INDEX_NEXT]] = fmul nsz float [[STEP_ADD]], [[C2:%.*]]630; CHECK-NEXT: br label [[LOOP]]631;632entry:633 br label %loop634 635loop:636 %index = phi float [ 0., %entry ], [ %index.next, %loop ]637 %step.add = fmul reassoc nsz float %index, %c1638 call void @use(float %step.add)639 %index.next = fmul nsz float %step.add, %c2640 br label %loop641}642 643; No intersection in flags present on both instructions,644; except reassoc and nsz.645define void @fadd_fmf_nointersect(float %c1, float %c2) {646; CHECK-LABEL: @fadd_fmf_nointersect(647; CHECK-NEXT: entry:648; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fadd reassoc nsz float [[C1:%.*]], [[C2:%.*]]649; CHECK-NEXT: br label [[LOOP:%.*]]650; CHECK: loop:651; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]652; CHECK-NEXT: [[STEP_ADD:%.*]] = fadd reassoc nnan nsz float [[INDEX]], [[C1]]653; CHECK-NEXT: call void @use(float [[STEP_ADD]])654; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fadd reassoc nsz float [[INDEX]], [[INVARIANT_OP]]655; CHECK-NEXT: br label [[LOOP]]656;657entry:658 br label %loop659 660loop:661 %index = phi float [ 0., %entry ], [ %index.next, %loop ]662 %step.add = fadd reassoc nsz nnan float %index, %c1663 call void @use(float %step.add)664 %index.next = fadd reassoc nsz ninf float %step.add, %c2665 br label %loop666}667 668; No intersection in flags present on both instructions,669; except reassoc and nsz.670define void @fmul_fmf_nointersect(float %c1, float %c2) {671; CHECK-LABEL: @fmul_fmf_nointersect(672; CHECK-NEXT: entry:673; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fmul reassoc nsz float [[C1:%.*]], [[C2:%.*]]674; CHECK-NEXT: br label [[LOOP:%.*]]675; CHECK: loop:676; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]677; CHECK-NEXT: [[STEP_ADD:%.*]] = fmul reassoc nsz contract float [[INDEX]], [[C1]]678; CHECK-NEXT: call void @use(float [[STEP_ADD]])679; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fmul reassoc nsz float [[INDEX]], [[INVARIANT_OP]]680; CHECK-NEXT: br label [[LOOP]]681;682entry:683 br label %loop684 685loop:686 %index = phi float [ 0., %entry ], [ %index.next, %loop ]687 %step.add = fmul reassoc nsz contract float %index, %c1688 call void @use(float %step.add)689 %index.next = fmul reassoc nnan nsz float %step.add, %c2690 br label %loop691}692 693; Non-empty intersection in flags present on both instructions,694; including reassoc and nsz.695define void @fadd_fmf_intersect(float %c1, float %c2) {696; CHECK-LABEL: @fadd_fmf_intersect(697; CHECK-NEXT: entry:698; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fadd reassoc ninf nsz float [[C1:%.*]], [[C2:%.*]]699; CHECK-NEXT: br label [[LOOP:%.*]]700; CHECK: loop:701; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]702; CHECK-NEXT: [[STEP_ADD:%.*]] = fadd reassoc nnan ninf nsz float [[INDEX]], [[C1]]703; CHECK-NEXT: call void @use(float [[STEP_ADD]])704; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fadd reassoc ninf nsz float [[INDEX]], [[INVARIANT_OP]]705; CHECK-NEXT: br label [[LOOP]]706;707entry:708 br label %loop709 710loop:711 %index = phi float [ 0., %entry ], [ %index.next, %loop ]712 %step.add = fadd reassoc nnan nsz ninf float %index, %c1713 call void @use(float %step.add)714 %index.next = fadd reassoc ninf nsz float %step.add, %c2715 br label %loop716}717 718; Non-empty intersection in flags present on both instructions,719; including reassoc and nsz.720define void @fmul_fmf_intersect(float %c1, float %c2) {721; CHECK-LABEL: @fmul_fmf_intersect(722; CHECK-NEXT: entry:723; CHECK-NEXT: [[INVARIANT_OP:%.*]] = fmul reassoc nsz afn float [[C1:%.*]], [[C2:%.*]]724; CHECK-NEXT: br label [[LOOP:%.*]]725; CHECK: loop:726; CHECK-NEXT: [[INDEX:%.*]] = phi float [ 0.000000e+00, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]727; CHECK-NEXT: [[STEP_ADD:%.*]] = fmul reassoc nsz arcp afn float [[INDEX]], [[C1]]728; CHECK-NEXT: call void @use(float [[STEP_ADD]])729; CHECK-NEXT: [[INDEX_NEXT_REASS]] = fmul reassoc nsz afn float [[INDEX]], [[INVARIANT_OP]]730; CHECK-NEXT: br label [[LOOP]]731;732entry:733 br label %loop734 735loop:736 %index = phi float [ 0., %entry ], [ %index.next, %loop ]737 %step.add = fmul reassoc afn nsz arcp float %index, %c1738 call void @use(float %step.add)739 %index.next = fmul reassoc nsz afn float %step.add, %c2740 br label %loop741}742 743; Trivially hoist and.744define void @and(i64 %c1, i64 %c2) {745; CHECK-LABEL: @and(746; CHECK-NEXT: entry:747; CHECK-NEXT: [[INVARIANT_OP:%.*]] = and i64 [[C1:%.*]], [[C2:%.*]]748; CHECK-NEXT: br label [[LOOP:%.*]]749; CHECK: loop:750; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]751; CHECK-NEXT: [[INDEX_NEXT_REASS]] = and i64 [[INDEX]], [[INVARIANT_OP]]752; CHECK-NEXT: br label [[LOOP]]753;754entry:755 br label %loop756 757loop:758 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]759 %step.add = and i64 %index, %c1760 %index.next = and i64 %step.add, %c2761 br label %loop762}763 764; Trivially hoist or.765define void @or(i64 %c1, i64 %c2) {766; CHECK-LABEL: @or(767; CHECK-NEXT: entry:768; CHECK-NEXT: [[INVARIANT_OP:%.*]] = or i64 [[C1:%.*]], [[C2:%.*]]769; CHECK-NEXT: br label [[LOOP:%.*]]770; CHECK: loop:771; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]772; CHECK-NEXT: [[INDEX_NEXT_REASS]] = or i64 [[INDEX]], [[INVARIANT_OP]]773; CHECK-NEXT: br label [[LOOP]]774;775entry:776 br label %loop777 778loop:779 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]780 %step.add = or i64 %index, %c1781 %index.next = or i64 %c2, %step.add782 br label %loop783}784 785; Trivially hoist or disjoint.786define void @or_all_disjoint(i64 %c1, i64 %c2) {787; CHECK-LABEL: @or_all_disjoint(788; CHECK-NEXT: entry:789; CHECK-NEXT: [[INVARIANT_OP:%.*]] = or disjoint i64 [[C1:%.*]], [[C2:%.*]]790; CHECK-NEXT: br label [[LOOP:%.*]]791; CHECK: loop:792; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]793; CHECK-NEXT: [[INDEX_NEXT_REASS]] = or disjoint i64 [[INDEX]], [[INVARIANT_OP]]794; CHECK-NEXT: br label [[LOOP]]795;796entry:797 br label %loop798 799loop:800 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]801 %step.add = or disjoint i64 %index, %c1802 %index.next = or disjoint i64 %c2, %step.add803 br label %loop804}805 806; Trivially hoist or, disjoint on first or only .807define void @or_disjoint_on_first_or_only(i64 %c1, i64 %c2) {808; CHECK-LABEL: @or_disjoint_on_first_or_only(809; CHECK-NEXT: entry:810; CHECK-NEXT: [[INVARIANT_OP:%.*]] = or i64 [[C1:%.*]], [[C2:%.*]]811; CHECK-NEXT: br label [[LOOP:%.*]]812; CHECK: loop:813; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]814; CHECK-NEXT: [[INDEX_NEXT_REASS]] = or i64 [[INDEX]], [[INVARIANT_OP]]815; CHECK-NEXT: br label [[LOOP]]816;817entry:818 br label %loop819 820loop:821 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]822 %step.add = or i64 %index, %c1823 %index.next = or disjoint i64 %c2, %step.add824 br label %loop825}826 827; Trivially hoist or, disjoint on second or only .828define void @or_disjoint_on_second_or_only(i64 %c1, i64 %c2) {829; CHECK-LABEL: @or_disjoint_on_second_or_only(830; CHECK-NEXT: entry:831; CHECK-NEXT: [[INVARIANT_OP:%.*]] = or i64 [[C1:%.*]], [[C2:%.*]]832; CHECK-NEXT: br label [[LOOP:%.*]]833; CHECK: loop:834; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]835; CHECK-NEXT: [[INDEX_NEXT_REASS]] = or i64 [[INDEX]], [[INVARIANT_OP]]836; CHECK-NEXT: br label [[LOOP]]837;838entry:839 br label %loop840 841loop:842 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]843 %step.add = or disjoint i64 %index, %c1844 %index.next = or i64 %c2, %step.add845 br label %loop846}847 848; Trivially hoist xor.849define void @xor(i64 %c1, i64 %c2) {850; CHECK-LABEL: @xor(851; CHECK-NEXT: entry:852; CHECK-NEXT: [[INVARIANT_OP:%.*]] = xor i64 [[C1:%.*]], [[C2:%.*]]853; CHECK-NEXT: br label [[LOOP:%.*]]854; CHECK: loop:855; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT_REASS:%.*]], [[LOOP]] ]856; CHECK-NEXT: [[INDEX_NEXT_REASS]] = xor i64 [[INDEX]], [[INVARIANT_OP]]857; CHECK-NEXT: br label [[LOOP]]858;859entry:860 br label %loop861 862loop:863 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]864 %step.add = xor i64 %c1, %index865 %index.next = xor i64 %step.add, %c2866 br label %loop867}868 869; Don't hoist if the intermediate op has more than two uses. This is an870; heuristic that can be adjusted if warranted. Currently we are being871; conservative to minimise potential impact in code size.872define void @not_many_uses(i64 %c1, i64 %c2, i64 %c3) {873; CHECK-LABEL: @not_many_uses(874; CHECK-NEXT: entry:875; CHECK-NEXT: br label [[LOOP:%.*]]876; CHECK: loop:877; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]878; CHECK-NEXT: [[STEP_ADD:%.*]] = add i64 [[INDEX]], [[C1:%.*]]879; CHECK-NEXT: call void @use(i64 [[STEP_ADD]])880; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[STEP_ADD]], [[C2:%.*]]881; CHECK-NEXT: [[OTHER:%.*]] = add i64 [[STEP_ADD]], [[C3:%.*]]882; CHECK-NEXT: call void @use(i64 [[OTHER]])883; CHECK-NEXT: br label [[LOOP]]884;885entry:886 br label %loop887 888loop:889 %index = phi i64 [ 0, %entry ], [ %index.next, %loop ]890 %step.add = add i64 %index, %c1891 call void @use(i64 %step.add)892 %index.next = add i64 %step.add, %c2893 %other = add i64 %step.add, %c3894 call void @use(i64 %other)895 br label %loop896}897 898; Original reproducer, adapted from:899; for(long i = 0; i < n; ++i)900; a[i] = (i*k) * v;901define void @test(i64 %n, i64 %k) {902; CHECK-LABEL: @test(903; CHECK-NEXT: entry:904; CHECK-NEXT: [[K_2:%.*]] = shl nuw nsw i64 [[K:%.*]], 1905; CHECK-NEXT: [[VEC_INIT:%.*]] = insertelement <2 x i64> zeroinitializer, i64 [[K]], i64 1906; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[K_2]], i64 0907; CHECK-NEXT: [[DOTSPLAT:%.*]] = shufflevector <2 x i64> [[DOTSPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer908; CHECK-NEXT: [[INVARIANT_OP:%.*]] = add <2 x i64> [[DOTSPLAT]], [[DOTSPLAT]]909; CHECK-NEXT: br label [[LOOP:%.*]]910; CHECK: loop:911; CHECK-NEXT: [[VEC_IND:%.*]] = phi <2 x i64> [ [[VEC_INIT]], [[ENTRY:%.*]] ], [ [[VEC_IND_NEXT_REASS:%.*]], [[LOOP]] ]912; CHECK-NEXT: [[STEP_ADD:%.*]] = add <2 x i64> [[VEC_IND]], [[DOTSPLAT]]913; CHECK-NEXT: call void @use(<2 x i64> [[STEP_ADD]])914; CHECK-NEXT: [[VEC_IND_NEXT_REASS]] = add <2 x i64> [[VEC_IND]], [[INVARIANT_OP]]915; CHECK-NEXT: br label [[LOOP]]916;917entry:918 %k.2 = shl nuw nsw i64 %k, 1919 %vec.init = insertelement <2 x i64> zeroinitializer, i64 %k, i64 1920 %.splatinsert = insertelement <2 x i64> poison, i64 %k.2, i64 0921 %.splat = shufflevector <2 x i64> %.splatinsert, <2 x i64> poison, <2 x i32> zeroinitializer922 br label %loop923 924loop:925 %vec.ind = phi <2 x i64> [ %vec.init, %entry ], [ %vec.ind.next, %loop ]926 %step.add = add <2 x i64> %vec.ind, %.splat927 call void @use(<2 x i64> %step.add)928 %vec.ind.next = add <2 x i64> %step.add, %.splat929 br label %loop930}931 932declare void @use()933