1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4declare void @foo() 5declare void @bar() 6declare void @baz() 7declare void @qux() 8declare void @quux() 9 10declare i1 @geni1() 11 12declare void @usei32(i32) 13declare void @usei32i32agg({ i32, i32 }) 14 15; Most basic test - diamond structure 16define { i32, i32 } @test0({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 17; CHECK-LABEL: @test0( 18; CHECK-NEXT: entry: 19; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 20; CHECK: left: 21; CHECK-NEXT: call void @foo() 22; CHECK-NEXT: br label [[END:%.*]] 23; CHECK: right: 24; CHECK-NEXT: call void @bar() 25; CHECK-NEXT: br label [[END]] 26; CHECK: end: 27; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 28; CHECK-NEXT: call void @baz() 29; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]] 30; 31entry: 32 br i1 %c, label %left, label %right 33 34left: 35 %i0 = extractvalue { i32, i32 } %agg_left, 0 36 %i2 = extractvalue { i32, i32 } %agg_left, 1 37 call void @foo() 38 br label %end 39 40right: 41 %i3 = extractvalue { i32, i32 } %agg_right, 0 42 %i4 = extractvalue { i32, i32 } %agg_right, 1 43 call void @bar() 44 br label %end 45 46end: 47 %i5 = phi i32 [ %i0, %left ], [ %i3, %right ] 48 %i6 = phi i32 [ %i2, %left ], [ %i4, %right ] 49 call void @baz() 50 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 51 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 52 ret { i32, i32 } %i8 53} 54 55; Second element is coming from wrong aggregate 56define { i32, i32 } @negative_test1({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 57; CHECK-LABEL: @negative_test1( 58; CHECK-NEXT: entry: 59; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 60; CHECK: left: 61; CHECK-NEXT: call void @foo() 62; CHECK-NEXT: br label [[END:%.*]] 63; CHECK: right: 64; CHECK-NEXT: call void @bar() 65; CHECK-NEXT: br label [[END]] 66; CHECK: end: 67; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 68; CHECK-NEXT: [[AGG_RIGHT_PN:%.*]] = phi { i32, i32 } [ [[AGG_RIGHT]], [[LEFT]] ], [ [[AGG_LEFT]], [[RIGHT]] ] 69; CHECK-NEXT: [[I6:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT_PN]], 1 70; CHECK-NEXT: [[I5:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT_PN]], 0 71; CHECK-NEXT: call void @baz() 72; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0 73; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1 74; CHECK-NEXT: ret { i32, i32 } [[I8]] 75; 76entry: 77 %i0 = extractvalue { i32, i32 } %agg_left, 0 78 %i2 = extractvalue { i32, i32 } %agg_left, 1 79 %i3 = extractvalue { i32, i32 } %agg_right, 0 80 %i4 = extractvalue { i32, i32 } %agg_right, 1 81 br i1 %c, label %left, label %right 82 83left: 84 call void @foo() 85 br label %end 86 87right: 88 call void @bar() 89 br label %end 90 91end: 92 %i5 = phi i32 [ %i0, %left ], [ %i3, %right ] 93 %i6 = phi i32 [ %i4, %left ], [ %i2, %right ] 94 call void @baz() 95 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 96 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 97 ret { i32, i32 } %i8 98} 99 100; When coming from %left, elements are swapped 101define { i32, i32 } @negative_test2({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 102; CHECK-LABEL: @negative_test2( 103; CHECK-NEXT: entry: 104; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 105; CHECK: left: 106; CHECK-NEXT: [[I2:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 1 107; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT]], 0 108; CHECK-NEXT: call void @foo() 109; CHECK-NEXT: br label [[END:%.*]] 110; CHECK: right: 111; CHECK-NEXT: [[I4:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 1 112; CHECK-NEXT: [[I3:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT]], 0 113; CHECK-NEXT: call void @bar() 114; CHECK-NEXT: br label [[END]] 115; CHECK: end: 116; CHECK-NEXT: [[I5:%.*]] = phi i32 [ [[I2]], [[LEFT]] ], [ [[I3]], [[RIGHT]] ] 117; CHECK-NEXT: [[I6:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I4]], [[RIGHT]] ] 118; CHECK-NEXT: call void @baz() 119; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0 120; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1 121; CHECK-NEXT: ret { i32, i32 } [[I8]] 122; 123entry: 124 %i0 = extractvalue { i32, i32 } %agg_left, 0 125 %i2 = extractvalue { i32, i32 } %agg_left, 1 126 %i3 = extractvalue { i32, i32 } %agg_right, 0 127 %i4 = extractvalue { i32, i32 } %agg_right, 1 128 br i1 %c, label %left, label %right 129 130left: 131 call void @foo() 132 br label %end 133 134right: 135 call void @bar() 136 br label %end 137 138end: 139 %i5 = phi i32 [ %i2, %left ], [ %i3, %right ] 140 %i6 = phi i32 [ %i0, %left ], [ %i4, %right ] 141 call void @baz() 142 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 143 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 144 ret { i32, i32 } %i8 145} 146 147; FIXME: we should probably be able to handle multiple levels of PHI indirection 148define { i32, i32 } @test3({ i32, i32 } %agg_00, { i32, i32 } %agg_01, { i32, i32 } %agg_10, i1 %c0, i1 %c1) { 149; CHECK-LABEL: @test3( 150; CHECK-NEXT: entry: 151; CHECK-NEXT: br i1 [[C0:%.*]], label [[BB0_DISPATCH:%.*]], label [[BB10:%.*]] 152; CHECK: bb0.dispatch: 153; CHECK-NEXT: br i1 [[C1:%.*]], label [[BB00:%.*]], label [[BB01:%.*]] 154; CHECK: bb00: 155; CHECK-NEXT: br label [[BB0_MERGE:%.*]] 156; CHECK: bb01: 157; CHECK-NEXT: br label [[BB0_MERGE]] 158; CHECK: bb0.merge: 159; CHECK-NEXT: [[AGG_00_PN:%.*]] = phi { i32, i32 } [ [[AGG_00:%.*]], [[BB00]] ], [ [[AGG_01:%.*]], [[BB01]] ] 160; CHECK-NEXT: br label [[END:%.*]] 161; CHECK: bb10: 162; CHECK-NEXT: br label [[END]] 163; CHECK: end: 164; CHECK-NEXT: [[AGG_00_PN_PN:%.*]] = phi { i32, i32 } [ [[AGG_00_PN]], [[BB0_MERGE]] ], [ [[AGG_10:%.*]], [[BB10]] ] 165; CHECK-NEXT: call void @baz() 166; CHECK-NEXT: ret { i32, i32 } [[AGG_00_PN_PN]] 167; 168entry: 169 br i1 %c0, label %bb0.dispatch, label %bb10 170 171bb0.dispatch: 172 br i1 %c1, label %bb00, label %bb01 173 174bb00: 175 %i0 = extractvalue { i32, i32 } %agg_00, 0 176 %i1 = extractvalue { i32, i32 } %agg_00, 1 177 br label %bb0.merge 178 179bb01: 180 %i2 = extractvalue { i32, i32 } %agg_01, 0 181 %i3 = extractvalue { i32, i32 } %agg_01, 1 182 br label %bb0.merge 183 184bb0.merge: 185 %i4 = phi i32 [ %i0, %bb00 ], [ %i2, %bb01 ] 186 %i5 = phi i32 [ %i1, %bb00 ], [ %i3, %bb01 ] 187 br label %end 188 189bb10: 190 %i6 = extractvalue { i32, i32 } %agg_10, 0 191 %i7 = extractvalue { i32, i32 } %agg_10, 1 192 br label %end 193 194end: 195 %i8 = phi i32 [ %i4, %bb0.merge ], [ %i6, %bb10 ] 196 %i9 = phi i32 [ %i5, %bb0.merge ], [ %i7, %bb10 ] 197 call void @baz() 198 %i10 = insertvalue { i32, i32 } undef, i32 %i8, 0 199 %i11 = insertvalue { i32, i32 } %i10, i32 %i9, 1 200 ret { i32, i32 } %i11 201} 202 203; Not sure what should happen for cycles. 204define { i32, i32 } @test4({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0) { 205; CHECK-LABEL: @test4( 206; CHECK-NEXT: entry: 207; CHECK-NEXT: br i1 [[C0:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 208; CHECK: left: 209; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 210; CHECK-NEXT: [[I2:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT]], 1 211; CHECK-NEXT: call void @foo() 212; CHECK-NEXT: br label [[MIDDLE:%.*]] 213; CHECK: right: 214; CHECK-NEXT: [[I3:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 0 215; CHECK-NEXT: [[I4:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT]], 1 216; CHECK-NEXT: call void @bar() 217; CHECK-NEXT: br label [[MIDDLE]] 218; CHECK: middle: 219; CHECK-NEXT: [[I5:%.*]] = phi i32 [ [[I0]], [[LEFT]] ], [ [[I3]], [[RIGHT]] ], [ [[I5]], [[MIDDLE]] ] 220; CHECK-NEXT: [[I6:%.*]] = phi i32 [ [[I2]], [[LEFT]] ], [ [[I4]], [[RIGHT]] ], [ [[I6]], [[MIDDLE]] ] 221; CHECK-NEXT: call void @baz() 222; CHECK-NEXT: [[C1:%.*]] = call i1 @geni1() 223; CHECK-NEXT: br i1 [[C1]], label [[END:%.*]], label [[MIDDLE]] 224; CHECK: end: 225; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I5]], 0 226; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I6]], 1 227; CHECK-NEXT: ret { i32, i32 } [[I8]] 228; 229entry: 230 br i1 %c0, label %left, label %right 231 232left: 233 %i0 = extractvalue { i32, i32 } %agg_left, 0 234 %i2 = extractvalue { i32, i32 } %agg_left, 1 235 call void @foo() 236 br label %middle 237 238right: 239 %i3 = extractvalue { i32, i32 } %agg_right, 0 240 %i4 = extractvalue { i32, i32 } %agg_right, 1 241 call void @bar() 242 br label %middle 243 244middle: 245 %i5 = phi i32 [ %i0, %left ], [ %i3, %right ], [ %i5, %middle ] 246 %i6 = phi i32 [ %i2, %left ], [ %i4, %right ], [ %i6, %middle ] 247 call void @baz() 248 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 249 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 250 %c1 = call i1 @geni1() 251 br i1 %c1, label %end, label %middle 252 253end: 254 ret { i32, i32 } %i8 255} 256 257; But here since we start without an explicit self-cycle, we already manage to fold it. 258define { i32, i32 } @test5({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0) { 259; CHECK-LABEL: @test5( 260; CHECK-NEXT: entry: 261; CHECK-NEXT: br i1 [[C0:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 262; CHECK: left: 263; CHECK-NEXT: call void @foo() 264; CHECK-NEXT: br label [[MIDDLE:%.*]] 265; CHECK: right: 266; CHECK-NEXT: call void @bar() 267; CHECK-NEXT: br label [[MIDDLE]] 268; CHECK: middle: 269; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ], [ [[AGG_LEFT_PN]], [[MIDDLE]] ] 270; CHECK-NEXT: call void @baz() 271; CHECK-NEXT: [[C1:%.*]] = call i1 @geni1() 272; CHECK-NEXT: br i1 [[C1]], label [[END:%.*]], label [[MIDDLE]] 273; CHECK: end: 274; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]] 275; 276entry: 277 br i1 %c0, label %left, label %right 278 279left: 280 %i0 = extractvalue { i32, i32 } %agg_left, 0 281 %i2 = extractvalue { i32, i32 } %agg_left, 1 282 call void @foo() 283 br label %middle 284 285right: 286 %i3 = extractvalue { i32, i32 } %agg_right, 0 287 %i4 = extractvalue { i32, i32 } %agg_right, 1 288 call void @bar() 289 br label %middle 290 291middle: 292 %i5 = phi i32 [ %i0, %left ], [ %i3, %right ], [ %i9, %middle ] 293 %i6 = phi i32 [ %i2, %left ], [ %i4, %right ], [ %i10, %middle ] 294 call void @baz() 295 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 296 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 297 %i9 = extractvalue { i32, i32 } %i8, 0 298 %i10 = extractvalue { i32, i32 } %i8, 1 299 %c1 = call i1 @geni1() 300 br i1 %c1, label %end, label %middle 301 302end: 303 ret { i32, i32 } %i8 304} 305 306; Diamond structure, but with "padding" block before the use. 307define { i32, i32 } @test6({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) { 308; CHECK-LABEL: @test6( 309; CHECK-NEXT: entry: 310; CHECK-NEXT: br i1 [[C0:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 311; CHECK: left: 312; CHECK-NEXT: call void @foo() 313; CHECK-NEXT: br label [[MERGE:%.*]] 314; CHECK: right: 315; CHECK-NEXT: call void @bar() 316; CHECK-NEXT: br label [[MERGE]] 317; CHECK: merge: 318; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 319; CHECK-NEXT: call void @baz() 320; CHECK-NEXT: br i1 [[C1:%.*]], label [[END:%.*]], label [[PASSTHROUGH:%.*]] 321; CHECK: passthrough: 322; CHECK-NEXT: call void @qux() 323; CHECK-NEXT: br label [[END]] 324; CHECK: end: 325; CHECK-NEXT: call void @quux() 326; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]] 327; 328entry: 329 br i1 %c0, label %left, label %right 330 331left: 332 %i0 = extractvalue { i32, i32 } %agg_left, 0 333 %i2 = extractvalue { i32, i32 } %agg_left, 1 334 call void @foo() 335 br label %merge 336 337right: 338 %i3 = extractvalue { i32, i32 } %agg_right, 0 339 %i4 = extractvalue { i32, i32 } %agg_right, 1 340 call void @bar() 341 br label %merge 342 343merge: 344 %i5 = phi i32 [ %i0, %left ], [ %i3, %right ] 345 %i6 = phi i32 [ %i2, %left ], [ %i4, %right ] 346 call void @baz() 347 br i1 %c1, label %end, label %passthrough 348 349passthrough: 350 call void @qux() 351 br label %end 352 353end: 354 call void @quux() 355 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 356 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 357 ret { i32, i32 } %i8 358} 359 360; All the definitions of the aggregate elements must happen in the same block. 361define { i32, i32 } @negative_test7({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c0, i1 %c1) { 362; CHECK-LABEL: @negative_test7( 363; CHECK-NEXT: entry: 364; CHECK-NEXT: [[I0:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT:%.*]], 0 365; CHECK-NEXT: call void @usei32(i32 [[I0]]) 366; CHECK-NEXT: br i1 [[C0:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 367; CHECK: left: 368; CHECK-NEXT: [[I1:%.*]] = extractvalue { i32, i32 } [[AGG_LEFT]], 1 369; CHECK-NEXT: call void @usei32(i32 [[I1]]) 370; CHECK-NEXT: br label [[MERGE:%.*]] 371; CHECK: right: 372; CHECK-NEXT: [[I2:%.*]] = extractvalue { i32, i32 } [[AGG_RIGHT:%.*]], 1 373; CHECK-NEXT: call void @usei32(i32 [[I2]]) 374; CHECK-NEXT: br label [[MERGE]] 375; CHECK: merge: 376; CHECK-NEXT: [[I3:%.*]] = phi i32 [ [[I1]], [[LEFT]] ], [ [[I2]], [[RIGHT]] ] 377; CHECK-NEXT: call void @bar() 378; CHECK-NEXT: br label [[END:%.*]] 379; CHECK: end: 380; CHECK-NEXT: call void @baz() 381; CHECK-NEXT: [[I7:%.*]] = insertvalue { i32, i32 } undef, i32 [[I0]], 0 382; CHECK-NEXT: [[I8:%.*]] = insertvalue { i32, i32 } [[I7]], i32 [[I3]], 1 383; CHECK-NEXT: ret { i32, i32 } [[I8]] 384; 385entry: 386 %i0 = extractvalue { i32, i32 } %agg_left, 0 387 call void @usei32(i32 %i0) 388 br i1 %c0, label %left, label %right 389 390left: 391 %i1 = extractvalue { i32, i32 } %agg_left, 1 392 call void @usei32(i32 %i1) 393 br label %merge 394 395right: 396 %i2 = extractvalue { i32, i32 } %agg_right, 1 397 call void @usei32(i32 %i2) 398 br label %merge 399 400merge: 401 %i3 = phi i32 [ %i1, %left ], [ %i2, %right ] 402 call void @bar() 403 br label %end 404 405end: 406 call void @baz() 407 %i7 = insertvalue { i32, i32 } undef, i32 %i0, 0 408 %i8 = insertvalue { i32, i32 } %i7, i32 %i3, 1 409 ret { i32, i32 } %i8 410} 411 412; Most basic test - diamond structure, but with a switch, which results in multiple duplicate predecessors 413define { i32, i32 } @test8({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c, i32 %val_left, i32 %val_right) { 414; CHECK-LABEL: @test8( 415; CHECK-NEXT: entry: 416; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 417; CHECK: left: 418; CHECK-NEXT: call void @foo() 419; CHECK-NEXT: switch i32 [[VAL_LEFT:%.*]], label [[IMPOSSIBLE:%.*]] [ 420; CHECK-NEXT: i32 -42, label [[END:%.*]] 421; CHECK-NEXT: i32 42, label [[END]] 422; CHECK-NEXT: ] 423; CHECK: right: 424; CHECK-NEXT: call void @bar() 425; CHECK-NEXT: switch i32 [[VAL_RIGHT:%.*]], label [[IMPOSSIBLE]] [ 426; CHECK-NEXT: i32 42, label [[END]] 427; CHECK-NEXT: i32 -42, label [[END]] 428; CHECK-NEXT: ] 429; CHECK: impossible: 430; CHECK-NEXT: unreachable 431; CHECK: end: 432; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_LEFT]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ], [ [[AGG_RIGHT]], [[RIGHT]] ] 433; CHECK-NEXT: call void @baz() 434; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]] 435; 436entry: 437 br i1 %c, label %left, label %right 438 439left: 440 %i0 = extractvalue { i32, i32 } %agg_left, 0 441 %i2 = extractvalue { i32, i32 } %agg_left, 1 442 call void @foo() 443 switch i32 %val_left, label %impossible [ 444 i32 -42, label %end 445 i32 42, label %end 446 ] 447 448right: 449 %i3 = extractvalue { i32, i32 } %agg_right, 0 450 %i4 = extractvalue { i32, i32 } %agg_right, 1 451 call void @bar() 452 switch i32 %val_right, label %impossible [ 453 i32 42, label %end 454 i32 -42, label %end 455 ] 456 457impossible: 458 unreachable 459 460end: 461 %i5 = phi i32 [ %i0, %left ], [ %i0, %left ], [ %i3, %right ], [ %i3, %right ] 462 %i6 = phi i32 [ %i2, %left ], [ %i2, %left ], [ %i4, %right ], [ %i4, %right ] 463 call void @baz() 464 %i7 = insertvalue { i32, i32 } undef, i32 %i5, 0 465 %i8 = insertvalue { i32, i32 } %i7, i32 %i6, 1 466 ret { i32, i32 } %i8 467} 468 469; The insertion of first element could have been split/hoisted into the predecessors. 470define { i32, i32 } @test9({ i32, i32 } %agg_left, { i32, i32 } %agg_right, i1 %c) { 471; CHECK-LABEL: @test9( 472; CHECK-NEXT: entry: 473; CHECK-NEXT: br i1 [[C:%.*]], label [[LEFT:%.*]], label [[RIGHT:%.*]] 474; CHECK: left: 475; CHECK-NEXT: call void @foo() 476; CHECK-NEXT: br label [[END:%.*]] 477; CHECK: right: 478; CHECK-NEXT: call void @bar() 479; CHECK-NEXT: br label [[END]] 480; CHECK: end: 481; CHECK-NEXT: [[AGG_LEFT_PN:%.*]] = phi { i32, i32 } [ [[AGG_LEFT:%.*]], [[LEFT]] ], [ [[AGG_RIGHT:%.*]], [[RIGHT]] ] 482; CHECK-NEXT: call void @baz() 483; CHECK-NEXT: ret { i32, i32 } [[AGG_LEFT_PN]] 484; 485entry: 486 br i1 %c, label %left, label %right 487 488left: 489 %i0 = extractvalue { i32, i32 } %agg_left, 0 490 %i1 = extractvalue { i32, i32 } %agg_left, 1 491 %i2 = insertvalue { i32, i32 } undef, i32 %i0, 0 492 call void @foo() 493 br label %end 494 495right: 496 %i3 = extractvalue { i32, i32 } %agg_right, 0 497 %i4 = extractvalue { i32, i32 } %agg_right, 1 498 %i5 = insertvalue { i32, i32 } undef, i32 %i3, 0 499 call void @bar() 500 br label %end 501 502end: 503 %i6 = phi { i32, i32 } [ %i2, %left ], [ %i5, %right ] 504 %i7 = phi i32 [ %i1, %left ], [ %i4, %right ] 505 call void @baz() 506 %i8 = insertvalue { i32, i32 } %i6, i32 %i7, 1 507 ret { i32, i32 } %i8 508} 509