1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes='sroa<preserve-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-PRESERVE-CFG 3; RUN: opt -S -passes='sroa<modify-cfg>' < %s | FileCheck %s --check-prefixes=CHECK,CHECK-MODIFY-CFG 4 5%pair = type { i32, i32 } 6 7define i32 @test_sroa_phi_gep(i1 %cond) { 8; CHECK-LABEL: @test_sroa_phi_gep( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]] 11; CHECK: if.then: 12; CHECK-NEXT: br label [[END]] 13; CHECK: end: 14; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ] 15; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 16; 17entry: 18 %a = alloca %pair, align 4 19 %b = alloca %pair, align 4 20 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 21 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1 22 store i32 1, ptr %gep_a, align 4 23 store i32 2, ptr %gep_b, align 4 24 br i1 %cond, label %if.then, label %end 25 26if.then: 27 br label %end 28 29end: 30 %phi = phi ptr [ %a, %entry], [ %b, %if.then ] 31 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 32 %load = load i32, ptr %gep, align 4 33 ret i32 %load 34} 35 36define i32 @test_sroa_phi_gep_non_inbound(i1 %cond) { 37; CHECK-LABEL: @test_sroa_phi_gep_non_inbound( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]] 40; CHECK: if.then: 41; CHECK-NEXT: br label [[END]] 42; CHECK: end: 43; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 2, [[IF_THEN]] ] 44; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 45; 46entry: 47 %a = alloca %pair, align 4 48 %b = alloca %pair, align 4 49 %gep_a = getelementptr %pair, ptr %a, i32 0, i32 1 50 %gep_b = getelementptr %pair, ptr %b, i32 0, i32 1 51 store i32 1, ptr %gep_a, align 4 52 store i32 2, ptr %gep_b, align 4 53 br i1 %cond, label %if.then, label %end 54 55if.then: 56 br label %end 57 58end: 59 %phi = phi ptr [ %a, %entry], [ %b, %if.then ] 60 %gep = getelementptr %pair, ptr %phi, i32 0, i32 1 61 %load = load i32, ptr %gep, align 4 62 ret i32 %load 63} 64 65define i32 @test_sroa_phi_gep_poison(i1 %cond) { 66; CHECK-LABEL: @test_sroa_phi_gep_poison( 67; CHECK-NEXT: entry: 68; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]] 69; CHECK: if.then: 70; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr poison, align 4 71; CHECK-NEXT: br label [[END]] 72; CHECK: end: 73; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ] 74; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 75; 76entry: 77 %a = alloca %pair, align 4 78 br i1 %cond, label %if.then, label %end 79 80if.then: 81 br label %end 82 83end: 84 %phi = phi ptr [ %a, %entry], [ poison, %if.then ] 85 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 86 %load = load i32, ptr %gep, align 4 87 ret i32 %load 88} 89 90@g = global %pair zeroinitializer, align 4 91 92define i32 @test_sroa_phi_gep_global(i1 %cond) { 93; CHECK-LABEL: @test_sroa_phi_gep_global( 94; CHECK-NEXT: entry: 95; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]] 96; CHECK: if.then: 97; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN:%.*]] = load i32, ptr getelementptr inbounds ([[PAIR:%.*]], ptr @g, i32 0, i32 1), align 4 98; CHECK-NEXT: br label [[END]] 99; CHECK: end: 100; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[PHI_SROA_PHI_SROA_SPECULATE_LOAD_IF_THEN]], [[IF_THEN]] ] 101; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 102; 103entry: 104 %a = alloca %pair, align 4 105 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 106 store i32 1, ptr %gep_a, align 4 107 br i1 %cond, label %if.then, label %end 108 109if.then: 110 br label %end 111 112end: 113 %phi = phi ptr [ %a, %entry], [ @g, %if.then ] 114 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 115 %load = load i32, ptr %gep, align 4 116 ret i32 %load 117} 118 119define i32 @test_sroa_phi_gep_arg_phi_inspt(i1 %cond) { 120; CHECK-LABEL: @test_sroa_phi_gep_arg_phi_inspt( 121; CHECK-NEXT: entry: 122; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]] 123; CHECK: for: 124; CHECK-NEXT: [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ] 125; CHECK-NEXT: [[I]] = add i32 [[PHI_INSPT]], 1 126; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10 127; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]] 128; CHECK: end: 129; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ 1, [[ENTRY]] ], [ 2, [[FOR]] ] 130; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 131; 132entry: 133 %a = alloca %pair, align 4 134 %b = alloca %pair, align 4 135 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 136 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1 137 store i32 1, ptr %gep_a, align 4 138 store i32 2, ptr %gep_b, align 4 139 br i1 %cond, label %for, label %end 140 141for: 142 %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ] 143 %i = add i32 %phi_inspt, 1 144 %loop.cond = icmp ult i32 %i, 10 145 br i1 %loop.cond, label %for, label %end 146 147end: 148 %phi = phi ptr [ %a, %entry], [ %b, %for ] 149 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 150 %load = load i32, ptr %gep, align 4 151 ret i32 %load 152} 153 154define i32 @test_sroa_phi_gep_phi_inspt(i1 %cond) { 155; CHECK-LABEL: @test_sroa_phi_gep_phi_inspt( 156; CHECK-NEXT: entry: 157; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4 158; CHECK-NEXT: [[B:%.*]] = alloca [[PAIR]], align 4 159; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1 160; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1 161; CHECK-NEXT: store i32 1, ptr [[GEP_A]], align 4 162; CHECK-NEXT: store i32 2, ptr [[GEP_B]], align 4 163; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]] 164; CHECK: for: 165; CHECK-NEXT: [[PHI_IN:%.*]] = phi ptr [ null, [[ENTRY:%.*]] ], [ [[B]], [[FOR]] ] 166; CHECK-NEXT: [[PHI_INSPT:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[I:%.*]], [[FOR]] ] 167; CHECK-NEXT: [[I]] = add i32 [[PHI_INSPT]], 1 168; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10 169; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]] 170; CHECK: end: 171; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY]] ], [ [[PHI_IN]], [[FOR]] ] 172; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1 173; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 174; CHECK-NEXT: ret i32 [[LOAD]] 175; 176entry: 177 %a = alloca %pair, align 4 178 %b = alloca %pair, align 4 179 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 180 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1 181 store i32 1, ptr %gep_a, align 4 182 store i32 2, ptr %gep_b, align 4 183 br i1 %cond, label %for, label %end 184 185for: 186 %phi_in = phi ptr [ null, %entry ], [ %b, %for ] 187 %phi_inspt = phi i32 [ 0, %entry ], [ %i, %for ] 188 %i = add i32 %phi_inspt, 1 189 %loop.cond = icmp ult i32 %i, 10 190 br i1 %loop.cond, label %for, label %end 191 192end: 193 %phi = phi ptr [ %a, %entry], [ %phi_in, %for ] 194 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 195 %load = load i32, ptr %gep, align 4 196 ret i32 %load 197} 198 199define i32 @test_sroa_gep_phi_gep(i1 %cond) { 200; CHECK-LABEL: @test_sroa_gep_phi_gep( 201; CHECK-NEXT: entry: 202; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 203; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]] 204; CHECK: for: 205; CHECK-NEXT: [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ] 206; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ] 207; CHECK-NEXT: [[I]] = add i32 [[PHI_I]], 1 208; CHECK-NEXT: [[GEP_FOR]] = getelementptr inbounds i32, ptr [[PHI]], i32 0 209; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10 210; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]] 211; CHECK: end: 212; CHECK-NEXT: [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ] 213; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4 214; CHECK-NEXT: ret i32 [[LOAD]] 215; 216entry: 217 %a = alloca %pair, align 4 218 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 219 br i1 %cond, label %for, label %end 220 221for: 222 %phi_i = phi i32 [ 0, %entry ], [ %i, %for ] 223 %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ] 224 %i = add i32 %phi_i, 1 225 %gep_for = getelementptr inbounds i32, ptr %phi, i32 0 226 %loop.cond = icmp ult i32 %i, 10 227 br i1 %loop.cond, label %for, label %end 228 229end: 230 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ] 231 %load = load i32, ptr %phi_end, align 4 232 ret i32 %load 233} 234 235define i32 @test_sroa_invoke_phi_gep(i1 %cond) personality ptr @__gxx_personality_v0 { 236; CHECK-LABEL: @test_sroa_invoke_phi_gep( 237; CHECK-NEXT: entry: 238; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4 239; CHECK-NEXT: br i1 [[COND:%.*]], label [[CALL:%.*]], label [[END:%.*]] 240; CHECK: call: 241; CHECK-NEXT: [[B:%.*]] = invoke ptr @foo() 242; CHECK-NEXT: to label [[END]] unwind label [[INVOKE_CATCH:%.*]] 243; CHECK: end: 244; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[CALL]] ] 245; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 0, i32 1 246; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 247; CHECK-NEXT: ret i32 [[LOAD]] 248; CHECK: invoke_catch: 249; CHECK-NEXT: [[RES:%.*]] = landingpad { ptr, i32 } 250; CHECK-NEXT: catch ptr null 251; CHECK-NEXT: ret i32 0 252; 253entry: 254 %a = alloca %pair, align 4 255 br i1 %cond, label %call, label %end 256 257call: 258 %b = invoke ptr @foo() 259 to label %end unwind label %invoke_catch 260 261end: 262 %phi = phi ptr [ %a, %entry], [ %b, %call ] 263 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 264 %load = load i32, ptr %gep, align 4 265 ret i32 %load 266 267invoke_catch: 268 %res = landingpad { ptr, i32 } 269 catch ptr null 270 ret i32 0 271} 272 273define i32 @test_sroa_phi_gep_nonconst_idx(i1 %cond, i32 %idx) { 274; CHECK-LABEL: @test_sroa_phi_gep_nonconst_idx( 275; CHECK-NEXT: entry: 276; CHECK-NEXT: [[A:%.*]] = alloca [[PAIR:%.*]], align 4 277; CHECK-NEXT: [[B:%.*]] = alloca [[PAIR]], align 4 278; CHECK-NEXT: [[GEP_A:%.*]] = getelementptr inbounds [[PAIR]], ptr [[A]], i32 0, i32 1 279; CHECK-NEXT: [[GEP_B:%.*]] = getelementptr inbounds [[PAIR]], ptr [[B]], i32 0, i32 1 280; CHECK-NEXT: store i32 1, ptr [[GEP_A]], align 4 281; CHECK-NEXT: store i32 2, ptr [[GEP_B]], align 4 282; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[END:%.*]] 283; CHECK: if.then: 284; CHECK-NEXT: br label [[END]] 285; CHECK: end: 286; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ] 287; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i32 [[IDX:%.*]], i32 1 288; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 289; CHECK-NEXT: ret i32 [[LOAD]] 290; 291entry: 292 %a = alloca %pair, align 4 293 %b = alloca %pair, align 4 294 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 295 %gep_b = getelementptr inbounds %pair, ptr %b, i32 0, i32 1 296 store i32 1, ptr %gep_a, align 4 297 store i32 2, ptr %gep_b, align 4 298 br i1 %cond, label %if.then, label %end 299 300if.then: 301 br label %end 302 303end: 304 %phi = phi ptr [ %a, %entry], [ %b, %if.then ] 305 %gep = getelementptr inbounds %pair, ptr %phi, i32 %idx, i32 1 306 %load = load i32, ptr %gep, align 4 307 ret i32 %load 308} 309 310define void @test_sroa_gep_phi_select_other_block(i1 %c1, i1 %c2, ptr %ptr) { 311; CHECK-LABEL: @test_sroa_gep_phi_select_other_block( 312; CHECK-NEXT: entry: 313; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8 314; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 315; CHECK: while.body: 316; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ] 317; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]] 318; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]] 319; CHECK: exit: 320; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1 321; CHECK-NEXT: unreachable 322; 323entry: 324 %alloca = alloca %pair, align 8 325 br label %while.body 326 327while.body: 328 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ] 329 %select = select i1 %c1, ptr %phi, ptr %ptr 330 br i1 %c2, label %exit, label %while.body 331 332exit: 333 %gep = getelementptr inbounds %pair, ptr %phi, i64 1 334 unreachable 335} 336 337define void @test_sroa_gep_phi_select_same_block(i1 %c1, i1 %c2, ptr %ptr) { 338; CHECK-LABEL: @test_sroa_gep_phi_select_same_block( 339; CHECK-NEXT: entry: 340; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8 341; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 342; CHECK: while.body: 343; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ] 344; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]] 345; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PHI]], i64 1 346; CHECK-NEXT: [[PTR_SROA_GEP:%.*]] = getelementptr inbounds [[PAIR]], ptr [[PTR]], i64 1 347; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]] 348; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]] 349; CHECK: exit: 350; CHECK-NEXT: ret void 351; 352entry: 353 %alloca = alloca %pair, align 8 354 br label %while.body 355 356while.body: 357 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ] 358 %select = select i1 %c1, ptr %phi, ptr %ptr 359 %gep = getelementptr inbounds %pair, ptr %select, i64 1 360 br i1 %c2, label %exit, label %while.body 361 362exit: 363 ret void 364} 365 366define void @test_sroa_gep_phi_select_same_block_nuw(i1 %c1, i1 %c2, ptr %ptr) { 367; CHECK-LABEL: @test_sroa_gep_phi_select_same_block_nuw( 368; CHECK-NEXT: entry: 369; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [[PAIR:%.*]], align 8 370; CHECK-NEXT: br label [[WHILE_BODY:%.*]] 371; CHECK: while.body: 372; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[ENTRY:%.*]] ], [ [[SELECT:%.*]], [[WHILE_BODY]] ] 373; CHECK-NEXT: [[SELECT]] = select i1 [[C1:%.*]], ptr [[PHI]], ptr [[PTR:%.*]] 374; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PHI]], i64 1 375; CHECK-NEXT: [[PTR_SROA_GEP:%.*]] = getelementptr nuw [[PAIR]], ptr [[PTR]], i64 1 376; CHECK-NEXT: [[SELECT_SROA_SEL:%.*]] = select i1 [[C1]], ptr [[PHI_SROA_GEP]], ptr [[PTR_SROA_GEP]] 377; CHECK-NEXT: br i1 [[C2:%.*]], label [[EXIT:%.*]], label [[WHILE_BODY]] 378; CHECK: exit: 379; CHECK-NEXT: ret void 380; 381entry: 382 %alloca = alloca %pair, align 8 383 br label %while.body 384 385while.body: 386 %phi = phi ptr [ %alloca, %entry ], [ %select, %while.body ] 387 %select = select i1 %c1, ptr %phi, ptr %ptr 388 %gep = getelementptr nuw %pair, ptr %select, i64 1 389 br i1 %c2, label %exit, label %while.body 390 391exit: 392 ret void 393} 394 395define i32 @test_sroa_gep_cast_phi_gep(i1 %cond) { 396; CHECK-LABEL: @test_sroa_gep_cast_phi_gep( 397; CHECK-NEXT: entry: 398; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 399; CHECK-NEXT: store i32 1065353216, ptr [[A_SROA_0]], align 4 400; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR:%.*]], label [[END:%.*]] 401; CHECK: for: 402; CHECK-NEXT: [[PHI_I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I:%.*]], [[FOR]] ] 403; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[GEP_FOR:%.*]], [[FOR]] ] 404; CHECK-NEXT: [[I]] = add i32 [[PHI_I]], 1 405; CHECK-NEXT: [[GEP_FOR]] = getelementptr inbounds float, ptr [[PHI]], i32 0 406; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp ult i32 [[I]], 10 407; CHECK-NEXT: br i1 [[LOOP_COND]], label [[FOR]], label [[END]] 408; CHECK: end: 409; CHECK-NEXT: [[PHI_END:%.*]] = phi ptr [ [[A_SROA_0]], [[ENTRY]] ], [ [[PHI]], [[FOR]] ] 410; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[PHI_END]], align 4 411; CHECK-NEXT: ret i32 [[LOAD]] 412; 413entry: 414 %a = alloca %pair, align 4 415 %gep_a = getelementptr inbounds %pair, ptr %a, i32 0, i32 1 416 store float 1.0, ptr %gep_a, align 4 417 br i1 %cond, label %for, label %end 418 419for: 420 %phi_i = phi i32 [ 0, %entry ], [ %i, %for ] 421 %phi = phi ptr [ %gep_a, %entry], [ %gep_for, %for ] 422 %i = add i32 %phi_i, 1 423 %gep_for = getelementptr inbounds float, ptr %phi, i32 0 424 %loop.cond = icmp ult i32 %i, 10 425 br i1 %loop.cond, label %for, label %end 426 427end: 428 %phi_end = phi ptr [ %gep_a, %entry], [ %phi, %for ] 429 %load = load i32, ptr %phi_end, align 4 430 ret i32 %load 431} 432 433define void @unreachable_term(i1 %c1) { 434; CHECK-LABEL: @unreachable_term( 435; CHECK-NEXT: [[A_SROA_0:%.*]] = alloca i32, align 4 436; CHECK-NEXT: unreachable 437; CHECK: bb1: 438; CHECK-NEXT: br label [[BB1_I:%.*]] 439; CHECK: bb1.i: 440; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[A_SROA_0]], [[BB1:%.*]] ], [ null, [[BB1_I]] ] 441; CHECK-NEXT: store i32 0, ptr [[PHI]], align 1 442; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB1_I]], label [[EXIT:%.*]] 443; CHECK: exit: 444; CHECK-NEXT: br label [[BB2:%.*]] 445; CHECK: bb2: 446; CHECK-NEXT: ret void 447; 448 %a = alloca [3 x i32], align 1 449 unreachable 450 451bb1: 452 br label %bb1.i 453 454bb1.i: 455 %phi = phi ptr [ %a, %bb1 ], [ null, %bb1.i ] 456 store i32 0, ptr %phi, align 1 457 br i1 %c1, label %bb1.i, label %exit 458 459exit: 460 br label %bb2 461 462bb2: 463 ret void 464} 465 466define void @constant_value_phi(i1 %c1) { 467; CHECK-LABEL: @constant_value_phi( 468; CHECK-NEXT: entry: 469; CHECK-NEXT: br label [[LAND_LHS_TRUE_I:%.*]] 470; CHECK: land.lhs.true.i: 471; CHECK-NEXT: br i1 [[C1:%.*]], label [[COND_END_I:%.*]], label [[COND_END_I]] 472; CHECK: cond.end.i: 473; CHECK-NEXT: unreachable 474; 475entry: 476 %s1 = alloca [3 x i16] 477 %s = alloca [3 x i16] 478 br label %land.lhs.true.i 479 480land.lhs.true.i: ; preds = %entry 481 br i1 %c1, label %cond.end.i, label %cond.end.i 482 483cond.end.i: ; preds = %land.lhs.true.i, %land.lhs.true.i 484 %.pre-phi1 = phi ptr [ %s1, %land.lhs.true.i ], [ %s1, %land.lhs.true.i ] 485 call void @llvm.memcpy.p0.p0.i64(ptr %.pre-phi1, ptr %s, i64 3, i1 false) 486 %load = load i16, ptr %s 487 unreachable 488} 489 490define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) { 491; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block( 492; CHECK-NEXT: bb.1: 493; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [ 494; CHECK-NEXT: i32 1, label [[BB_2:%.*]] 495; CHECK-NEXT: i32 2, label [[BB_2]] 496; CHECK-NEXT: i32 3, label [[BB_4:%.*]] 497; CHECK-NEXT: i32 4, label [[BB_4]] 498; CHECK-NEXT: ] 499; CHECK: bb.2: 500; CHECK-NEXT: br label [[BB_4]] 501; CHECK: bb.3: 502; CHECK-NEXT: br label [[BB_4]] 503; CHECK: bb.4: 504; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ] 505; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]] 506; 507bb.1: 508 %a = alloca %pair, align 4 509 %b = alloca %pair, align 4 510 switch i32 %arg, label %bb.3 [ 511 i32 1, label %bb.2 512 i32 2, label %bb.2 513 i32 3, label %bb.4 514 i32 4, label %bb.4 515 ] 516 517bb.2: ; preds = %bb.1, %bb.1 518 br label %bb.4 519 520bb.3: ; preds = %bb.1 521 br label %bb.4 522 523bb.4: ; preds = %bb.1, %bb.1, %bb.3, %bb.2 524 %phi = phi ptr [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ] 525 %gep = getelementptr inbounds %pair, ptr %phi, i32 0, i32 1 526 %load = load i32, ptr %gep, align 4 527 ret i32 %load 528} 529 530define i64 @test_phi_idx_mem2reg_const(i1 %arg) { 531; CHECK-LABEL: @test_phi_idx_mem2reg_const( 532; CHECK-NEXT: bb: 533; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 534; CHECK: bb1: 535; CHECK-NEXT: br label [[END:%.*]] 536; CHECK: bb2: 537; CHECK-NEXT: br label [[END]] 538; CHECK: end: 539; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i64 [ 2, [[BB1]] ], [ 3, [[BB2]] ] 540; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ] 541; CHECK-NEXT: ret i64 [[PHI_SROA_PHI_SROA_SPECULATED]] 542; 543bb: 544 %alloca = alloca [2 x i64], align 8 545 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1 546 store i64 2, ptr %alloca 547 store i64 3, ptr %gep1 548 br i1 %arg, label %bb1, label %bb2 549 550bb1: 551 br label %end 552 553bb2: 554 br label %end 555 556end: 557 %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ] 558 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi 559 %load = load i64, ptr %getelementptr 560 ret i64 %load 561} 562 563define i64 @test_phi_idx_mem2reg_not_const(i1 %arg, i64 %idx) { 564; CHECK-LABEL: @test_phi_idx_mem2reg_not_const( 565; CHECK-NEXT: bb: 566; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i64], align 8 567; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1 568; CHECK-NEXT: store i64 2, ptr [[ALLOCA]], align 4 569; CHECK-NEXT: store i64 3, ptr [[GEP1]], align 4 570; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 571; CHECK: bb1: 572; CHECK-NEXT: br label [[END:%.*]] 573; CHECK: bb2: 574; CHECK-NEXT: br label [[END]] 575; CHECK: end: 576; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ [[IDX:%.*]], [[BB2]] ] 577; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[PHI]] 578; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4 579; CHECK-NEXT: ret i64 [[LOAD]] 580; 581bb: 582 %alloca = alloca [2 x i64], align 8 583 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1 584 store i64 2, ptr %alloca 585 store i64 3, ptr %gep1 586 br i1 %arg, label %bb1, label %bb2 587 588bb1: 589 br label %end 590 591bb2: 592 br label %end 593 594end: 595 %phi = phi i64 [ 0, %bb1 ], [ %idx, %bb2 ] 596 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %phi 597 %load = load i64, ptr %getelementptr 598 ret i64 %load 599} 600 601define i64 @test_phi_mem2reg_pointer_op_is_non_const_gep(i1 %arg, i64 %idx) { 602; CHECK-LABEL: @test_phi_mem2reg_pointer_op_is_non_const_gep( 603; CHECK-NEXT: bb: 604; CHECK-NEXT: [[ALLOCA:%.*]] = alloca [2 x i64], align 8 605; CHECK-NEXT: [[GEP1:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 1 606; CHECK-NEXT: store i64 2, ptr [[ALLOCA]], align 4 607; CHECK-NEXT: store i64 3, ptr [[GEP1]], align 4 608; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 609; CHECK: bb1: 610; CHECK-NEXT: br label [[END:%.*]] 611; CHECK: bb2: 612; CHECK-NEXT: br label [[END]] 613; CHECK: end: 614; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 0, [[BB1]] ], [ 1, [[BB2]] ] 615; CHECK-NEXT: [[GETELEMENTPTR:%.*]] = getelementptr inbounds i64, ptr [[ALLOCA]], i64 [[IDX:%.*]] 616; CHECK-NEXT: [[GETELEMENTPTR2:%.*]] = getelementptr inbounds i64, ptr [[GETELEMENTPTR]], i64 [[PHI]] 617; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[GETELEMENTPTR]], align 4 618; CHECK-NEXT: ret i64 [[LOAD]] 619; 620bb: 621 %alloca = alloca [2 x i64], align 8 622 %gep1 = getelementptr inbounds i64, ptr %alloca, i64 1 623 store i64 2, ptr %alloca 624 store i64 3, ptr %gep1 625 br i1 %arg, label %bb1, label %bb2 626 627bb1: 628 br label %end 629 630bb2: 631 br label %end 632 633end: 634 %phi = phi i64 [ 0, %bb1 ], [ 1, %bb2 ] 635 %getelementptr = getelementptr inbounds i64, ptr %alloca, i64 %idx 636 %getelementptr2 = getelementptr inbounds i64, ptr %getelementptr, i64 %phi 637 %load = load i64, ptr %getelementptr 638 ret i64 %load 639} 640 641define i1 @test_phi_mem2reg_entry_block_alloca_not_at_beginning(i1 %arg) { 642; CHECK-LABEL: @test_phi_mem2reg_entry_block_alloca_not_at_beginning( 643; CHECK-NEXT: bb: 644; CHECK-NEXT: call void @f() 645; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8 646; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 1 647; CHECK-NEXT: [[PHI_SROA_GEP1:%.*]] = getelementptr i64, ptr [[ALLOCA]], i64 2 648; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB2:%.*]], label [[BB3:%.*]] 649; CHECK: bb2: 650; CHECK-NEXT: br label [[BB3]] 651; CHECK: bb3: 652; CHECK-NEXT: [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB:%.*]] ], [ [[PHI_SROA_GEP1]], [[BB2]] ] 653; CHECK-NEXT: [[PHI:%.*]] = phi i64 [ 1, [[BB]] ], [ 2, [[BB2]] ] 654; CHECK-NEXT: [[ICMP:%.*]] = icmp eq ptr [[PHI_SROA_PHI]], null 655; CHECK-NEXT: ret i1 [[ICMP]] 656; 657bb: 658 call void @f() 659 %alloca = alloca i64 660 br i1 %arg, label %bb2, label %bb3 661bb2: 662 br label %bb3 663bb3: 664 %phi = phi i64 [ 1, %bb ], [ 2, %bb2 ] 665 %gep = getelementptr i64, ptr %alloca, i64 %phi 666 %icmp = icmp eq ptr %gep, null 667 ret i1 %icmp 668} 669 670define i32 @test_phi_mem2reg_alloca_not_in_entry_block(i1 %arg) { 671; CHECK-LABEL: @test_phi_mem2reg_alloca_not_in_entry_block( 672; CHECK-NEXT: bb: 673; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i64, align 8 674; CHECK-NEXT: store i64 123, ptr [[ALLOCA]], align 4 675; CHECK-NEXT: br label [[BB2:%.*]] 676; CHECK: bb2: 677; CHECK-NEXT: [[ALLOCA2:%.*]] = alloca i64, align 8 678; CHECK-NEXT: store i64 124, ptr [[ALLOCA]], align 4 679; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB3:%.*]], label [[BB4:%.*]] 680; CHECK: bb3: 681; CHECK-NEXT: br label [[BB4]] 682; CHECK: bb4: 683; CHECK-NEXT: [[PHI:%.*]] = phi ptr [ [[ALLOCA]], [[BB2]] ], [ [[ALLOCA2]], [[BB3]] ] 684; CHECK-NEXT: [[GEP:%.*]] = getelementptr i32, ptr [[PHI]], i64 1 685; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[GEP]], align 4 686; CHECK-NEXT: ret i32 [[LOAD]] 687; 688bb: 689 %alloca = alloca i64 690 store i64 123, ptr %alloca 691 br label %bb2 692bb2: 693 %alloca2 = alloca i64 694 store i64 124, ptr %alloca 695 br i1 %arg, label %bb3, label %bb4 696bb3: 697 br label %bb4 698bb4: 699 %phi = phi ptr [ %alloca, %bb2 ], [ %alloca2, %bb3 ] 700 %gep = getelementptr i32, ptr %phi, i64 1 701 %load = load i32, ptr %gep 702 ret i32 %load 703} 704 705define i64 @test_unfold_phi_duplicate_phi_entry(ptr %arg, i8 %arg1, i1 %arg2) { 706; CHECK-LABEL: @test_unfold_phi_duplicate_phi_entry( 707; CHECK-NEXT: bb: 708; CHECK-NEXT: [[ALLOCA_SROA_0:%.*]] = alloca i64, align 8 709; CHECK-NEXT: [[PHI_SROA_GEP:%.*]] = getelementptr i64, ptr [[ARG:%.*]], i64 1 710; CHECK-NEXT: br i1 [[ARG2:%.*]], label [[BB5:%.*]], label [[BB3:%.*]] 711; CHECK: bb3: 712; CHECK-NEXT: switch i8 [[ARG1:%.*]], label [[BB4:%.*]] [ 713; CHECK-NEXT: i8 0, label [[BB5]] 714; CHECK-NEXT: i8 1, label [[BB5]] 715; CHECK-NEXT: ] 716; CHECK: bb4: 717; CHECK-NEXT: ret i64 0 718; CHECK: bb5: 719; CHECK-NEXT: [[PHI_SROA_PHI:%.*]] = phi ptr [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[PHI_SROA_GEP]], [[BB3]] ], [ [[ALLOCA_SROA_0]], [[BB:%.*]] ] 720; CHECK-NEXT: [[LOAD:%.*]] = load i64, ptr [[PHI_SROA_PHI]], align 4 721; CHECK-NEXT: ret i64 [[LOAD]] 722; 723bb: 724 %alloca = alloca [2 x i64], align 8 725 br i1 %arg2, label %bb5, label %bb3 726 727bb3: ; preds = %bb 728 switch i8 %arg1, label %bb4 [ 729 i8 0, label %bb5 730 i8 1, label %bb5 731 ] 732 733bb4: ; preds = %bb5, %bb3 734 ret i64 0 735 736bb5: ; preds = %bb3, %bb3, %bb 737 %phi = phi ptr [ %arg, %bb3 ], [ %arg, %bb3 ], [ %alloca, %bb ] 738 %getelementptr = getelementptr i64, ptr %phi, i64 1 739 %load = load i64, ptr %getelementptr 740 ret i64 %load 741} 742 743declare void @f() 744 745declare ptr @foo() 746 747declare i32 @__gxx_personality_v0(...) 748 749declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) 750;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line: 751; CHECK-MODIFY-CFG: {{.*}} 752; CHECK-PRESERVE-CFG: {{.*}} 753