brintos

brintos / llvm-project-archived public Read only

0
0
Text · 32.6 KiB · 724f459 Raw
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