1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S --passes='simplifycfg<hoist-common-insts>' %s | FileCheck %s 3 4;; Check that the two loads are hoisted to the common predecessor, skipping 5;; over the add/sub instructions. 6 7define void @f0(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 8; CHECK-LABEL: @f0( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 11; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 12; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 13; CHECK: if.then: 14; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 15; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] 16; CHECK-NEXT: br label [[IF_END:%.*]] 17; CHECK: if.else: 18; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 19; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[SUB]], 3 20; CHECK-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP2]] 21; CHECK-NEXT: br label [[IF_END]] 22; CHECK: if.end: 23; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] 24; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 25; CHECK-NEXT: ret void 26; 27entry: 28 br i1 %c, label %if.then, label %if.else 29 30if.then: 31 %0 = load i16, ptr %b, align 2 32 %add = add nsw i16 %0, 1 33 %1 = load i16, ptr %m, align 2 34 %u = add i16 %add, %1 35 br label %if.end 36 37if.else: 38 %2 = load i16, ptr %b, align 2 39 %sub = sub nsw i16 %2, 1 40 %3 = load i16, ptr %m, align 2 41 %4 = add i16 %sub, 3 42 %v = add i16 %sub, %4 43 br label %if.end 44 45if.end: 46 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 47 store i16 %uv, ptr %d, align 2 48 ret void 49} 50 51define void @f0_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 52; CHECK-LABEL: @f0_switch( 53; CHECK-NEXT: entry: 54; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 55; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 56; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 57; CHECK-NEXT: i64 1, label [[BB1:%.*]] 58; CHECK-NEXT: i64 2, label [[BB2:%.*]] 59; CHECK-NEXT: ] 60; CHECK: bb0: 61; CHECK-NEXT: [[ADD:%.*]] = add nsw i16 [[TMP0]], 1 62; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD]], [[TMP1]] 63; CHECK-NEXT: br label [[END:%.*]] 64; CHECK: bb1: 65; CHECK-NEXT: [[SUB:%.*]] = sub nsw i16 [[TMP0]], 1 66; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[SUB]], 3 67; CHECK-NEXT: [[V:%.*]] = add i16 [[SUB]], [[TMP2]] 68; CHECK-NEXT: br label [[END]] 69; CHECK: bb2: 70; CHECK-NEXT: [[SUB2:%.*]] = sub nsw i16 [[TMP0]], 1 71; CHECK-NEXT: [[TMP3:%.*]] = add i16 [[SUB2]], 3 72; CHECK-NEXT: [[W:%.*]] = add i16 [[SUB2]], [[TMP3]] 73; CHECK-NEXT: br label [[END]] 74; CHECK: end: 75; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ] 76; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 77; CHECK-NEXT: ret void 78; 79entry: 80 switch i64 %i, label %bb0 [ 81 i64 1, label %bb1 82 i64 2, label %bb2 83 ] 84 85bb0: 86 %0 = load i16, ptr %b, align 2 87 %add = add nsw i16 %0, 1 88 %1 = load i16, ptr %m, align 2 89 %u = add i16 %add, %1 90 br label %end 91 92bb1: 93 %2 = load i16, ptr %b, align 2 94 %sub = sub nsw i16 %2, 1 95 %3 = load i16, ptr %m, align 2 96 %4 = add i16 %sub, 3 97 %v = add i16 %sub, %4 98 br label %end 99 100bb2: 101 %5 = load i16, ptr %b, align 2 102 %sub2 = sub nsw i16 %5, 1 103 %6 = load i16, ptr %m, align 2 104 %7 = add i16 %sub2, 3 105 %w = add i16 %sub2, %7 106 br label %end 107 108end: 109 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 110 store i16 %uv, ptr %d, align 2 111 ret void 112} 113 114;; Check some instructions (e.g. add) can be reordered across instructions with side 115;; effects, while others (e.g. load) can't. 116define void @f2(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 117; CHECK-LABEL: @f2( 118; CHECK-NEXT: entry: 119; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 120; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 121; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 122; CHECK: if.then: 123; CHECK-NEXT: call void @side_effects0() 124; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 125; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] 126; CHECK-NEXT: br label [[IF_END:%.*]] 127; CHECK: if.else: 128; CHECK-NEXT: call void @no_side_effects0() 129; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[M]], align 2 130; CHECK-NEXT: [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]] 131; CHECK-NEXT: br label [[IF_END]] 132; CHECK: if.end: 133; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] 134; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 135; CHECK-NEXT: ret void 136; 137entry: 138 br i1 %c, label %if.then, label %if.else 139 140if.then: 141 %0 = load i16, ptr %b, align 2 142 call void @side_effects0() 143 %add.0 = add nsw i16 %0, 1 144 %1 = load i16, ptr %m, align 2 145 %u = add i16 %add.0, %1 146 br label %if.end 147 148if.else: 149 %2 = load i16, ptr %b, align 2 150 call void @no_side_effects0() 151 %add.1 = add nsw i16 %2, 1 152 %3 = load i16, ptr %m, align 2 153 %v = add i16 %add.1, %3 154 br label %if.end 155 156if.end: 157 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 158 store i16 %uv, ptr %d, align 2 159 ret void 160} 161 162define void @f2_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 163; CHECK-LABEL: @f2_switch( 164; CHECK-NEXT: entry: 165; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 166; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 167; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 168; CHECK-NEXT: i64 1, label [[BB1:%.*]] 169; CHECK-NEXT: i64 2, label [[BB2:%.*]] 170; CHECK-NEXT: ] 171; CHECK: bb0: 172; CHECK-NEXT: call void @side_effects0() 173; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 174; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] 175; CHECK-NEXT: br label [[END:%.*]] 176; CHECK: bb1: 177; CHECK-NEXT: call void @no_side_effects0() 178; CHECK-NEXT: [[TMP2:%.*]] = load i16, ptr [[M]], align 2 179; CHECK-NEXT: [[V:%.*]] = add i16 [[ADD_0]], [[TMP2]] 180; CHECK-NEXT: br label [[END]] 181; CHECK: bb2: 182; CHECK-NEXT: call void @no_side_effects0() 183; CHECK-NEXT: [[TMP3:%.*]] = load i16, ptr [[M]], align 2 184; CHECK-NEXT: [[W:%.*]] = add i16 [[ADD_0]], [[TMP3]] 185; CHECK-NEXT: br label [[END]] 186; CHECK: end: 187; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ] 188; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 189; CHECK-NEXT: ret void 190; 191entry: 192 switch i64 %i, label %bb0 [ 193 i64 1, label %bb1 194 i64 2, label %bb2 195 ] 196 197bb0: 198 %0 = load i16, ptr %b, align 2 199 call void @side_effects0() 200 %add.0 = add nsw i16 %0, 1 201 %1 = load i16, ptr %m, align 2 202 %u = add i16 %add.0, %1 203 br label %end 204 205bb1: 206 %2 = load i16, ptr %b, align 2 207 call void @no_side_effects0() 208 %add.1 = add nsw i16 %2, 1 209 %3 = load i16, ptr %m, align 2 210 %v = add i16 %add.1, %3 211 br label %end 212 213bb2: 214 %4 = load i16, ptr %b, align 2 215 call void @no_side_effects0() 216 %add.2 = add nsw i16 %4, 1 217 %5 = load i16, ptr %m, align 2 218 %w = add i16 %add.2, %5 219 br label %end 220 221end: 222 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 223 store i16 %uv, ptr %d, align 2 224 ret void 225} 226 227;; Check indeed it was the side effects that prevented hoisting the load 228;; in the previous test. 229define void @f3(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 230; CHECK-LABEL: @f3( 231; CHECK-NEXT: entry: 232; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 233; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 234; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 235; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] 236; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 237; CHECK: if.then: 238; CHECK-NEXT: call void @no_side_effects0() 239; CHECK-NEXT: br label [[IF_END:%.*]] 240; CHECK: if.else: 241; CHECK-NEXT: call void @no_side_effects1() 242; CHECK-NEXT: br label [[IF_END]] 243; CHECK: if.end: 244; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 245; CHECK-NEXT: ret void 246; 247entry: 248 br i1 %c, label %if.then, label %if.else 249 250if.then: 251 %0 = load i16, ptr %b, align 2 252 call void @no_side_effects0() 253 %add.0 = add nsw i16 %0, 1 254 %1 = load i16, ptr %m, align 2 255 %u = add i16 %add.0, %1 256 br label %if.end 257 258if.else: 259 %2 = load i16, ptr %b, align 2 260 call void @no_side_effects1() 261 %add.1 = add nsw i16 %2, 1 262 %3 = load i16, ptr %m, align 2 263 %v = add i16 %add.1, %3 264 br label %if.end 265 266if.end: 267 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 268 store i16 %uv, ptr %d, align 2 269 ret void 270} 271 272define void @f3_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 273; CHECK-LABEL: @f3_switch( 274; CHECK-NEXT: entry: 275; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 276; CHECK-NEXT: [[ADD_0:%.*]] = add nsw i16 [[TMP0]], 1 277; CHECK-NEXT: [[TMP1:%.*]] = load i16, ptr [[M:%.*]], align 2 278; CHECK-NEXT: [[U:%.*]] = add i16 [[ADD_0]], [[TMP1]] 279; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 280; CHECK-NEXT: i64 1, label [[BB1:%.*]] 281; CHECK-NEXT: i64 2, label [[BB2:%.*]] 282; CHECK-NEXT: ] 283; CHECK: bb0: 284; CHECK-NEXT: call void @no_side_effects0() 285; CHECK-NEXT: br label [[END:%.*]] 286; CHECK: bb1: 287; CHECK-NEXT: call void @no_side_effects1() 288; CHECK-NEXT: br label [[END]] 289; CHECK: bb2: 290; CHECK-NEXT: call void @no_side_effects1() 291; CHECK-NEXT: br label [[END]] 292; CHECK: end: 293; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ] 294; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 295; CHECK-NEXT: ret void 296; 297entry: 298 switch i64 %i, label %bb0 [ 299 i64 1, label %bb1 300 i64 2, label %bb2 301 ] 302 303bb0: 304 %0 = load i16, ptr %b, align 2 305 call void @no_side_effects0() 306 %add.0 = add nsw i16 %0, 1 307 %1 = load i16, ptr %m, align 2 308 %u = add i16 %add.0, %1 309 br label %end 310 311bb1: 312 %2 = load i16, ptr %b, align 2 313 call void @no_side_effects1() 314 %add.1 = add nsw i16 %2, 1 315 %3 = load i16, ptr %m, align 2 316 %v = add i16 %add.1, %3 317 br label %end 318 319bb2: 320 %4 = load i16, ptr %b, align 2 321 call void @no_side_effects1() 322 %add.2 = add nsw i16 %4, 1 323 %5 = load i16, ptr %m, align 2 324 %w = add i16 %add.2, %5 325 br label %end 326 327end: 328 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 329 store i16 %uv, ptr %d, align 2 330 ret void 331} 332 333;; Check some instructions (e.g. sdiv) are not speculatively executed. 334 335;; Division by non-zero constant OK to speculate ... 336define void @f4(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 337; CHECK-LABEL: @f4( 338; CHECK-NEXT: entry: 339; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 340; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2 341; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 342; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 343; CHECK: if.then: 344; CHECK-NEXT: call void @side_effects0() 345; CHECK-NEXT: br label [[IF_END:%.*]] 346; CHECK: if.else: 347; CHECK-NEXT: call void @side_effects1() 348; CHECK-NEXT: br label [[IF_END]] 349; CHECK: if.end: 350; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 351; CHECK-NEXT: ret void 352; 353entry: 354 br i1 %c, label %if.then, label %if.else 355 356if.then: 357 %0 = load i16, ptr %b, align 2 358 call void @side_effects0() 359 %div.0 = sdiv i16 %0, 2 360 %u = add i16 %div.0, %0 361 br label %if.end 362 363if.else: 364 %1 = load i16, ptr %b, align 2 365 call void @side_effects1() 366 %div.1 = sdiv i16 %1, 2 367 %v = add i16 %div.1, %1 368 br label %if.end 369 370if.end: 371 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 372 store i16 %uv, ptr %d, align 2 373 ret void 374} 375 376define void @f4_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 377; CHECK-LABEL: @f4_switch( 378; CHECK-NEXT: entry: 379; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 380; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 [[TMP0]], 2 381; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 382; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 383; CHECK-NEXT: i64 1, label [[BB1:%.*]] 384; CHECK-NEXT: i64 2, label [[BB2:%.*]] 385; CHECK-NEXT: ] 386; CHECK: bb0: 387; CHECK-NEXT: call void @side_effects0() 388; CHECK-NEXT: br label [[IF_END:%.*]] 389; CHECK: bb1: 390; CHECK-NEXT: call void @side_effects1() 391; CHECK-NEXT: br label [[IF_END]] 392; CHECK: bb2: 393; CHECK-NEXT: call void @side_effects1() 394; CHECK-NEXT: br label [[IF_END]] 395; CHECK: if.end: 396; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ] 397; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 398; CHECK-NEXT: ret void 399; 400entry: 401 switch i64 %i, label %bb0 [ 402 i64 1, label %bb1 403 i64 2, label %bb2 404 ] 405 406bb0: 407 %0 = load i16, ptr %b, align 2 408 call void @side_effects0() 409 %div.0 = sdiv i16 %0, 2 410 %u = add i16 %div.0, %0 411 br label %if.end 412 413bb1: 414 %1 = load i16, ptr %b, align 2 415 call void @side_effects1() 416 %div.1 = sdiv i16 %1, 2 417 %v = add i16 %div.1, %1 418 br label %if.end 419 420bb2: 421 %2 = load i16, ptr %b, align 2 422 call void @side_effects1() 423 %div.2 = sdiv i16 %2, 2 424 %w = add i16 %div.2, %2 425 br label %if.end 426 427if.end: 428 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 429 store i16 %uv, ptr %d, align 2 430 ret void 431} 432 433;; ... but not a general division ... 434define void @f5(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 435; CHECK-LABEL: @f5( 436; CHECK-NEXT: entry: 437; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 438; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 439; CHECK: if.then: 440; CHECK-NEXT: call void @side_effects0() 441; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] 442; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 443; CHECK-NEXT: br label [[IF_END:%.*]] 444; CHECK: if.else: 445; CHECK-NEXT: call void @side_effects1() 446; CHECK-NEXT: [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]] 447; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] 448; CHECK-NEXT: br label [[IF_END]] 449; CHECK: if.end: 450; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[V]], [[IF_ELSE]] ], [ [[U]], [[IF_THEN]] ] 451; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 452; CHECK-NEXT: ret void 453; 454entry: 455 br i1 %c, label %if.then, label %if.else 456 457if.then: 458 %0 = load i16, ptr %b, align 2 459 call void @side_effects0() 460 %div.0 = sdiv i16 211, %0 461 %u = add i16 %div.0, %0 462 br label %if.end 463 464if.else: 465 %1 = load i16, ptr %b, align 2 466 call void @side_effects1() 467 %div.1 = sdiv i16 211, %1 468 %v = add i16 %div.1, %1 469 br label %if.end 470 471if.end: 472 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 473 store i16 %uv, ptr %d, align 2 474 ret void 475} 476 477define void @f5_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 478; CHECK-LABEL: @f5_switch( 479; CHECK-NEXT: entry: 480; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 481; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 482; CHECK-NEXT: i64 1, label [[BB1:%.*]] 483; CHECK-NEXT: i64 2, label [[BB2:%.*]] 484; CHECK-NEXT: ] 485; CHECK: bb0: 486; CHECK-NEXT: call void @side_effects0() 487; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] 488; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 489; CHECK-NEXT: br label [[END:%.*]] 490; CHECK: bb1: 491; CHECK-NEXT: call void @side_effects1() 492; CHECK-NEXT: [[DIV_1:%.*]] = sdiv i16 211, [[TMP0]] 493; CHECK-NEXT: [[V:%.*]] = add i16 [[DIV_1]], [[TMP0]] 494; CHECK-NEXT: br label [[END]] 495; CHECK: bb2: 496; CHECK-NEXT: call void @side_effects1() 497; CHECK-NEXT: [[DIV_2:%.*]] = sdiv i16 211, [[TMP0]] 498; CHECK-NEXT: [[W:%.*]] = add i16 [[DIV_2]], [[TMP0]] 499; CHECK-NEXT: br label [[END]] 500; CHECK: end: 501; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[V]], [[BB1]] ], [ [[W]], [[BB2]] ] 502; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 503; CHECK-NEXT: ret void 504; 505entry: 506 switch i64 %i, label %bb0 [ 507 i64 1, label %bb1 508 i64 2, label %bb2 509 ] 510 511bb0: 512 %0 = load i16, ptr %b, align 2 513 call void @side_effects0() 514 %div.0 = sdiv i16 211, %0 515 %u = add i16 %div.0, %0 516 br label %end 517 518bb1: 519 %1 = load i16, ptr %b, align 2 520 call void @side_effects1() 521 %div.1 = sdiv i16 211, %1 522 %v = add i16 %div.1, %1 523 br label %end 524 525bb2: 526 %2 = load i16, ptr %b, align 2 527 call void @side_effects1() 528 %div.2 = sdiv i16 211, %2 529 %w = add i16 %div.2, %2 530 br label %end 531 532end: 533 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 534 store i16 %uv, ptr %d, align 2 535 ret void 536} 537 538;; ... and it's also OK to hoist the division when there's no speculation happening. 539define void @f6(i1 %c, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 540; CHECK-LABEL: @f6( 541; CHECK-NEXT: entry: 542; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 543; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] 544; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 545; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 546; CHECK: if.then: 547; CHECK-NEXT: call void @no_side_effects0() 548; CHECK-NEXT: br label [[IF_END:%.*]] 549; CHECK: if.else: 550; CHECK-NEXT: call void @no_side_effects1() 551; CHECK-NEXT: br label [[IF_END]] 552; CHECK: if.end: 553; CHECK-NEXT: store i16 [[U]], ptr [[D:%.*]], align 2 554; CHECK-NEXT: ret void 555; 556entry: 557 br i1 %c, label %if.then, label %if.else 558 559if.then: 560 %0 = load i16, ptr %b, align 2 561 call void @no_side_effects0() 562 %div.0 = sdiv i16 211, %0 563 %u = add i16 %div.0, %0 564 br label %if.end 565 566if.else: 567 %1 = load i16, ptr %b, align 2 568 call void @no_side_effects1() 569 %div.1 = sdiv i16 211, %1 570 %v = add i16 %div.1, %1 571 br label %if.end 572 573if.end: 574 %uv = phi i16 [ %v, %if.else ], [ %u, %if.then ] 575 store i16 %uv, ptr %d, align 2 576 ret void 577} 578 579define void @f6_switch(i64 %i, ptr nocapture noundef %d, ptr nocapture noundef readonly %m, ptr nocapture noundef readonly %b) { 580; CHECK-LABEL: @f6_switch( 581; CHECK-NEXT: entry: 582; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr [[B:%.*]], align 2 583; CHECK-NEXT: [[DIV_0:%.*]] = sdiv i16 211, [[TMP0]] 584; CHECK-NEXT: [[U:%.*]] = add i16 [[DIV_0]], [[TMP0]] 585; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 586; CHECK-NEXT: i64 1, label [[BB1:%.*]] 587; CHECK-NEXT: i64 2, label [[BB2:%.*]] 588; CHECK-NEXT: ] 589; CHECK: bb0: 590; CHECK-NEXT: call void @no_side_effects0() 591; CHECK-NEXT: br label [[END:%.*]] 592; CHECK: bb1: 593; CHECK-NEXT: call void @no_side_effects1() 594; CHECK-NEXT: br label [[END]] 595; CHECK: bb2: 596; CHECK-NEXT: call void @no_side_effects1() 597; CHECK-NEXT: br label [[END]] 598; CHECK: end: 599; CHECK-NEXT: [[UV:%.*]] = phi i16 [ [[U]], [[BB0]] ], [ [[U]], [[BB1]] ], [ [[U]], [[BB2]] ] 600; CHECK-NEXT: store i16 [[UV]], ptr [[D:%.*]], align 2 601; CHECK-NEXT: ret void 602; 603entry: 604 switch i64 %i, label %bb0 [ 605 i64 1, label %bb1 606 i64 2, label %bb2 607 ] 608 609bb0: 610 %0 = load i16, ptr %b, align 2 611 call void @no_side_effects0() 612 %div.0 = sdiv i16 211, %0 613 %u = add i16 %div.0, %0 614 br label %end 615 616bb1: 617 %1 = load i16, ptr %b, align 2 618 call void @no_side_effects1() 619 %div.1 = sdiv i16 211, %1 620 %v = add i16 %div.1, %1 621 br label %end 622 623bb2: 624 %2 = load i16, ptr %b, align 2 625 call void @no_side_effects1() 626 %div.2 = sdiv i16 211, %2 627 %w = add i16 %div.2, %2 628 br label %end 629 630end: 631 %uv = phi i16 [ %u, %bb0 ], [ %v, %bb1 ], [ %w, %bb2 ] 632 store i16 %uv, ptr %d, align 2 633 ret void 634} 635 636;; No reorder of store over a load. 637define i16 @f7(i1 %c, ptr %a, ptr %b) { 638; CHECK-LABEL: @f7( 639; CHECK-NEXT: entry: 640; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 641; CHECK: if.then: 642; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2 643; CHECK-NEXT: store i16 0, ptr [[B:%.*]], align 2 644; CHECK-NEXT: br label [[IF_END:%.*]] 645; CHECK: if.else: 646; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B]], align 2 647; CHECK-NEXT: store i16 0, ptr [[B]], align 2 648; CHECK-NEXT: br label [[IF_END]] 649; CHECK: if.end: 650; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ] 651; CHECK-NEXT: ret i16 [[V]] 652; 653entry: 654 br i1 %c, label %if.then, label %if.else 655 656if.then: 657 %va = load i16, ptr %a, align 2 658 store i16 0, ptr %b, align 2 659 br label %if.end 660 661if.else: 662 %vb = load i16, ptr %b, align 2 663 store i16 0, ptr %b, align 2 664 br label %if.end 665 666if.end: 667 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ] 668 ret i16 %v 669} 670 671define i16 @f7_switch(i64 %i, ptr %a, ptr %b) { 672; CHECK-LABEL: @f7_switch( 673; CHECK-NEXT: entry: 674; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 675; CHECK-NEXT: i64 1, label [[BB1:%.*]] 676; CHECK-NEXT: i64 2, label [[BB2:%.*]] 677; CHECK-NEXT: ] 678; CHECK: bb0: 679; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2 680; CHECK-NEXT: store i16 0, ptr [[B:%.*]], align 2 681; CHECK-NEXT: br label [[END:%.*]] 682; CHECK: bb1: 683; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B]], align 2 684; CHECK-NEXT: store i16 0, ptr [[B]], align 2 685; CHECK-NEXT: br label [[END]] 686; CHECK: bb2: 687; CHECK-NEXT: [[VC:%.*]] = load i16, ptr [[B]], align 2 688; CHECK-NEXT: store i16 0, ptr [[B]], align 2 689; CHECK-NEXT: br label [[END]] 690; CHECK: end: 691; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ] 692; CHECK-NEXT: ret i16 [[V]] 693; 694entry: 695 switch i64 %i, label %bb0 [ 696 i64 1, label %bb1 697 i64 2, label %bb2 698 ] 699 700bb0: 701 %va = load i16, ptr %a, align 2 702 store i16 0, ptr %b, align 2 703 br label %end 704 705bb1: 706 %vb = load i16, ptr %b, align 2 707 store i16 0, ptr %b, align 2 708 br label %end 709 710bb2: 711 %vc = load i16, ptr %b, align 2 712 store i16 0, ptr %b, align 2 713 br label %end 714 715end: 716 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ] 717 ret i16 %v 718} 719 720;; Can reorder load over another load 721define i16 @f8(i1 %cond, ptr %a, ptr %b, ptr %c) { 722; CHECK-LABEL: @f8( 723; CHECK-NEXT: entry: 724; CHECK-NEXT: [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2 725; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 726; CHECK: if.then: 727; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2 728; CHECK-NEXT: br label [[IF_END:%.*]] 729; CHECK: if.else: 730; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2 731; CHECK-NEXT: br label [[IF_END]] 732; CHECK: if.end: 733; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ] 734; CHECK-NEXT: [[U:%.*]] = phi i16 [ [[C_0]], [[IF_THEN]] ], [ [[C_0]], [[IF_ELSE]] ] 735; CHECK-NEXT: [[W:%.*]] = add i16 [[V]], [[U]] 736; CHECK-NEXT: ret i16 [[W]] 737; 738entry: 739 br i1 %cond, label %if.then, label %if.else 740 741if.then: 742 %va = load i16, ptr %a, align 2 743 %c.0 = load i16, ptr %c 744 br label %if.end 745 746if.else: 747 %vb = load i16, ptr %b, align 2 748 %c.1 = load i16, ptr %c 749 br label %if.end 750 751if.end: 752 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ] 753 %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ] 754 755 %w = add i16 %v, %u 756 757 ret i16 %w 758} 759 760define i16 @f8_switch(i64 %i, ptr %a, ptr %b, ptr %c) { 761; CHECK-LABEL: @f8_switch( 762; CHECK-NEXT: entry: 763; CHECK-NEXT: [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2 764; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 765; CHECK-NEXT: i64 1, label [[BB1:%.*]] 766; CHECK-NEXT: i64 2, label [[BB2:%.*]] 767; CHECK-NEXT: ] 768; CHECK: bb0: 769; CHECK-NEXT: [[VA:%.*]] = load i16, ptr [[A:%.*]], align 2 770; CHECK-NEXT: br label [[END:%.*]] 771; CHECK: bb1: 772; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2 773; CHECK-NEXT: br label [[END]] 774; CHECK: bb2: 775; CHECK-NEXT: [[VC:%.*]] = load i16, ptr [[B]], align 2 776; CHECK-NEXT: br label [[END]] 777; CHECK: end: 778; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ] 779; CHECK-NEXT: [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_0]], [[BB1]] ], [ [[C_0]], [[BB2]] ] 780; CHECK-NEXT: [[W:%.*]] = add i16 [[V]], [[U]] 781; CHECK-NEXT: ret i16 [[W]] 782; 783entry: 784 switch i64 %i, label %bb0 [ 785 i64 1, label %bb1 786 i64 2, label %bb2 787 ] 788 789bb0: 790 %va = load i16, ptr %a, align 2 791 %c.0 = load i16, ptr %c 792 br label %end 793 794bb1: 795 %vb = load i16, ptr %b, align 2 796 %c.1 = load i16, ptr %c 797 br label %end 798 799bb2: 800 %vc = load i16, ptr %b, align 2 801 %c.2 = load i16, ptr %c 802 br label %end 803 804end: 805 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ] 806 %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ] 807 808 %w = add i16 %v, %u 809 810 ret i16 %w 811} 812 813;; Currently won't reorder volatile and non-volatile loads. 814define i16 @f9(i1 %cond, ptr %a, ptr %b, ptr %c) { 815; CHECK-LABEL: @f9( 816; CHECK-NEXT: entry: 817; CHECK-NEXT: br i1 [[COND:%.*]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]] 818; CHECK: if.then: 819; CHECK-NEXT: [[VA:%.*]] = load volatile i16, ptr [[A:%.*]], align 2 820; CHECK-NEXT: [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2 821; CHECK-NEXT: br label [[IF_END:%.*]] 822; CHECK: if.else: 823; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2 824; CHECK-NEXT: [[C_1:%.*]] = load i16, ptr [[C]], align 2 825; CHECK-NEXT: br label [[IF_END]] 826; CHECK: if.end: 827; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[IF_THEN]] ], [ [[VB]], [[IF_ELSE]] ] 828; CHECK-NEXT: [[U:%.*]] = phi i16 [ [[C_0]], [[IF_THEN]] ], [ [[C_1]], [[IF_ELSE]] ] 829; CHECK-NEXT: [[W:%.*]] = add i16 [[V]], [[U]] 830; CHECK-NEXT: ret i16 [[W]] 831; 832entry: 833 br i1 %cond, label %if.then, label %if.else 834 835if.then: 836 %va = load volatile i16, ptr %a, align 2 837 %c.0 = load i16, ptr %c 838 br label %if.end 839 840if.else: 841 %vb = load i16, ptr %b, align 2 842 %c.1 = load i16, ptr %c 843 br label %if.end 844 845if.end: 846 %v = phi i16 [ %va, %if.then ], [ %vb, %if.else ] 847 %u = phi i16 [ %c.0, %if.then ], [ %c.1, %if.else ] 848 849 %w = add i16 %v, %u 850 851 ret i16 %w 852} 853 854define i16 @f9_switch(i64 %i, ptr %a, ptr %b, ptr %c) { 855; CHECK-LABEL: @f9_switch( 856; CHECK-NEXT: entry: 857; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 858; CHECK-NEXT: i64 1, label [[BB1:%.*]] 859; CHECK-NEXT: i64 2, label [[BB2:%.*]] 860; CHECK-NEXT: ] 861; CHECK: bb0: 862; CHECK-NEXT: [[VA:%.*]] = load volatile i16, ptr [[A:%.*]], align 2 863; CHECK-NEXT: [[C_0:%.*]] = load i16, ptr [[C:%.*]], align 2 864; CHECK-NEXT: br label [[END:%.*]] 865; CHECK: bb1: 866; CHECK-NEXT: [[VB:%.*]] = load i16, ptr [[B:%.*]], align 2 867; CHECK-NEXT: [[C_1:%.*]] = load i16, ptr [[C]], align 2 868; CHECK-NEXT: br label [[END]] 869; CHECK: bb2: 870; CHECK-NEXT: [[VC:%.*]] = load i16, ptr [[B]], align 2 871; CHECK-NEXT: [[C_2:%.*]] = load i16, ptr [[C]], align 2 872; CHECK-NEXT: br label [[END]] 873; CHECK: end: 874; CHECK-NEXT: [[V:%.*]] = phi i16 [ [[VA]], [[BB0]] ], [ [[VB]], [[BB1]] ], [ [[VC]], [[BB2]] ] 875; CHECK-NEXT: [[U:%.*]] = phi i16 [ [[C_0]], [[BB0]] ], [ [[C_1]], [[BB1]] ], [ [[C_2]], [[BB2]] ] 876; CHECK-NEXT: [[W:%.*]] = add i16 [[V]], [[U]] 877; CHECK-NEXT: ret i16 [[W]] 878; 879entry: 880 switch i64 %i, label %bb0 [ 881 i64 1, label %bb1 882 i64 2, label %bb2 883 ] 884 885bb0: 886 %va = load volatile i16, ptr %a, align 2 887 %c.0 = load i16, ptr %c 888 br label %end 889 890bb1: 891 %vb = load i16, ptr %b, align 2 892 %c.1 = load i16, ptr %c 893 br label %end 894 895bb2: 896 %vc = load i16, ptr %b, align 2 897 %c.2 = load i16, ptr %c 898 br label %end 899 900end: 901 %v = phi i16 [ %va, %bb0 ], [ %vb, %bb1 ], [ %vc, %bb2 ] 902 %u = phi i16 [ %c.0, %bb0 ], [ %c.1, %bb1 ], [ %c.2, %bb2 ] 903 904 %w = add i16 %v, %u 905 906 ret i16 %w 907} 908 909;; Don't hoist stacksaves across inalloca allocas 910define void @f10(i1 %cond) { 911; CHECK-LABEL: @f10( 912; CHECK-NEXT: [[SS:%.*]] = call ptr @llvm.stacksave.p0() 913; CHECK-NEXT: br i1 [[COND:%.*]], label [[BB1:%.*]], label [[BB2:%.*]] 914; CHECK: bb1: 915; CHECK-NEXT: [[I1:%.*]] = alloca inalloca i32, align 4 916; CHECK-NEXT: [[SS2:%.*]] = call ptr @llvm.stacksave.p0() 917; CHECK-NEXT: [[I2:%.*]] = alloca inalloca i64, align 8 918; CHECK-NEXT: call void @inalloca_i64(ptr inalloca(i64) [[I2]]) 919; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS2]]) 920; CHECK-NEXT: call void @inalloca_i32(ptr inalloca(i32) [[I1]]) 921; CHECK-NEXT: br label [[END:%.*]] 922; CHECK: bb2: 923; CHECK-NEXT: [[I3:%.*]] = alloca inalloca i64, align 8 924; CHECK-NEXT: [[SS3:%.*]] = call ptr @llvm.stacksave.p0() 925; CHECK-NEXT: [[I4:%.*]] = alloca inalloca i64, align 8 926; CHECK-NEXT: [[TMP1:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I4]]) 927; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS3]]) 928; CHECK-NEXT: [[TMP2:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I3]]) 929; CHECK-NEXT: br label [[END]] 930; CHECK: end: 931; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS]]) 932; CHECK-NEXT: ret void 933; 934 %ss = call ptr @llvm.stacksave() 935 br i1 %cond, label %bb1, label %bb2 936 937bb1: 938 %i1 = alloca inalloca i32 939 %ss2 = call ptr @llvm.stacksave() 940 %i2 = alloca inalloca i64 941 call void @inalloca_i64(ptr inalloca(i64) %i2) 942 call void @llvm.stackrestore(ptr %ss2) 943 call void @inalloca_i32(ptr inalloca(i32) %i1) 944 br label %end 945 946bb2: 947 %i3 = alloca inalloca i64 948 %ss3 = call ptr @llvm.stacksave() 949 %i4 = alloca inalloca i64 950 call ptr @inalloca_i64(ptr inalloca(i64) %i4) 951 call void @llvm.stackrestore(ptr %ss3) 952 call ptr @inalloca_i64(ptr inalloca(i64) %i3) 953 br label %end 954 955end: 956 call void @llvm.stackrestore(ptr %ss) 957 ret void 958} 959 960define void @f10_switch(i64 %i) { 961; CHECK-LABEL: @f10_switch( 962; CHECK-NEXT: [[SS:%.*]] = call ptr @llvm.stacksave.p0() 963; CHECK-NEXT: switch i64 [[I:%.*]], label [[BB0:%.*]] [ 964; CHECK-NEXT: i64 1, label [[BB1:%.*]] 965; CHECK-NEXT: i64 2, label [[BB2:%.*]] 966; CHECK-NEXT: ] 967; CHECK: bb0: 968; CHECK-NEXT: [[I1:%.*]] = alloca inalloca i32, align 4 969; CHECK-NEXT: [[SS2:%.*]] = call ptr @llvm.stacksave.p0() 970; CHECK-NEXT: [[I2:%.*]] = alloca inalloca i64, align 8 971; CHECK-NEXT: call void @inalloca_i64(ptr inalloca(i64) [[I2]]) 972; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS2]]) 973; CHECK-NEXT: call void @inalloca_i32(ptr inalloca(i32) [[I1]]) 974; CHECK-NEXT: br label [[END:%.*]] 975; CHECK: bb1: 976; CHECK-NEXT: [[I3:%.*]] = alloca inalloca i64, align 8 977; CHECK-NEXT: [[SS3:%.*]] = call ptr @llvm.stacksave.p0() 978; CHECK-NEXT: [[I4:%.*]] = alloca inalloca i64, align 8 979; CHECK-NEXT: [[TMP1:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I4]]) 980; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS3]]) 981; CHECK-NEXT: [[TMP2:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I3]]) 982; CHECK-NEXT: br label [[END]] 983; CHECK: bb2: 984; CHECK-NEXT: [[I5:%.*]] = alloca inalloca i64, align 8 985; CHECK-NEXT: [[SS4:%.*]] = call ptr @llvm.stacksave.p0() 986; CHECK-NEXT: [[I6:%.*]] = alloca inalloca i64, align 8 987; CHECK-NEXT: [[TMP3:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I6]]) 988; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS4]]) 989; CHECK-NEXT: [[TMP4:%.*]] = call ptr @inalloca_i64(ptr inalloca(i64) [[I5]]) 990; CHECK-NEXT: br label [[END]] 991; CHECK: end: 992; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[SS]]) 993; CHECK-NEXT: ret void 994; 995 %ss = call ptr @llvm.stacksave() 996 switch i64 %i, label %bb0 [ 997 i64 1, label %bb1 998 i64 2, label %bb2 999 ] 1000 1001bb0: 1002 %i1 = alloca inalloca i32 1003 %ss2 = call ptr @llvm.stacksave() 1004 %i2 = alloca inalloca i64 1005 call void @inalloca_i64(ptr inalloca(i64) %i2) 1006 call void @llvm.stackrestore(ptr %ss2) 1007 call void @inalloca_i32(ptr inalloca(i32) %i1) 1008 br label %end 1009 1010bb1: 1011 %i3 = alloca inalloca i64 1012 %ss3 = call ptr @llvm.stacksave() 1013 %i4 = alloca inalloca i64 1014 call ptr @inalloca_i64(ptr inalloca(i64) %i4) 1015 call void @llvm.stackrestore(ptr %ss3) 1016 call ptr @inalloca_i64(ptr inalloca(i64) %i3) 1017 br label %end 1018 1019bb2: 1020 %i5 = alloca inalloca i64 1021 %ss4 = call ptr @llvm.stacksave() 1022 %i6 = alloca inalloca i64 1023 call ptr @inalloca_i64(ptr inalloca(i64) %i6) 1024 call void @llvm.stackrestore(ptr %ss4) 1025 call ptr @inalloca_i64(ptr inalloca(i64) %i5) 1026 br label %end 1027 1028end: 1029 call void @llvm.stackrestore(ptr %ss) 1030 ret void 1031} 1032 1033declare void @side_effects0() 1034declare void @side_effects1() 1035declare void @no_side_effects0() readonly nounwind willreturn 1036declare void @no_side_effects1() readonly nounwind willreturn 1037declare void @inalloca_i64(ptr inalloca(i64)) 1038declare void @inalloca_i32(ptr inalloca(i32)) 1039declare ptr @llvm.stacksave() 1040declare void @llvm.stackrestore(ptr) 1041