768 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals2; RUN: opt -S -passes='sroa<preserve-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG3; RUN: opt -S -passes='sroa<modify-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG4 5%pair = type { i32, i32 }6 7;.8; CHECK: @g = global %pair zeroinitializer, align 49;.10define i32 @test_sroa_phi_gep(i1 %cond) {11; CHECK-LABEL: @test_sroa_phi_gep(12; CHECK-NEXT: entry:13; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]14; CHECK: if.then:15; CHECK-NEXT: br label [[END]]16; CHECK: end:17; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]18; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]19;20entry:21 %a = alloca %pair, align 422 %b = alloca %pair, align 423 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 124 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 125 store i32 1, ptr %gep_a, align 426 store i32 2, ptr %gep_b, align 427 br i1 %cond, label %if.then, label %end28 29if.then:30 br label %end31 32end:33 %phi = phi ptr [ %a, %entry], [ %b, %if.then ]34 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 135 %load = load i32, ptr %gep, align 436 ret i32 %load37}38 39define i32 @test_sroa_phi_gep_non_inbound(i1 %cond) {40; CHECK-LABEL: @test_sroa_phi_gep_non_inbound(41; CHECK-NEXT: entry:42; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]43; CHECK: if.then:44; CHECK-NEXT: br label [[END]]45; CHECK: end:46; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ]47; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]48;49entry:50 %a = alloca %pair, align 451 %b = alloca %pair, align 452 %gep_a = getelementptr %pair, ptr %a, i32 0, i32 153 %gep_b = getelementptr %pair, ptr %b, i32 0, i32 154 store i32 1, ptr %gep_a, align 455 store i32 2, ptr %gep_b, align 456 br i1 %cond, label %if.then, label %end57 58if.then:59 br label %end60 61end:62 %phi = phi ptr [ %a, %entry], [ %b, %if.then ]63 %gep = getelementptr %pair, ptr %phi, i32 0, i32 164 %load = load i32, ptr %gep, align 465 ret i32 %load66}67 68define i32 @test_sroa_phi_gep_poison(i1 %cond) {69; CHECK-LABEL: @test_sroa_phi_gep_poison(70; CHECK-NEXT: entry:71; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]72; CHECK: if.then:73; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr poison, align 474; CHECK-NEXT: br label [[END]]75; CHECK: end:76; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ]77; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]78;79entry:80 %a = alloca %pair, align 481 br i1 %cond, label %if.then, label %end82 83if.then:84 br label %end85 86end:87 %phi = phi ptr [ %a, %entry], [ poison, %if.then ]88 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 189 %load = load i32, ptr %gep, align 490 ret i32 %load91}92 93@g = global %pair zeroinitializer, align 494 95define i32 @test_sroa_phi_gep_global(i1 %cond) {96; CHECK-LABEL: @test_sroa_phi_gep_global(97; CHECK-NEXT: entry:98; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]99; CHECK: if.then:100; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr getelementptr inbounds ([[PAIR:%.*]], ptr @g, i32 0, i32 1), align 4101; CHECK-NEXT: br label [[END]]102; CHECK: end:103; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ]104; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]105;106entry:107 %a = alloca %pair, align 4108 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1109 store i32 1, ptr %gep_a, align 4110 br i1 %cond, label %if.then, label %end111 112if.then:113 br label %end114 115end:116 %phi = phi ptr [ %a, %entry], [ @g, %if.then ]117 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1118 %load = load i32, ptr %gep, align 4119 ret i32 %load120}121 122define i32 @test_sroa_phi_gep_arg_phi_inspt(i1 %cond) {123; CHECK-LABEL: @test_sroa_phi_gep_arg_phi_inspt(124; CHECK-NEXT: entry:125; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]126; CHECK: for:127; CHECK-NEXT: [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]128; CHECK-NEXT: [[I]] = add i32 [[PHI_INSPT]], 1129; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10130; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]]131; CHECK: end:132; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 2, [[FOR]] ]133; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]134;135entry:136 %a = alloca %pair, align 4137 %b = alloca %pair, align 4138 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1139 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1140 store i32 1, ptr %gep_a, align 4141 store i32 2, ptr %gep_b, align 4142 br i1 %cond, label %for, label %end143 144for:145 %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]146 %i = add i32 %phi_inspt, 1147 %loop.cond = icmp ult i32 %i, 10148 br i1 %loop.cond, label %for, label %end149 150end:151 %phi = phi ptr [ %a, %entry], [ %b, %for ]152 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1153 %load = load i32, ptr %gep, align 4154 ret i32 %load155}156 157define i32 @test_sroa_phi_gep_phi_inspt(i1 %cond) {158; CHECK-LABEL: @test_sroa_phi_gep_phi_inspt(159; CHECK-NEXT: entry:160; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4161; CHECK-NEXT: [[B:%.*]] = alloca [[PAIR]], align 4162; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1163; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1164; CHECK-NEXT: store i32 1, ptr [[GEP_A]], align 4165; CHECK-NEXT: store i32 2, ptr [[GEP_B]], align 4166; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]167; CHECK: for:168; CHECK-NEXT: [[PHI_IN:%.*]] = phi ptr [ null, [[ENTRY:%.*]] ], [ [[B]], [[FOR]] ]169; CHECK-NEXT: [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I:%.*]], [[FOR]] ]170; CHECK-NEXT: [[I]] = add i32 [[PHI_INSPT]], 1171; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10172; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]]173; CHECK: end:174; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[PHI_IN]], [[FOR]] ]175; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1176; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4177; CHECK-NEXT: ret i32 [[LOAD]]178;179entry:180 %a = alloca %pair, align 4181 %b = alloca %pair, align 4182 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1183 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1184 store i32 1, ptr %gep_a, align 4185 store i32 2, ptr %gep_b, align 4186 br i1 %cond, label %for, label %end187 188for:189 %phi_in = phi ptr [ null, %entry ], [ %b, %for ]190 %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ]191 %i = add i32 %phi_inspt, 1192 %loop.cond = icmp ult i32 %i, 10193 br i1 %loop.cond, label %for, label %end194 195end:196 %phi = phi ptr [ %a, %entry], [ %phi_in, %for ]197 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1198 %load = load i32, ptr %gep, align 4199 ret i32 %load200}201 202define i32 @test_sroa_gep_phi_gep(i1 %cond) {203; CHECK-LABEL: @test_sroa_gep_phi_gep(204; CHECK-NEXT: entry:205; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4206; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]207; CHECK: for:208; CHECK-NEXT: [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]209; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ]210; CHECK-NEXT: [[I]] = add i32 [[PHI_I]], 1211; CHECK-NEXT: [[GEP_FOR]] = getelementptr inbounds i32, ptr [[PHI]], i32 0212; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10213; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]]214; CHECK: end:215; CHECK-NEXT: [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]216; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4217; CHECK-NEXT: ret i32 [[LOAD]]218;219entry:220 %a = alloca %pair, align 4221 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1222 br i1 %cond, label %for, label %end223 224for:225 %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]226 %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ]227 %i = add i32 %phi_i, 1228 %gep_for = getelementptr inbounds i32, ptr %phi, i32 0229 %loop.cond = icmp ult i32 %i, 10230 br i1 %loop.cond, label %for, label %end231 232end:233 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]234 %load = load i32, ptr %phi_end, align 4235 ret i32 %load236}237 238define i32 @test_sroa_invoke_phi_gep(i1 %cond) personality ptr @__gxx_personality_v0 {239; CHECK-LABEL: @test_sroa_invoke_phi_gep(240; CHECK-NEXT: entry:241; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4242; CHECK-NEXT: br i1 [[COND:%.*]], label [[CALL:%.*]], label [[END:%.*]]243; CHECK: call:244; CHECK-NEXT: [[B:%.*]] = invoke ptr @foo()245; CHECK-NEXT: to label [[END]] unwind label [[INVOKE_CATCH:%.*]]246; CHECK: end:247; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[CALL]] ]248; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1249; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4250; CHECK-NEXT: ret i32 [[LOAD]]251; CHECK: invoke_catch:252; CHECK-NEXT: [[RES:%.*]] = landingpad { ptr, i32 }253; CHECK-NEXT: catch ptr null254; CHECK-NEXT: ret i32 0255;256entry:257 %a = alloca %pair, align 4258 br i1 %cond, label %call, label %end259 260call:261 %b = invoke ptr @foo()262 to label %end unwind label %invoke_catch263 264end:265 %phi = phi ptr [ %a, %entry], [ %b, %call ]266 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1267 %load = load i32, ptr %gep, align 4268 ret i32 %load269 270invoke_catch:271 %res = landingpad { ptr, i32 }272 catch ptr null273 ret i32 0274}275 276define i32 @test_sroa_phi_gep_nonconst_idx(i1 %cond, i32 %idx) {277; CHECK-LABEL: @test_sroa_phi_gep_nonconst_idx(278; CHECK-NEXT: entry:279; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4280; CHECK-NEXT: [[B:%.*]] = alloca [[PAIR]], align 4281; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1282; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1283; CHECK-NEXT: store i32 1, ptr [[GEP_A]], align 4284; CHECK-NEXT: store i32 2, ptr [[GEP_B]], align 4285; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]]286; CHECK: if.then:287; CHECK-NEXT: br label [[END]]288; CHECK: end:289; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ]290; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 [[IDX:%.*]], i32 1291; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4292; CHECK-NEXT: ret i32 [[LOAD]]293;294entry:295 %a = alloca %pair, align 4296 %b = alloca %pair, align 4297 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1298 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1299 store i32 1, ptr %gep_a, align 4300 store i32 2, ptr %gep_b, align 4301 br i1 %cond, label %if.then, label %end302 303if.then:304 br label %end305 306end:307 %phi = phi ptr [ %a, %entry], [ %b, %if.then ]308 %gep = getelementptr inbounds %pair, ptr %phi, i32 %idx, i32 1309 %load = load i32, ptr %gep, align 4310 ret i32 %load311}312 313define void @test_sroa_gep_phi_select_other_block(i1 %c1, i1 %c2, ptr %ptr) {314; CHECK-LABEL: @test_sroa_gep_phi_select_other_block(315; CHECK-NEXT: entry:316; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8317; CHECK-NEXT: br label [[WHILE_BODY:%.*]]318; CHECK: while.body:319; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]320; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]]321; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]]322; CHECK: exit:323; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1324; CHECK-NEXT: unreachable325;326entry:327 %alloca = alloca %pair, align 8328 br label %while.body329 330while.body:331 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]332 %select = select i1 %c1, ptr %phi, ptr %ptr333 br i1 %c2, label %exit, label %while.body334 335exit:336 %gep = getelementptr inbounds %pair, ptr %phi, i64 1337 unreachable338}339 340define void @test_sroa_gep_phi_select_same_block(i1 %c1, i1 %c2, ptr %ptr) !prof !0 {341; CHECK-LABEL: @test_sroa_gep_phi_select_same_block(342; CHECK-NEXT: entry:343; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8344; CHECK-NEXT: br label [[WHILE_BODY:%.*]]345; CHECK: while.body:346; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]347; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]], !prof [[PROF1:![0-9]+]]348; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1349; CHECK-NEXT: [[PTR_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PTR]], i64 1350; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]], !prof [[PROF1]]351; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]], !prof [[PROF2:![0-9]+]]352; CHECK: exit:353; CHECK-NEXT: ret void354;355entry:356 %alloca = alloca %pair, align 8357 br label %while.body358 359while.body:360 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]361 %select = select i1 %c1, ptr %phi, ptr %ptr, !prof !1362 %gep = getelementptr inbounds %pair, ptr %select, i64 1363 br i1 %c2, label %exit, label %while.body, !prof !2364 365exit:366 ret void367}368 369define void @test_sroa_gep_phi_select_same_block_nuw(i1 %c1, i1 %c2, ptr %ptr) {370; CHECK-LABEL: @test_sroa_gep_phi_select_same_block_nuw(371; CHECK-NEXT: entry:372; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8373; CHECK-NEXT: br label [[WHILE_BODY:%.*]]374; CHECK: while.body:375; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ]376; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]]377; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PHI]], i64 1378; CHECK-NEXT: [[PTR_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PTR]], i64 1379; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]]380; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]]381; CHECK: exit:382; CHECK-NEXT: ret void383;384entry:385 %alloca = alloca %pair, align 8386 br label %while.body387 388while.body:389 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ]390 %select = select i1 %c1, ptr %phi, ptr %ptr391 %gep = getelementptr nuw %pair, ptr %select, i64 1392 br i1 %c2, label %exit, label %while.body393 394exit:395 ret void396}397 398define i32 @test_sroa_gep_cast_phi_gep(i1 %cond) {399; CHECK-LABEL: @test_sroa_gep_cast_phi_gep(400; CHECK-NEXT: entry:401; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4402; CHECK-NEXT: store i32 1065353216, ptr [[A_SROA_0]], align 4403; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]]404; CHECK: for:405; CHECK-NEXT: [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ]406; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ]407; CHECK-NEXT: [[I]] = add i32 [[PHI_I]], 1408; CHECK-NEXT: [[GEP_FOR]] = getelementptr inbounds float, ptr [[PHI]], i32 0409; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10410; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]]411; CHECK: end:412; CHECK-NEXT: [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ]413; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4414; CHECK-NEXT: ret i32 [[LOAD]]415;416entry:417 %a = alloca %pair, align 4418 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1419 store float 1.0, ptr %gep_a, align 4420 br i1 %cond, label %for, label %end421 422for:423 %phi_i = phi i32 [ 0, %entry ], [ %i, %for ]424 %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ]425 %i = add i32 %phi_i, 1426 %gep_for = getelementptr inbounds float, ptr %phi, i32 0427 %loop.cond = icmp ult i32 %i, 10428 br i1 %loop.cond, label %for, label %end429 430end:431 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ]432 %load = load i32, ptr %phi_end, align 4433 ret i32 %load434}435 436define void @unreachable_term(i1 %c1) {437; CHECK-LABEL: @unreachable_term(438; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4439; CHECK-NEXT: unreachable440; CHECK: bb1:441; CHECK-NEXT: br label [[BB1_I:%.*]]442; CHECK: bb1.i:443; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[BB1:%.*]] ], [ null, [[BB1_I]] ]444; CHECK-NEXT: store i32 0, ptr [[PHI]], align 1445; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1_I]], label [[EXIT:%.*]]446; CHECK: exit:447; CHECK-NEXT: br label [[BB2:%.*]]448; CHECK: bb2:449; CHECK-NEXT: ret void450;451 %a = alloca [3 x i32], align 1452 unreachable453 454bb1:455 br label %bb1.i456 457bb1.i:458 %phi = phi ptr [ %a, %bb1 ], [ null, %bb1.i ]459 store i32 0, ptr %phi, align 1460 br i1 %c1, label %bb1.i, label %exit461 462exit:463 br label %bb2464 465bb2:466 ret void467}468 469define void @constant_value_phi(i1 %c1) {470; CHECK-LABEL: @constant_value_phi(471; CHECK-NEXT: entry:472; CHECK-NEXT: br label [[LAND_LHS_TRUE_I:%.*]]473; CHECK: land.lhs.true.i:474; CHECK-NEXT: br i1 [[C1:%.*]], label [[COND_END_I:%.*]], label [[COND_END_I]]475; CHECK: cond.end.i:476; CHECK-NEXT: unreachable477;478entry:479 %s1 = alloca [3 x i16]480 %s = alloca [3 x i16]481 br label %land.lhs.true.i482 483land.lhs.true.i: ; preds = %entry484 br i1 %c1, label %cond.end.i, label %cond.end.i485 486cond.end.i: ; preds = %land.lhs.true.i, %land.lhs.true.i487 %.pre-phi1 = phi ptr [ %s1, %land.lhs.true.i ], [ %s1, %land.lhs.true.i ]488 call void @llvm.memcpy.p0.p0.i64(ptr %.pre-phi1, ptr %s, i64 3, i1 false)489 %load = load i16, ptr %s490 unreachable491}492 493define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) {494; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block(495; CHECK-NEXT: bb.1:496; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [497; CHECK-NEXT: i32 1, label [[BB_2:%.*]]498; CHECK-NEXT: i32 2, label [[BB_2]]499; CHECK-NEXT: i32 3, label [[BB_4:%.*]]500; CHECK-NEXT: i32 4, label [[BB_4]]501; CHECK-NEXT: ]502; CHECK: bb.2:503; CHECK-NEXT: br label [[BB_4]]504; CHECK: bb.3:505; CHECK-NEXT: br label [[BB_4]]506; CHECK: bb.4:507; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ]508; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]509;510bb.1:511 %a = alloca %pair, align 4512 %b = alloca %pair, align 4513 switch i32 %arg, label %bb.3 [514 i32 1, label %bb.2515 i32 2, label %bb.2516 i32 3, label %bb.4517 i32 4, label %bb.4518 ]519 520bb.2: ; preds = %bb.1, %bb.1521 br label %bb.4522 523bb.3: ; preds = %bb.1524 br label %bb.4525 526bb.4: ; preds = %bb.1, %bb.1, %bb.3, %bb.2527 %phi = phi ptr [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ]528 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1529 %load = load i32, ptr %gep, align 4530 ret i32 %load531}532 533define i64 @test_phi_idx_mem2reg_const(i1 %arg) {534; CHECK-LABEL: @test_phi_idx_mem2reg_const(535; CHECK-NEXT: bb:536; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]537; CHECK: bb1:538; CHECK-NEXT: br label [[END:%.*]]539; CHECK: bb2:540; CHECK-NEXT: br label [[END]]541; CHECK: end:542; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i64 [ 2, [[BB1]] ], [ 3, [[BB2]] ]543; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ]544; CHECK-NEXT: ret i64 [[PHI_SROA_PHI_SROA_SPECULATED]]545;546bb:547 %alloca = alloca [2 x i64], align 8548 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1549 store i64 2, ptr %alloca550 store i64 3, ptr %gep1551 br i1 %arg, label %bb1, label %bb2552 553bb1:554 br label %end555 556bb2:557 br label %end558 559end:560 %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ]561 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi562 %load = load i64, ptr %getelementptr563 ret i64 %load564}565 566define i64 @test_phi_idx_mem2reg_not_const(i1 %arg, i64 %idx) {567; CHECK-LABEL: @test_phi_idx_mem2reg_not_const(568; CHECK-NEXT: bb:569; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i64], align 8570; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1571; CHECK-NEXT: store i64 2, ptr [[ALLOCA]], align 4572; CHECK-NEXT: store i64 3, ptr [[GEP1]], align 4573; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]574; CHECK: bb1:575; CHECK-NEXT: br label [[END:%.*]]576; CHECK: bb2:577; CHECK-NEXT: br label [[END]]578; CHECK: end:579; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ [[IDX:%.*]], [[BB2]] ]580; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[PHI]]581; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4582; CHECK-NEXT: ret i64 [[LOAD]]583;584bb:585 %alloca = alloca [2 x i64], align 8586 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1587 store i64 2, ptr %alloca588 store i64 3, ptr %gep1589 br i1 %arg, label %bb1, label %bb2590 591bb1:592 br label %end593 594bb2:595 br label %end596 597end:598 %phi = phi i64 [ 0, %bb1 ], [ %idx, %bb2 ]599 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi600 %load = load i64, ptr %getelementptr601 ret i64 %load602}603 604define i64 @test_phi_mem2reg_pointer_op_is_non_const_gep(i1 %arg, i64 %idx) {605; CHECK-LABEL: @test_phi_mem2reg_pointer_op_is_non_const_gep(606; CHECK-NEXT: bb:607; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i64], align 8608; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1609; CHECK-NEXT: store i64 2, ptr [[ALLOCA]], align 4610; CHECK-NEXT: store i64 3, ptr [[GEP1]], align 4611; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]612; CHECK: bb1:613; CHECK-NEXT: br label [[END:%.*]]614; CHECK: bb2:615; CHECK-NEXT: br label [[END]]616; CHECK: end:617; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ]618; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[IDX:%.*]]619; CHECK-NEXT: [[GETELEMENTPTR2:%.*]] = getelementptr inbounds i64, ptr [[GETELEMENTPTR]], i64 [[PHI]]620; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4621; CHECK-NEXT: ret i64 [[LOAD]]622;623bb:624 %alloca = alloca [2 x i64], align 8625 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1626 store i64 2, ptr %alloca627 store i64 3, ptr %gep1628 br i1 %arg, label %bb1, label %bb2629 630bb1:631 br label %end632 633bb2:634 br label %end635 636end:637 %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ]638 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %idx639 %getelementptr2 = getelementptr inbounds i64, ptr %getelementptr, i64 %phi640 %load = load i64, ptr %getelementptr641 ret i64 %load642}643 644define i1 @test_phi_mem2reg_entry_block_alloca_not_at_beginning(i1 %arg) {645; CHECK-LABEL: @test_phi_mem2reg_entry_block_alloca_not_at_beginning(646; CHECK-NEXT: bb:647; CHECK-NEXT: call void @f()648; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8649; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 1650; CHECK-NEXT: [[PHI_SROA_GEP1:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 2651; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB2:%.*]], label [[BB3:%.*]]652; CHECK: bb2:653; CHECK-NEXT: br label [[BB3]]654; CHECK: bb3:655; CHECK-NEXT: [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB:%.*]] ], [ [[PHI_SROA_GEP1]], [[BB2]] ]656; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 1, [[BB]] ], [ 2, [[BB2]] ]657; CHECK-NEXT: [[ICMP:%.*]] = icmp eq ptr [[PHI_SROA_PHI]], null658; CHECK-NEXT: ret i1 [[ICMP]]659;660bb:661 call void @f()662 %alloca = alloca i64663 br i1 %arg, label %bb2, label %bb3664bb2:665 br label %bb3666bb3:667 %phi = phi i64 [ 1, %bb ], [ 2, %bb2 ]668 %gep = getelementptr i64, ptr %alloca, i64 %phi669 %icmp = icmp eq ptr %gep, null670 ret i1 %icmp671}672 673define i32 @test_phi_mem2reg_alloca_not_in_entry_block(i1 %arg) {674; CHECK-LABEL: @test_phi_mem2reg_alloca_not_in_entry_block(675; CHECK-NEXT: bb:676; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8677; CHECK-NEXT: store i64 123, ptr [[ALLOCA]], align 4678; CHECK-NEXT: br label [[BB2:%.*]]679; CHECK: bb2:680; CHECK-NEXT: [[ALLOCA2:%.*]] = alloca i64, align 8681; CHECK-NEXT: store i64 124, ptr [[ALLOCA]], align 4682; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB3:%.*]], label [[BB4:%.*]]683; CHECK: bb3:684; CHECK-NEXT: br label [[BB4]]685; CHECK: bb4:686; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[BB2]] ], [ [[ALLOCA2]], [[BB3]] ]687; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1688; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4689; CHECK-NEXT: ret i32 [[LOAD]]690;691bb:692 %alloca = alloca i64693 store i64 123, ptr %alloca694 br label %bb2695bb2:696 %alloca2 = alloca i64697 store i64 124, ptr %alloca698 br i1 %arg, label %bb3, label %bb4699bb3:700 br label %bb4701bb4:702 %phi = phi ptr [ %alloca, %bb2 ], [ %alloca2, %bb3 ]703 %gep = getelementptr i32, ptr %phi, i64 1704 %load = load i32, ptr %gep705 ret i32 %load706}707 708define i64 @test_unfold_phi_duplicate_phi_entry(ptr %arg, i8 %arg1, i1 %arg2) {709; CHECK-LABEL: @test_unfold_phi_duplicate_phi_entry(710; CHECK-NEXT: bb:711; CHECK-NEXT: [[ALLOCA_SROA_0:%.*]] = alloca i64, align 8712; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ARG:%.*]], i64 1713; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB5:%.*]], label [[BB3:%.*]]714; CHECK: bb3:715; CHECK-NEXT: switch i8 [[ARG1:%.*]], label [[BB4:%.*]] [716; CHECK-NEXT: i8 0, label [[BB5]]717; CHECK-NEXT: i8 1, label [[BB5]]718; CHECK-NEXT: ]719; CHECK: bb4:720; CHECK-NEXT: ret i64 0721; CHECK: bb5:722; CHECK-NEXT: [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[ALLOCA_SROA_0]], [[BB:%.*]] ]723; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[PHI_SROA_PHI]], align 4724; CHECK-NEXT: ret i64 [[LOAD]]725;726bb:727 %alloca = alloca [2 x i64], align 8728 br i1 %arg2, label %bb5, label %bb3729 730bb3: ; preds = %bb731 switch i8 %arg1, label %bb4 [732 i8 0, label %bb5733 i8 1, label %bb5734 ]735 736bb4: ; preds = %bb5, %bb3737 ret i64 0738 739bb5: ; preds = %bb3, %bb3, %bb740 %phi = phi ptr [ %arg, %bb3 ], [ %arg, %bb3 ], [ %alloca, %bb ]741 %getelementptr = getelementptr i64, ptr %phi, i64 1742 %load = load i64, ptr %getelementptr743 ret i64 %load744}745 746declare void @f()747 748declare ptr @foo()749 750declare i32 @__gxx_personality_v0(...)751 752declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg)753 754!0 = !{!"function_entry_count", i32 10}755!1 = !{!"branch_weights", i32 3, i32 5}756!2 = !{!"branch_weights", i32 7, i32 11}757 758;.759; CHECK: attributes #[[ATTR0:[0-9]+]] = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }760;.761; CHECK: [[META0:![0-9]+]] = !{!"function_entry_count", i32 10}762; CHECK: [[PROF1]] = !{!"branch_weights", i32 3, i32 5}763; CHECK: [[PROF2]] = !{!"branch_weights", i32 7, i32 11}764;.765;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:766; CHECK-MODIFY-CFG: {{.*}}767; CHECK-PRESERVE-CFG: {{.*}}768