1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc %s -o - -enable-shrink-wrap=true -pass-remarks-output=%t -disable-cgp-delete-phis | FileCheck %s --check-prefix=ENABLE 3; RUN: cat %t | FileCheck %s --check-prefix=REMARKS 4; RUN: llc %s -o - -enable-shrink-wrap=false -disable-cgp-delete-phis | FileCheck %s --check-prefix=DISABLE 5; 6; Note: Lots of tests use inline asm instead of regular calls. 7; This allows to have a better control on what the allocation will do. 8; Otherwise, we may have spill right in the entry block, defeating 9; shrink-wrapping. Moreover, some of the inline asm statement (nop) 10; are here to ensure that the related paths do not end up as critical 11; edges. 12target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 13target triple = "x86_64-apple-macosx" 14 15 16; Initial motivating example: Simple diamond with a call just on one side. 17define i32 @foo(i32 %a, i32 %b) { 18; ENABLE-LABEL: foo: 19; ENABLE: ## %bb.0: 20; ENABLE-NEXT: movl %edi, %eax 21; ENABLE-NEXT: cmpl %esi, %edi 22; ENABLE-NEXT: jge LBB0_2 23; ENABLE-NEXT: ## %bb.1: ## %true 24; ENABLE-NEXT: pushq %rax 25; ENABLE-NEXT: .cfi_def_cfa_offset 16 26; ENABLE-NEXT: movl %eax, {{[0-9]+}}(%rsp) 27; ENABLE-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 28; ENABLE-NEXT: xorl %edi, %edi 29; ENABLE-NEXT: callq _doSomething 30; ENABLE-NEXT: addq $8, %rsp 31; ENABLE-NEXT: LBB0_2: ## %false 32; ENABLE-NEXT: retq 33; 34; DISABLE-LABEL: foo: 35; DISABLE: ## %bb.0: 36; DISABLE-NEXT: pushq %rax 37; DISABLE-NEXT: .cfi_def_cfa_offset 16 38; DISABLE-NEXT: movl %edi, %eax 39; DISABLE-NEXT: cmpl %esi, %edi 40; DISABLE-NEXT: jge LBB0_2 41; DISABLE-NEXT: ## %bb.1: ## %true 42; DISABLE-NEXT: movl %eax, {{[0-9]+}}(%rsp) 43; DISABLE-NEXT: leaq {{[0-9]+}}(%rsp), %rsi 44; DISABLE-NEXT: xorl %edi, %edi 45; DISABLE-NEXT: callq _doSomething 46; DISABLE-NEXT: LBB0_2: ## %false 47; DISABLE-NEXT: popq %rcx 48; DISABLE-NEXT: retq 49 %tmp = alloca i32, align 4 50 %tmp2 = icmp slt i32 %a, %b 51 br i1 %tmp2, label %true, label %false 52 53true: 54 store i32 %a, ptr %tmp, align 4 55 %tmp4 = call i32 @doSomething(i32 0, ptr %tmp) 56 br label %false 57 58false: 59 %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ] 60 ret i32 %tmp.0 61} 62 63; Function Attrs: optsize 64declare i32 @doSomething(i32, ptr) 65 66 67; Check that we do not perform the restore inside the loop whereas the save 68; is outside. 69define i32 @freqSaveAndRestoreOutsideLoop(i32 %cond, i32 %N) { 70; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop: 71; ENABLE: ## %bb.0: ## %entry 72; ENABLE-NEXT: testl %edi, %edi 73; ENABLE-NEXT: je LBB1_4 74; ENABLE-NEXT: ## %bb.1: ## %for.preheader 75; ENABLE-NEXT: pushq %rbx 76; ENABLE-NEXT: .cfi_def_cfa_offset 16 77; ENABLE-NEXT: .cfi_offset %rbx, -16 78; ENABLE-NEXT: ## InlineAsm Start 79; ENABLE-NEXT: nop 80; ENABLE-NEXT: ## InlineAsm End 81; ENABLE-NEXT: xorl %eax, %eax 82; ENABLE-NEXT: movl $10, %ecx 83; ENABLE-NEXT: .p2align 4 84; ENABLE-NEXT: LBB1_2: ## %for.body 85; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 86; ENABLE-NEXT: ## InlineAsm Start 87; ENABLE-NEXT: movl $1, %edx 88; ENABLE-NEXT: ## InlineAsm End 89; ENABLE-NEXT: addl %edx, %eax 90; ENABLE-NEXT: decl %ecx 91; ENABLE-NEXT: jne LBB1_2 92; ENABLE-NEXT: ## %bb.3: ## %for.end 93; ENABLE-NEXT: shll $3, %eax 94; ENABLE-NEXT: popq %rbx 95; ENABLE-NEXT: retq 96; ENABLE-NEXT: LBB1_4: ## %if.else 97; ENABLE-NEXT: movl %esi, %eax 98; ENABLE-NEXT: addl %esi, %eax 99; ENABLE-NEXT: retq 100; 101; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop: 102; DISABLE: ## %bb.0: ## %entry 103; DISABLE-NEXT: pushq %rbx 104; DISABLE-NEXT: .cfi_def_cfa_offset 16 105; DISABLE-NEXT: .cfi_offset %rbx, -16 106; DISABLE-NEXT: testl %edi, %edi 107; DISABLE-NEXT: je LBB1_4 108; DISABLE-NEXT: ## %bb.1: ## %for.preheader 109; DISABLE-NEXT: ## InlineAsm Start 110; DISABLE-NEXT: nop 111; DISABLE-NEXT: ## InlineAsm End 112; DISABLE-NEXT: xorl %eax, %eax 113; DISABLE-NEXT: movl $10, %ecx 114; DISABLE-NEXT: .p2align 4 115; DISABLE-NEXT: LBB1_2: ## %for.body 116; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 117; DISABLE-NEXT: ## InlineAsm Start 118; DISABLE-NEXT: movl $1, %edx 119; DISABLE-NEXT: ## InlineAsm End 120; DISABLE-NEXT: addl %edx, %eax 121; DISABLE-NEXT: decl %ecx 122; DISABLE-NEXT: jne LBB1_2 123; DISABLE-NEXT: ## %bb.3: ## %for.end 124; DISABLE-NEXT: shll $3, %eax 125; DISABLE-NEXT: popq %rbx 126; DISABLE-NEXT: retq 127; DISABLE-NEXT: LBB1_4: ## %if.else 128; DISABLE-NEXT: movl %esi, %eax 129; DISABLE-NEXT: addl %esi, %eax 130; DISABLE-NEXT: popq %rbx 131; DISABLE-NEXT: retq 132entry: 133 %tobool = icmp eq i32 %cond, 0 134 br i1 %tobool, label %if.else, label %for.preheader 135 136for.preheader: 137 tail call void asm "nop", ""() 138 br label %for.body 139 140for.body: ; preds = %entry, %for.body 141 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 142 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 143 %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() 144 %add = add nsw i32 %call, %sum.04 145 %inc = add nuw nsw i32 %i.05, 1 146 %exitcond = icmp eq i32 %inc, 10 147 br i1 %exitcond, label %for.end, label %for.body 148 149for.end: ; preds = %for.body 150 %shl = shl i32 %add, 3 151 br label %if.end 152 153if.else: ; preds = %entry 154 %mul = shl nsw i32 %N, 1 155 br label %if.end 156 157if.end: ; preds = %if.else, %for.end 158 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 159 ret i32 %sum.1 160} 161 162declare i32 @something(...) 163 164; Check that we do not perform the shrink-wrapping inside the loop even 165; though that would be legal. The cost model must prevent that. 166define i32 @freqSaveAndRestoreOutsideLoop2(i32 %cond) { 167; ENABLE-LABEL: freqSaveAndRestoreOutsideLoop2: 168; ENABLE: ## %bb.0: ## %entry 169; ENABLE-NEXT: pushq %rbx 170; ENABLE-NEXT: .cfi_def_cfa_offset 16 171; ENABLE-NEXT: .cfi_offset %rbx, -16 172; ENABLE-NEXT: ## InlineAsm Start 173; ENABLE-NEXT: nop 174; ENABLE-NEXT: ## InlineAsm End 175; ENABLE-NEXT: xorl %eax, %eax 176; ENABLE-NEXT: movl $10, %ecx 177; ENABLE-NEXT: .p2align 4 178; ENABLE-NEXT: LBB2_1: ## %for.body 179; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 180; ENABLE-NEXT: ## InlineAsm Start 181; ENABLE-NEXT: movl $1, %edx 182; ENABLE-NEXT: ## InlineAsm End 183; ENABLE-NEXT: addl %edx, %eax 184; ENABLE-NEXT: decl %ecx 185; ENABLE-NEXT: jne LBB2_1 186; ENABLE-NEXT: ## %bb.2: ## %for.exit 187; ENABLE-NEXT: ## InlineAsm Start 188; ENABLE-NEXT: nop 189; ENABLE-NEXT: ## InlineAsm End 190; ENABLE-NEXT: popq %rbx 191; ENABLE-NEXT: retq 192; 193; DISABLE-LABEL: freqSaveAndRestoreOutsideLoop2: 194; DISABLE: ## %bb.0: ## %entry 195; DISABLE-NEXT: pushq %rbx 196; DISABLE-NEXT: .cfi_def_cfa_offset 16 197; DISABLE-NEXT: .cfi_offset %rbx, -16 198; DISABLE-NEXT: ## InlineAsm Start 199; DISABLE-NEXT: nop 200; DISABLE-NEXT: ## InlineAsm End 201; DISABLE-NEXT: xorl %eax, %eax 202; DISABLE-NEXT: movl $10, %ecx 203; DISABLE-NEXT: .p2align 4 204; DISABLE-NEXT: LBB2_1: ## %for.body 205; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 206; DISABLE-NEXT: ## InlineAsm Start 207; DISABLE-NEXT: movl $1, %edx 208; DISABLE-NEXT: ## InlineAsm End 209; DISABLE-NEXT: addl %edx, %eax 210; DISABLE-NEXT: decl %ecx 211; DISABLE-NEXT: jne LBB2_1 212; DISABLE-NEXT: ## %bb.2: ## %for.exit 213; DISABLE-NEXT: ## InlineAsm Start 214; DISABLE-NEXT: nop 215; DISABLE-NEXT: ## InlineAsm End 216; DISABLE-NEXT: popq %rbx 217; DISABLE-NEXT: retq 218entry: 219 br label %for.preheader 220 221for.preheader: 222 tail call void asm "nop", ""() 223 br label %for.body 224 225for.body: ; preds = %for.body, %entry 226 %i.04 = phi i32 [ 0, %for.preheader ], [ %inc, %for.body ] 227 %sum.03 = phi i32 [ 0, %for.preheader ], [ %add, %for.body ] 228 %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() 229 %add = add nsw i32 %call, %sum.03 230 %inc = add nuw nsw i32 %i.04, 1 231 %exitcond = icmp eq i32 %inc, 10 232 br i1 %exitcond, label %for.exit, label %for.body 233 234for.exit: 235 tail call void asm "nop", ""() 236 br label %for.end 237 238for.end: ; preds = %for.body 239 ret i32 %add 240} 241 242; Check with a more complex case that we do not have save within the loop and 243; restore outside. 244define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) { 245; ENABLE-LABEL: loopInfoSaveOutsideLoop: 246; ENABLE: ## %bb.0: ## %entry 247; ENABLE-NEXT: testl %edi, %edi 248; ENABLE-NEXT: je LBB3_4 249; ENABLE-NEXT: ## %bb.1: ## %for.preheader 250; ENABLE-NEXT: pushq %rbx 251; ENABLE-NEXT: .cfi_def_cfa_offset 16 252; ENABLE-NEXT: .cfi_offset %rbx, -16 253; ENABLE-NEXT: ## InlineAsm Start 254; ENABLE-NEXT: nop 255; ENABLE-NEXT: ## InlineAsm End 256; ENABLE-NEXT: xorl %eax, %eax 257; ENABLE-NEXT: movl $10, %ecx 258; ENABLE-NEXT: .p2align 4 259; ENABLE-NEXT: LBB3_2: ## %for.body 260; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 261; ENABLE-NEXT: ## InlineAsm Start 262; ENABLE-NEXT: movl $1, %edx 263; ENABLE-NEXT: ## InlineAsm End 264; ENABLE-NEXT: addl %edx, %eax 265; ENABLE-NEXT: decl %ecx 266; ENABLE-NEXT: jne LBB3_2 267; ENABLE-NEXT: ## %bb.3: ## %for.end 268; ENABLE-NEXT: ## InlineAsm Start 269; ENABLE-NEXT: nop 270; ENABLE-NEXT: ## InlineAsm End 271; ENABLE-NEXT: shll $3, %eax 272; ENABLE-NEXT: popq %rbx 273; ENABLE-NEXT: retq 274; ENABLE-NEXT: LBB3_4: ## %if.else 275; ENABLE-NEXT: movl %esi, %eax 276; ENABLE-NEXT: addl %esi, %eax 277; ENABLE-NEXT: retq 278; 279; DISABLE-LABEL: loopInfoSaveOutsideLoop: 280; DISABLE: ## %bb.0: ## %entry 281; DISABLE-NEXT: pushq %rbx 282; DISABLE-NEXT: .cfi_def_cfa_offset 16 283; DISABLE-NEXT: .cfi_offset %rbx, -16 284; DISABLE-NEXT: testl %edi, %edi 285; DISABLE-NEXT: je LBB3_4 286; DISABLE-NEXT: ## %bb.1: ## %for.preheader 287; DISABLE-NEXT: ## InlineAsm Start 288; DISABLE-NEXT: nop 289; DISABLE-NEXT: ## InlineAsm End 290; DISABLE-NEXT: xorl %eax, %eax 291; DISABLE-NEXT: movl $10, %ecx 292; DISABLE-NEXT: .p2align 4 293; DISABLE-NEXT: LBB3_2: ## %for.body 294; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 295; DISABLE-NEXT: ## InlineAsm Start 296; DISABLE-NEXT: movl $1, %edx 297; DISABLE-NEXT: ## InlineAsm End 298; DISABLE-NEXT: addl %edx, %eax 299; DISABLE-NEXT: decl %ecx 300; DISABLE-NEXT: jne LBB3_2 301; DISABLE-NEXT: ## %bb.3: ## %for.end 302; DISABLE-NEXT: ## InlineAsm Start 303; DISABLE-NEXT: nop 304; DISABLE-NEXT: ## InlineAsm End 305; DISABLE-NEXT: shll $3, %eax 306; DISABLE-NEXT: popq %rbx 307; DISABLE-NEXT: retq 308; DISABLE-NEXT: LBB3_4: ## %if.else 309; DISABLE-NEXT: movl %esi, %eax 310; DISABLE-NEXT: addl %esi, %eax 311; DISABLE-NEXT: popq %rbx 312; DISABLE-NEXT: retq 313entry: 314 %tobool = icmp eq i32 %cond, 0 315 br i1 %tobool, label %if.else, label %for.preheader 316 317for.preheader: 318 tail call void asm "nop", ""() 319 br label %for.body 320 321for.body: ; preds = %entry, %for.body 322 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 323 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 324 %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() 325 %add = add nsw i32 %call, %sum.04 326 %inc = add nuw nsw i32 %i.05, 1 327 %exitcond = icmp eq i32 %inc, 10 328 br i1 %exitcond, label %for.end, label %for.body 329 330for.end: ; preds = %for.body 331 tail call void asm "nop", "~{ebx}"() 332 %shl = shl i32 %add, 3 333 br label %if.end 334 335if.else: ; preds = %entry 336 %mul = shl nsw i32 %N, 1 337 br label %if.end 338 339if.end: ; preds = %if.else, %for.end 340 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 341 ret i32 %sum.1 342} 343 344; Check with a more complex case that we do not have restore within the loop and 345; save outside. 346define i32 @loopInfoRestoreOutsideLoop(i32 %cond, i32 %N) nounwind { 347; ENABLE-LABEL: loopInfoRestoreOutsideLoop: 348; ENABLE: ## %bb.0: ## %entry 349; ENABLE-NEXT: testl %edi, %edi 350; ENABLE-NEXT: je LBB4_4 351; ENABLE-NEXT: ## %bb.1: ## %if.then 352; ENABLE-NEXT: pushq %rbx 353; ENABLE-NEXT: ## InlineAsm Start 354; ENABLE-NEXT: nop 355; ENABLE-NEXT: ## InlineAsm End 356; ENABLE-NEXT: xorl %eax, %eax 357; ENABLE-NEXT: movl $10, %ecx 358; ENABLE-NEXT: .p2align 4 359; ENABLE-NEXT: LBB4_2: ## %for.body 360; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 361; ENABLE-NEXT: ## InlineAsm Start 362; ENABLE-NEXT: movl $1, %edx 363; ENABLE-NEXT: ## InlineAsm End 364; ENABLE-NEXT: addl %edx, %eax 365; ENABLE-NEXT: decl %ecx 366; ENABLE-NEXT: jne LBB4_2 367; ENABLE-NEXT: ## %bb.3: ## %for.end 368; ENABLE-NEXT: shll $3, %eax 369; ENABLE-NEXT: popq %rbx 370; ENABLE-NEXT: retq 371; ENABLE-NEXT: LBB4_4: ## %if.else 372; ENABLE-NEXT: movl %esi, %eax 373; ENABLE-NEXT: addl %esi, %eax 374; ENABLE-NEXT: retq 375; 376; DISABLE-LABEL: loopInfoRestoreOutsideLoop: 377; DISABLE: ## %bb.0: ## %entry 378; DISABLE-NEXT: pushq %rbx 379; DISABLE-NEXT: testl %edi, %edi 380; DISABLE-NEXT: je LBB4_4 381; DISABLE-NEXT: ## %bb.1: ## %if.then 382; DISABLE-NEXT: ## InlineAsm Start 383; DISABLE-NEXT: nop 384; DISABLE-NEXT: ## InlineAsm End 385; DISABLE-NEXT: xorl %eax, %eax 386; DISABLE-NEXT: movl $10, %ecx 387; DISABLE-NEXT: .p2align 4 388; DISABLE-NEXT: LBB4_2: ## %for.body 389; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 390; DISABLE-NEXT: ## InlineAsm Start 391; DISABLE-NEXT: movl $1, %edx 392; DISABLE-NEXT: ## InlineAsm End 393; DISABLE-NEXT: addl %edx, %eax 394; DISABLE-NEXT: decl %ecx 395; DISABLE-NEXT: jne LBB4_2 396; DISABLE-NEXT: ## %bb.3: ## %for.end 397; DISABLE-NEXT: shll $3, %eax 398; DISABLE-NEXT: popq %rbx 399; DISABLE-NEXT: retq 400; DISABLE-NEXT: LBB4_4: ## %if.else 401; DISABLE-NEXT: movl %esi, %eax 402; DISABLE-NEXT: addl %esi, %eax 403; DISABLE-NEXT: popq %rbx 404; DISABLE-NEXT: retq 405entry: 406 %tobool = icmp eq i32 %cond, 0 407 br i1 %tobool, label %if.else, label %if.then 408 409if.then: ; preds = %entry 410 tail call void asm "nop", "~{ebx}"() 411 br label %for.body 412 413for.body: ; preds = %for.body, %if.then 414 %i.05 = phi i32 [ 0, %if.then ], [ %inc, %for.body ] 415 %sum.04 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 416 %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() 417 %add = add nsw i32 %call, %sum.04 418 %inc = add nuw nsw i32 %i.05, 1 419 %exitcond = icmp eq i32 %inc, 10 420 br i1 %exitcond, label %for.end, label %for.body 421 422for.end: ; preds = %for.body 423 %shl = shl i32 %add, 3 424 br label %if.end 425 426if.else: ; preds = %entry 427 %mul = shl nsw i32 %N, 1 428 br label %if.end 429 430if.end: ; preds = %if.else, %for.end 431 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 432 ret i32 %sum.1 433} 434 435; Check that we handle function with no frame information correctly. 436define i32 @emptyFrame() { 437; ENABLE-LABEL: emptyFrame: 438; ENABLE: ## %bb.0: ## %entry 439; ENABLE-NEXT: xorl %eax, %eax 440; ENABLE-NEXT: retq 441; 442; DISABLE-LABEL: emptyFrame: 443; DISABLE: ## %bb.0: ## %entry 444; DISABLE-NEXT: xorl %eax, %eax 445; DISABLE-NEXT: retq 446entry: 447 ret i32 0 448} 449 450; Check that we handle inline asm correctly. 451define i32 @inlineAsm(i32 %cond, i32 %N) { 452; ENABLE-LABEL: inlineAsm: 453; ENABLE: ## %bb.0: ## %entry 454; ENABLE-NEXT: testl %edi, %edi 455; ENABLE-NEXT: je LBB6_4 456; ENABLE-NEXT: ## %bb.1: ## %for.preheader 457; ENABLE-NEXT: pushq %rbx 458; ENABLE-NEXT: .cfi_def_cfa_offset 16 459; ENABLE-NEXT: .cfi_offset %rbx, -16 460; ENABLE-NEXT: ## InlineAsm Start 461; ENABLE-NEXT: nop 462; ENABLE-NEXT: ## InlineAsm End 463; ENABLE-NEXT: movl $10, %eax 464; ENABLE-NEXT: .p2align 4 465; ENABLE-NEXT: LBB6_2: ## %for.body 466; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 467; ENABLE-NEXT: ## InlineAsm Start 468; ENABLE-NEXT: addl $1, %ebx 469; ENABLE-NEXT: ## InlineAsm End 470; ENABLE-NEXT: decl %eax 471; ENABLE-NEXT: jne LBB6_2 472; ENABLE-NEXT: ## %bb.3: ## %for.exit 473; ENABLE-NEXT: ## InlineAsm Start 474; ENABLE-NEXT: nop 475; ENABLE-NEXT: ## InlineAsm End 476; ENABLE-NEXT: xorl %eax, %eax 477; ENABLE-NEXT: popq %rbx 478; ENABLE-NEXT: retq 479; ENABLE-NEXT: LBB6_4: ## %if.else 480; ENABLE-NEXT: movl %esi, %eax 481; ENABLE-NEXT: addl %esi, %eax 482; ENABLE-NEXT: retq 483; 484; DISABLE-LABEL: inlineAsm: 485; DISABLE: ## %bb.0: ## %entry 486; DISABLE-NEXT: pushq %rbx 487; DISABLE-NEXT: .cfi_def_cfa_offset 16 488; DISABLE-NEXT: .cfi_offset %rbx, -16 489; DISABLE-NEXT: testl %edi, %edi 490; DISABLE-NEXT: je LBB6_4 491; DISABLE-NEXT: ## %bb.1: ## %for.preheader 492; DISABLE-NEXT: ## InlineAsm Start 493; DISABLE-NEXT: nop 494; DISABLE-NEXT: ## InlineAsm End 495; DISABLE-NEXT: movl $10, %eax 496; DISABLE-NEXT: .p2align 4 497; DISABLE-NEXT: LBB6_2: ## %for.body 498; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 499; DISABLE-NEXT: ## InlineAsm Start 500; DISABLE-NEXT: addl $1, %ebx 501; DISABLE-NEXT: ## InlineAsm End 502; DISABLE-NEXT: decl %eax 503; DISABLE-NEXT: jne LBB6_2 504; DISABLE-NEXT: ## %bb.3: ## %for.exit 505; DISABLE-NEXT: ## InlineAsm Start 506; DISABLE-NEXT: nop 507; DISABLE-NEXT: ## InlineAsm End 508; DISABLE-NEXT: xorl %eax, %eax 509; DISABLE-NEXT: popq %rbx 510; DISABLE-NEXT: retq 511; DISABLE-NEXT: LBB6_4: ## %if.else 512; DISABLE-NEXT: movl %esi, %eax 513; DISABLE-NEXT: addl %esi, %eax 514; DISABLE-NEXT: popq %rbx 515; DISABLE-NEXT: retq 516entry: 517 %tobool = icmp eq i32 %cond, 0 518 br i1 %tobool, label %if.else, label %for.preheader 519 520for.preheader: 521 tail call void asm "nop", ""() 522 br label %for.body 523 524for.body: ; preds = %entry, %for.body 525 %i.03 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 526 tail call void asm "addl $$1, %ebx", "~{ebx}"() 527 %inc = add nuw nsw i32 %i.03, 1 528 %exitcond = icmp eq i32 %inc, 10 529 br i1 %exitcond, label %for.exit, label %for.body 530 531for.exit: 532 tail call void asm "nop", ""() 533 br label %if.end 534 535if.else: ; preds = %entry 536 %mul = shl nsw i32 %N, 1 537 br label %if.end 538 539if.end: ; preds = %for.body, %if.else 540 %sum.0 = phi i32 [ %mul, %if.else ], [ 0, %for.exit ] 541 ret i32 %sum.0 542} 543 544; Check that we handle calls to variadic functions correctly. 545define i32 @callVariadicFunc(i32 %cond, i32 %N) { 546; ENABLE-LABEL: callVariadicFunc: 547; ENABLE: ## %bb.0: ## %entry 548; ENABLE-NEXT: movl %esi, %eax 549; ENABLE-NEXT: testl %edi, %edi 550; ENABLE-NEXT: je LBB7_2 551; ENABLE-NEXT: ## %bb.1: ## %if.then 552; ENABLE-NEXT: pushq %rax 553; ENABLE-NEXT: .cfi_def_cfa_offset 16 554; ENABLE-NEXT: movl %eax, (%rsp) 555; ENABLE-NEXT: movl %eax, %edi 556; ENABLE-NEXT: movl %eax, %esi 557; ENABLE-NEXT: movl %eax, %edx 558; ENABLE-NEXT: movl %eax, %ecx 559; ENABLE-NEXT: movl %eax, %r8d 560; ENABLE-NEXT: movl %eax, %r9d 561; ENABLE-NEXT: xorl %eax, %eax 562; ENABLE-NEXT: callq _someVariadicFunc 563; ENABLE-NEXT: shll $3, %eax 564; ENABLE-NEXT: addq $8, %rsp 565; ENABLE-NEXT: retq 566; ENABLE-NEXT: LBB7_2: ## %if.else 567; ENABLE-NEXT: addl %eax, %eax 568; ENABLE-NEXT: retq 569; 570; DISABLE-LABEL: callVariadicFunc: 571; DISABLE: ## %bb.0: ## %entry 572; DISABLE-NEXT: pushq %rax 573; DISABLE-NEXT: .cfi_def_cfa_offset 16 574; DISABLE-NEXT: movl %esi, %eax 575; DISABLE-NEXT: testl %edi, %edi 576; DISABLE-NEXT: je LBB7_2 577; DISABLE-NEXT: ## %bb.1: ## %if.then 578; DISABLE-NEXT: movl %eax, (%rsp) 579; DISABLE-NEXT: movl %eax, %edi 580; DISABLE-NEXT: movl %eax, %esi 581; DISABLE-NEXT: movl %eax, %edx 582; DISABLE-NEXT: movl %eax, %ecx 583; DISABLE-NEXT: movl %eax, %r8d 584; DISABLE-NEXT: movl %eax, %r9d 585; DISABLE-NEXT: xorl %eax, %eax 586; DISABLE-NEXT: callq _someVariadicFunc 587; DISABLE-NEXT: shll $3, %eax 588; DISABLE-NEXT: popq %rcx 589; DISABLE-NEXT: retq 590; DISABLE-NEXT: LBB7_2: ## %if.else 591; DISABLE-NEXT: addl %eax, %eax 592; DISABLE-NEXT: popq %rcx 593; DISABLE-NEXT: retq 594entry: 595 %tobool = icmp eq i32 %cond, 0 596 br i1 %tobool, label %if.else, label %if.then 597 598if.then: ; preds = %entry 599 %call = tail call i32 (i32, ...) @someVariadicFunc(i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N, i32 %N) 600 %shl = shl i32 %call, 3 601 br label %if.end 602 603if.else: ; preds = %entry 604 %mul = shl nsw i32 %N, 1 605 br label %if.end 606 607if.end: ; preds = %if.else, %if.then 608 %sum.0 = phi i32 [ %shl, %if.then ], [ %mul, %if.else ] 609 ret i32 %sum.0 610} 611 612declare i32 @someVariadicFunc(i32, ...) 613 614; Check that we use LEA not to clobber EFLAGS. 615%struct.temp_slot = type { ptr, ptr, ptr, i32, i64, ptr, ptr, i8, i8, i32, i32, i64, i64 } 616%union.tree_node = type { %struct.tree_decl } 617%struct.tree_decl = type { %struct.tree_common, ptr, i32, i32, ptr, i48, %union.anon, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, %union.anon.1, ptr, ptr, ptr, i64, ptr } 618%struct.tree_common = type { ptr, ptr, i32 } 619%union.anon = type { i64 } 620%union.anon.1 = type { ptr } 621%struct.function = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i32, i32, i32, i32, ptr, %struct.ix86_args, ptr, ptr, ptr, ptr, i32, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, i64, ptr, ptr, ptr, ptr, i32, ptr, ptr, i32, i32, i32, ptr, i32, i32, ptr, ptr, ptr, i32, i32, ptr, i32, i32, ptr, ptr, i24 } 622%struct.eh_status = type opaque 623%struct.stmt_status = type opaque 624%struct.expr_status = type { i32, i32, i32, ptr, ptr, ptr, ptr } 625%struct.emit_status = type { i32, i32, ptr, ptr, ptr, ptr, i32, i32, ptr, i32, ptr, ptr, ptr } 626%struct.sequence_stack = type { ptr, ptr, ptr, ptr } 627%struct.varasm_status = type opaque 628%struct.ix86_args = type { i32, i32, i32, i32, i32, i32, i32 } 629%struct.initial_value_struct = type opaque 630%struct.var_refs_queue = type { ptr, i32, i32, ptr } 631%struct.machine_function = type opaque 632%struct.language_function = type opaque 633%struct.lang_decl = type opaque 634%struct.rtx_def = type { i32, [1 x %union.rtunion_def] } 635%union.rtunion_def = type { i64 } 636 637declare hidden fastcc ptr @find_temp_slot_from_address(ptr readonly) 638 639define void @useLEA(ptr readonly %x) { 640; ENABLE-LABEL: useLEA: 641; ENABLE: ## %bb.0: ## %entry 642; ENABLE-NEXT: testq %rdi, %rdi 643; ENABLE-NEXT: je LBB8_9 644; ENABLE-NEXT: ## %bb.1: ## %if.end 645; ENABLE-NEXT: cmpw $66, (%rdi) 646; ENABLE-NEXT: jne LBB8_9 647; ENABLE-NEXT: ## %bb.2: ## %lor.lhs.false 648; ENABLE-NEXT: pushq %rax 649; ENABLE-NEXT: .cfi_def_cfa_offset 16 650; ENABLE-NEXT: movq 8(%rdi), %rdi 651; ENABLE-NEXT: movzwl (%rdi), %eax 652; ENABLE-NEXT: leal -54(%rax), %ecx 653; ENABLE-NEXT: cmpl $14, %ecx 654; ENABLE-NEXT: ja LBB8_3 655; ENABLE-NEXT: ## %bb.7: ## %lor.lhs.false 656; ENABLE-NEXT: movl $24599, %edx ## imm = 0x6017 657; ENABLE-NEXT: btl %ecx, %edx 658; ENABLE-NEXT: jae LBB8_3 659; ENABLE-NEXT: LBB8_8: 660; ENABLE-NEXT: addq $8, %rsp 661; ENABLE-NEXT: LBB8_9: ## %cleanup 662; ENABLE-NEXT: retq 663; ENABLE-NEXT: LBB8_3: ## %lor.lhs.false 664; ENABLE-NEXT: cmpl $134, %eax 665; ENABLE-NEXT: je LBB8_8 666; ENABLE-NEXT: ## %bb.4: ## %lor.lhs.false 667; ENABLE-NEXT: cmpl $140, %eax 668; ENABLE-NEXT: je LBB8_8 669; ENABLE-NEXT: ## %bb.5: ## %if.end.55 670; ENABLE-NEXT: callq _find_temp_slot_from_address 671; ENABLE-NEXT: testq %rax, %rax 672; ENABLE-NEXT: je LBB8_8 673; ENABLE-NEXT: ## %bb.6: ## %if.then.60 674; ENABLE-NEXT: movb $1, 57(%rax) 675; ENABLE-NEXT: jmp LBB8_8 676; 677; DISABLE-LABEL: useLEA: 678; DISABLE: ## %bb.0: ## %entry 679; DISABLE-NEXT: pushq %rax 680; DISABLE-NEXT: .cfi_def_cfa_offset 16 681; DISABLE-NEXT: testq %rdi, %rdi 682; DISABLE-NEXT: je LBB8_7 683; DISABLE-NEXT: ## %bb.1: ## %if.end 684; DISABLE-NEXT: cmpw $66, (%rdi) 685; DISABLE-NEXT: jne LBB8_7 686; DISABLE-NEXT: ## %bb.2: ## %lor.lhs.false 687; DISABLE-NEXT: movq 8(%rdi), %rdi 688; DISABLE-NEXT: movzwl (%rdi), %eax 689; DISABLE-NEXT: leal -54(%rax), %ecx 690; DISABLE-NEXT: cmpl $14, %ecx 691; DISABLE-NEXT: ja LBB8_3 692; DISABLE-NEXT: ## %bb.8: ## %lor.lhs.false 693; DISABLE-NEXT: movl $24599, %edx ## imm = 0x6017 694; DISABLE-NEXT: btl %ecx, %edx 695; DISABLE-NEXT: jae LBB8_3 696; DISABLE-NEXT: LBB8_7: ## %cleanup 697; DISABLE-NEXT: popq %rax 698; DISABLE-NEXT: retq 699; DISABLE-NEXT: LBB8_3: ## %lor.lhs.false 700; DISABLE-NEXT: cmpl $134, %eax 701; DISABLE-NEXT: je LBB8_7 702; DISABLE-NEXT: ## %bb.4: ## %lor.lhs.false 703; DISABLE-NEXT: cmpl $140, %eax 704; DISABLE-NEXT: je LBB8_7 705; DISABLE-NEXT: ## %bb.5: ## %if.end.55 706; DISABLE-NEXT: callq _find_temp_slot_from_address 707; DISABLE-NEXT: testq %rax, %rax 708; DISABLE-NEXT: je LBB8_7 709; DISABLE-NEXT: ## %bb.6: ## %if.then.60 710; DISABLE-NEXT: movb $1, 57(%rax) 711; DISABLE-NEXT: popq %rax 712; DISABLE-NEXT: retq 713entry: 714 %cmp = icmp eq ptr %x, null 715 br i1 %cmp, label %cleanup, label %if.end 716 717if.end: ; preds = %entry 718 %bf.load = load i32, ptr %x, align 8 719 %bf.clear = and i32 %bf.load, 65535 720 %cmp1 = icmp eq i32 %bf.clear, 66 721 br i1 %cmp1, label %lor.lhs.false, label %cleanup 722 723lor.lhs.false: ; preds = %if.end 724 %arrayidx = getelementptr inbounds %struct.rtx_def, ptr %x, i64 0, i32 1, i64 0 725 %tmp1 = load ptr, ptr %arrayidx, align 8 726 %bf.load2 = load i32, ptr %tmp1, align 8 727 %bf.clear3 = and i32 %bf.load2, 65535 728 switch i32 %bf.clear3, label %if.end.55 [ 729 i32 67, label %cleanup 730 i32 68, label %cleanup 731 i32 54, label %cleanup 732 i32 55, label %cleanup 733 i32 58, label %cleanup 734 i32 134, label %cleanup 735 i32 56, label %cleanup 736 i32 140, label %cleanup 737 ] 738 739if.end.55: ; preds = %lor.lhs.false 740 %call = tail call fastcc ptr @find_temp_slot_from_address(ptr %tmp1) #2 741 %cmp59 = icmp eq ptr %call, null 742 br i1 %cmp59, label %cleanup, label %if.then.60 743 744if.then.60: ; preds = %if.end.55 745 %addr_taken = getelementptr inbounds %struct.temp_slot, ptr %call, i64 0, i32 8 746 store i8 1, ptr %addr_taken, align 1 747 br label %cleanup 748 749cleanup: ; preds = %if.then.60, %if.end.55, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %lor.lhs.false, %if.end, %entry 750 ret void 751} 752 753; Make sure we do not insert unreachable code after noreturn function. 754; Although this is not incorrect to insert such code, it is useless 755; and it hurts the binary size. 756define i32 @noreturn(i8 signext %bad_thing) { 757; ENABLE-LABEL: noreturn: 758; ENABLE: ## %bb.0: ## %entry 759; ENABLE-NEXT: testb %dil, %dil 760; ENABLE-NEXT: jne LBB9_2 761; ENABLE-NEXT: ## %bb.1: ## %if.end 762; ENABLE-NEXT: movl $42, %eax 763; ENABLE-NEXT: retq 764; ENABLE-NEXT: LBB9_2: ## %if.abort 765; ENABLE-NEXT: pushq %rax 766; ENABLE-NEXT: .cfi_def_cfa_offset 16 767; ENABLE-NEXT: callq _abort 768; 769; DISABLE-LABEL: noreturn: 770; DISABLE: ## %bb.0: ## %entry 771; DISABLE-NEXT: pushq %rax 772; DISABLE-NEXT: .cfi_def_cfa_offset 16 773; DISABLE-NEXT: testb %dil, %dil 774; DISABLE-NEXT: jne LBB9_2 775; DISABLE-NEXT: ## %bb.1: ## %if.end 776; DISABLE-NEXT: movl $42, %eax 777; DISABLE-NEXT: popq %rcx 778; DISABLE-NEXT: retq 779; DISABLE-NEXT: LBB9_2: ## %if.abort 780; DISABLE-NEXT: callq _abort 781entry: 782 %tobool = icmp eq i8 %bad_thing, 0 783 br i1 %tobool, label %if.end, label %if.abort 784 785if.abort: 786 tail call void @abort() #0 787 unreachable 788 789if.end: 790 ret i32 42 791} 792 793declare void @abort() #0 794 795attributes #0 = { noreturn nounwind } 796 797 798; Make sure that we handle infinite loops properly When checking that the Save 799; and Restore blocks are control flow equivalent, the loop searches for the 800; immediate (post) dominator for the (restore) save blocks. When either the Save 801; or Restore block is located in an infinite loop the only immediate (post) 802; dominator is itself. In this case, we cannot perform shrink wrapping, but we 803; should return gracefully and continue compilation. 804; The only condition for this test is the compilation finishes correctly. 805; 806define void @infiniteloop() { 807; ENABLE-LABEL: infiniteloop: 808; ENABLE: ## %bb.0: ## %entry 809; ENABLE-NEXT: pushq %rbp 810; ENABLE-NEXT: .cfi_def_cfa_offset 16 811; ENABLE-NEXT: .cfi_offset %rbp, -16 812; ENABLE-NEXT: movq %rsp, %rbp 813; ENABLE-NEXT: .cfi_def_cfa_register %rbp 814; ENABLE-NEXT: pushq %rbx 815; ENABLE-NEXT: pushq %rax 816; ENABLE-NEXT: .cfi_offset %rbx, -24 817; ENABLE-NEXT: xorl %eax, %eax 818; ENABLE-NEXT: testb %al, %al 819; ENABLE-NEXT: jne LBB10_3 820; ENABLE-NEXT: ## %bb.1: ## %if.then 821; ENABLE-NEXT: movq %rsp, %rcx 822; ENABLE-NEXT: addq $-16, %rcx 823; ENABLE-NEXT: movq %rcx, %rsp 824; ENABLE-NEXT: ## InlineAsm Start 825; ENABLE-NEXT: movl $1, %edx 826; ENABLE-NEXT: ## InlineAsm End 827; ENABLE-NEXT: .p2align 4 828; ENABLE-NEXT: LBB10_2: ## %for.body 829; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 830; ENABLE-NEXT: addl %edx, %eax 831; ENABLE-NEXT: movl %eax, (%rcx) 832; ENABLE-NEXT: jmp LBB10_2 833; ENABLE-NEXT: LBB10_3: ## %if.end 834; ENABLE-NEXT: leaq -8(%rbp), %rsp 835; ENABLE-NEXT: popq %rbx 836; ENABLE-NEXT: popq %rbp 837; ENABLE-NEXT: retq 838; 839; DISABLE-LABEL: infiniteloop: 840; DISABLE: ## %bb.0: ## %entry 841; DISABLE-NEXT: pushq %rbp 842; DISABLE-NEXT: .cfi_def_cfa_offset 16 843; DISABLE-NEXT: .cfi_offset %rbp, -16 844; DISABLE-NEXT: movq %rsp, %rbp 845; DISABLE-NEXT: .cfi_def_cfa_register %rbp 846; DISABLE-NEXT: pushq %rbx 847; DISABLE-NEXT: pushq %rax 848; DISABLE-NEXT: .cfi_offset %rbx, -24 849; DISABLE-NEXT: xorl %eax, %eax 850; DISABLE-NEXT: testb %al, %al 851; DISABLE-NEXT: jne LBB10_3 852; DISABLE-NEXT: ## %bb.1: ## %if.then 853; DISABLE-NEXT: movq %rsp, %rcx 854; DISABLE-NEXT: addq $-16, %rcx 855; DISABLE-NEXT: movq %rcx, %rsp 856; DISABLE-NEXT: ## InlineAsm Start 857; DISABLE-NEXT: movl $1, %edx 858; DISABLE-NEXT: ## InlineAsm End 859; DISABLE-NEXT: .p2align 4 860; DISABLE-NEXT: LBB10_2: ## %for.body 861; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 862; DISABLE-NEXT: addl %edx, %eax 863; DISABLE-NEXT: movl %eax, (%rcx) 864; DISABLE-NEXT: jmp LBB10_2 865; DISABLE-NEXT: LBB10_3: ## %if.end 866; DISABLE-NEXT: leaq -8(%rbp), %rsp 867; DISABLE-NEXT: popq %rbx 868; DISABLE-NEXT: popq %rbp 869; DISABLE-NEXT: retq 870entry: 871 br i1 poison, label %if.then, label %if.end 872 873if.then: 874 %ptr = alloca i32, i32 4 875 br label %for.body 876 877for.body: ; preds = %for.body, %entry 878 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %for.body ] 879 %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() 880 %add = add nsw i32 %call, %sum.03 881 store i32 %add, ptr %ptr 882 br label %for.body 883 884if.end: 885 ret void 886} 887 888; Another infinite loop test this time with a body bigger than just one block. 889define void @infiniteloop2() { 890; ENABLE-LABEL: infiniteloop2: 891; ENABLE: ## %bb.0: ## %entry 892; ENABLE-NEXT: pushq %rbp 893; ENABLE-NEXT: .cfi_def_cfa_offset 16 894; ENABLE-NEXT: .cfi_offset %rbp, -16 895; ENABLE-NEXT: movq %rsp, %rbp 896; ENABLE-NEXT: .cfi_def_cfa_register %rbp 897; ENABLE-NEXT: pushq %rbx 898; ENABLE-NEXT: pushq %rax 899; ENABLE-NEXT: .cfi_offset %rbx, -24 900; ENABLE-NEXT: xorl %eax, %eax 901; ENABLE-NEXT: testb %al, %al 902; ENABLE-NEXT: jne LBB11_5 903; ENABLE-NEXT: ## %bb.1: ## %if.then 904; ENABLE-NEXT: movq %rsp, %rcx 905; ENABLE-NEXT: addq $-16, %rcx 906; ENABLE-NEXT: movq %rcx, %rsp 907; ENABLE-NEXT: xorl %edx, %edx 908; ENABLE-NEXT: jmp LBB11_2 909; ENABLE-NEXT: .p2align 4 910; ENABLE-NEXT: LBB11_4: ## %body2 911; ENABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1 912; ENABLE-NEXT: ## InlineAsm Start 913; ENABLE-NEXT: nop 914; ENABLE-NEXT: ## InlineAsm End 915; ENABLE-NEXT: movl $1, %edx 916; ENABLE-NEXT: LBB11_2: ## %for.body 917; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 918; ENABLE-NEXT: movl %edx, %esi 919; ENABLE-NEXT: ## InlineAsm Start 920; ENABLE-NEXT: movl $1, %edx 921; ENABLE-NEXT: ## InlineAsm End 922; ENABLE-NEXT: addl %esi, %edx 923; ENABLE-NEXT: movl %edx, (%rcx) 924; ENABLE-NEXT: testb %al, %al 925; ENABLE-NEXT: jne LBB11_4 926; ENABLE-NEXT: ## %bb.3: ## %body1 927; ENABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1 928; ENABLE-NEXT: ## InlineAsm Start 929; ENABLE-NEXT: nop 930; ENABLE-NEXT: ## InlineAsm End 931; ENABLE-NEXT: jmp LBB11_2 932; ENABLE-NEXT: LBB11_5: ## %if.end 933; ENABLE-NEXT: leaq -8(%rbp), %rsp 934; ENABLE-NEXT: popq %rbx 935; ENABLE-NEXT: popq %rbp 936; ENABLE-NEXT: retq 937; 938; DISABLE-LABEL: infiniteloop2: 939; DISABLE: ## %bb.0: ## %entry 940; DISABLE-NEXT: pushq %rbp 941; DISABLE-NEXT: .cfi_def_cfa_offset 16 942; DISABLE-NEXT: .cfi_offset %rbp, -16 943; DISABLE-NEXT: movq %rsp, %rbp 944; DISABLE-NEXT: .cfi_def_cfa_register %rbp 945; DISABLE-NEXT: pushq %rbx 946; DISABLE-NEXT: pushq %rax 947; DISABLE-NEXT: .cfi_offset %rbx, -24 948; DISABLE-NEXT: xorl %eax, %eax 949; DISABLE-NEXT: testb %al, %al 950; DISABLE-NEXT: jne LBB11_5 951; DISABLE-NEXT: ## %bb.1: ## %if.then 952; DISABLE-NEXT: movq %rsp, %rcx 953; DISABLE-NEXT: addq $-16, %rcx 954; DISABLE-NEXT: movq %rcx, %rsp 955; DISABLE-NEXT: xorl %edx, %edx 956; DISABLE-NEXT: jmp LBB11_2 957; DISABLE-NEXT: .p2align 4 958; DISABLE-NEXT: LBB11_4: ## %body2 959; DISABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1 960; DISABLE-NEXT: ## InlineAsm Start 961; DISABLE-NEXT: nop 962; DISABLE-NEXT: ## InlineAsm End 963; DISABLE-NEXT: movl $1, %edx 964; DISABLE-NEXT: LBB11_2: ## %for.body 965; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 966; DISABLE-NEXT: movl %edx, %esi 967; DISABLE-NEXT: ## InlineAsm Start 968; DISABLE-NEXT: movl $1, %edx 969; DISABLE-NEXT: ## InlineAsm End 970; DISABLE-NEXT: addl %esi, %edx 971; DISABLE-NEXT: movl %edx, (%rcx) 972; DISABLE-NEXT: testb %al, %al 973; DISABLE-NEXT: jne LBB11_4 974; DISABLE-NEXT: ## %bb.3: ## %body1 975; DISABLE-NEXT: ## in Loop: Header=BB11_2 Depth=1 976; DISABLE-NEXT: ## InlineAsm Start 977; DISABLE-NEXT: nop 978; DISABLE-NEXT: ## InlineAsm End 979; DISABLE-NEXT: jmp LBB11_2 980; DISABLE-NEXT: LBB11_5: ## %if.end 981; DISABLE-NEXT: leaq -8(%rbp), %rsp 982; DISABLE-NEXT: popq %rbx 983; DISABLE-NEXT: popq %rbp 984; DISABLE-NEXT: retq 985entry: 986 br i1 poison, label %if.then, label %if.end 987 988if.then: 989 %ptr = alloca i32, i32 4 990 br label %for.body 991 992for.body: ; preds = %for.body, %entry 993 %sum.03 = phi i32 [ 0, %if.then ], [ %add, %body1 ], [ 1, %body2] 994 %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() 995 %add = add nsw i32 %call, %sum.03 996 store i32 %add, ptr %ptr 997 br i1 poison, label %body1, label %body2 998 999body1: 1000 tail call void asm sideeffect "nop", "~{ebx}"() 1001 br label %for.body 1002 1003body2: 1004 tail call void asm sideeffect "nop", "~{ebx}"() 1005 br label %for.body 1006 1007if.end: 1008 ret void 1009} 1010 1011; Another infinite loop test this time with two nested infinite loop. 1012define void @infiniteloop3() { 1013; ENABLE-LABEL: infiniteloop3: 1014; ENABLE: ## %bb.0: ## %entry 1015; ENABLE-NEXT: xorl %eax, %eax 1016; ENABLE-NEXT: testb %al, %al 1017; ENABLE-NEXT: jne LBB12_2 1018; ENABLE-NEXT: ## %bb.1: ## %body 1019; ENABLE-NEXT: xorl %eax, %eax 1020; ENABLE-NEXT: testb %al, %al 1021; ENABLE-NEXT: jne LBB12_7 1022; ENABLE-NEXT: LBB12_2: ## %loop2a.preheader 1023; ENABLE-NEXT: xorl %eax, %eax 1024; ENABLE-NEXT: xorl %ecx, %ecx 1025; ENABLE-NEXT: movq %rax, %rsi 1026; ENABLE-NEXT: jmp LBB12_4 1027; ENABLE-NEXT: .p2align 4 1028; ENABLE-NEXT: LBB12_3: ## %loop2b 1029; ENABLE-NEXT: ## in Loop: Header=BB12_4 Depth=1 1030; ENABLE-NEXT: movq %rdx, (%rsi) 1031; ENABLE-NEXT: movq %rdx, %rsi 1032; ENABLE-NEXT: LBB12_4: ## %loop1 1033; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1034; ENABLE-NEXT: movq %rcx, %rdx 1035; ENABLE-NEXT: testq %rax, %rax 1036; ENABLE-NEXT: movq (%rax), %rcx 1037; ENABLE-NEXT: jne LBB12_3 1038; ENABLE-NEXT: ## %bb.5: ## in Loop: Header=BB12_4 Depth=1 1039; ENABLE-NEXT: movq %rdx, %rax 1040; ENABLE-NEXT: movq %rdx, %rsi 1041; ENABLE-NEXT: jmp LBB12_4 1042; ENABLE-NEXT: LBB12_7: ## %end 1043; ENABLE-NEXT: retq 1044; 1045; DISABLE-LABEL: infiniteloop3: 1046; DISABLE: ## %bb.0: ## %entry 1047; DISABLE-NEXT: xorl %eax, %eax 1048; DISABLE-NEXT: testb %al, %al 1049; DISABLE-NEXT: jne LBB12_2 1050; DISABLE-NEXT: ## %bb.1: ## %body 1051; DISABLE-NEXT: xorl %eax, %eax 1052; DISABLE-NEXT: testb %al, %al 1053; DISABLE-NEXT: jne LBB12_7 1054; DISABLE-NEXT: LBB12_2: ## %loop2a.preheader 1055; DISABLE-NEXT: xorl %eax, %eax 1056; DISABLE-NEXT: xorl %ecx, %ecx 1057; DISABLE-NEXT: movq %rax, %rsi 1058; DISABLE-NEXT: jmp LBB12_4 1059; DISABLE-NEXT: .p2align 4 1060; DISABLE-NEXT: LBB12_3: ## %loop2b 1061; DISABLE-NEXT: ## in Loop: Header=BB12_4 Depth=1 1062; DISABLE-NEXT: movq %rdx, (%rsi) 1063; DISABLE-NEXT: movq %rdx, %rsi 1064; DISABLE-NEXT: LBB12_4: ## %loop1 1065; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1066; DISABLE-NEXT: movq %rcx, %rdx 1067; DISABLE-NEXT: testq %rax, %rax 1068; DISABLE-NEXT: movq (%rax), %rcx 1069; DISABLE-NEXT: jne LBB12_3 1070; DISABLE-NEXT: ## %bb.5: ## in Loop: Header=BB12_4 Depth=1 1071; DISABLE-NEXT: movq %rdx, %rax 1072; DISABLE-NEXT: movq %rdx, %rsi 1073; DISABLE-NEXT: jmp LBB12_4 1074; DISABLE-NEXT: LBB12_7: ## %end 1075; DISABLE-NEXT: retq 1076entry: 1077 br i1 poison, label %loop2a, label %body 1078 1079body: ; preds = %entry 1080 br i1 poison, label %loop2a, label %end 1081 1082loop1: ; preds = %loop2a, %loop2b 1083 %var.phi = phi ptr [ %next.phi, %loop2b ], [ %var, %loop2a ] 1084 %next.phi = phi ptr [ %next.load, %loop2b ], [ %next.var, %loop2a ] 1085 %0 = icmp eq ptr %var, null 1086 %next.load = load ptr, ptr undef 1087 br i1 %0, label %loop2a, label %loop2b 1088 1089loop2a: ; preds = %loop1, %body, %entry 1090 %var = phi ptr [ null, %body ], [ null, %entry ], [ %next.phi, %loop1 ] 1091 %next.var = phi ptr [ undef, %body ], [ null, %entry ], [ %next.load, %loop1 ] 1092 br label %loop1 1093 1094loop2b: ; preds = %loop1 1095 store ptr %next.phi, ptr %var.phi 1096 br label %loop1 1097 1098end: 1099 ret void 1100} 1101 1102; Check that we just don't bail out on RegMask. 1103; In this case, the RegMask does not touch a CSR so we are good to go! 1104define i32 @regmask(i32 %a, i32 %b, ptr %addr) { 1105; ENABLE-LABEL: regmask: 1106; ENABLE: ## %bb.0: 1107; ENABLE-NEXT: cmpl %esi, %edi 1108; ENABLE-NEXT: jge LBB13_2 1109; ENABLE-NEXT: ## %bb.1: ## %true 1110; ENABLE-NEXT: pushq %rbx 1111; ENABLE-NEXT: .cfi_def_cfa_offset 16 1112; ENABLE-NEXT: .cfi_offset %rbx, -16 1113; ENABLE-NEXT: ## InlineAsm Start 1114; ENABLE-NEXT: nop 1115; ENABLE-NEXT: ## InlineAsm End 1116; ENABLE-NEXT: xorl %edi, %edi 1117; ENABLE-NEXT: movq %rdx, %rsi 1118; ENABLE-NEXT: callq _doSomething 1119; ENABLE-NEXT: popq %rbx 1120; ENABLE-NEXT: retq 1121; ENABLE-NEXT: LBB13_2: ## %false 1122; ENABLE-NEXT: movl $6, %edi 1123; ENABLE-NEXT: movq %rdx, %rsi 1124; ENABLE-NEXT: jmp _doSomething ## TAILCALL 1125; 1126; DISABLE-LABEL: regmask: 1127; DISABLE: ## %bb.0: 1128; DISABLE-NEXT: pushq %rbx 1129; DISABLE-NEXT: .cfi_def_cfa_offset 16 1130; DISABLE-NEXT: .cfi_offset %rbx, -16 1131; DISABLE-NEXT: cmpl %esi, %edi 1132; DISABLE-NEXT: jge LBB13_2 1133; DISABLE-NEXT: ## %bb.1: ## %true 1134; DISABLE-NEXT: ## InlineAsm Start 1135; DISABLE-NEXT: nop 1136; DISABLE-NEXT: ## InlineAsm End 1137; DISABLE-NEXT: xorl %edi, %edi 1138; DISABLE-NEXT: movq %rdx, %rsi 1139; DISABLE-NEXT: callq _doSomething 1140; DISABLE-NEXT: popq %rbx 1141; DISABLE-NEXT: retq 1142; DISABLE-NEXT: LBB13_2: ## %false 1143; DISABLE-NEXT: movl $6, %edi 1144; DISABLE-NEXT: movq %rdx, %rsi 1145; DISABLE-NEXT: popq %rbx 1146; DISABLE-NEXT: jmp _doSomething ## TAILCALL 1147 %tmp2 = icmp slt i32 %a, %b 1148 br i1 %tmp2, label %true, label %false 1149 1150true: 1151 ; Clobber a CSR so that we check something on the regmask 1152 ; of the tail call. 1153 tail call void asm sideeffect "nop", "~{ebx}"() 1154 %tmp4 = call i32 @doSomething(i32 0, ptr %addr) 1155 br label %end 1156 1157false: 1158 %tmp5 = tail call i32 @doSomething(i32 6, ptr %addr) 1159 br label %end 1160 1161end: 1162 %tmp.0 = phi i32 [ %tmp4, %true ], [ %tmp5, %false ] 1163 ret i32 %tmp.0 1164} 1165 1166@b = internal unnamed_addr global i1 false 1167@c = internal unnamed_addr global i8 0, align 1 1168@a = common global i32 0, align 4 1169 1170; Make sure the prologue does not clobber the EFLAGS when 1171; it is live accross. 1172; PR25629. 1173; Note: The registers may change in the following patterns, but 1174; because they imply register hierarchy (e.g., eax, al) this is 1175; tricky to write robust patterns. 1176define i32 @useLEAForPrologue(i32 %d, i32 %a, i8 %c) #3 { 1177; ENABLE-LABEL: useLEAForPrologue: 1178; ENABLE: ## %bb.0: ## %entry 1179; ENABLE-NEXT: pushq %rbx 1180; ENABLE-NEXT: subq $16, %rsp 1181; ENABLE-NEXT: xorl %eax, %eax 1182; ENABLE-NEXT: cmpb $0, _b(%rip) 1183; ENABLE-NEXT: movl $48, %ecx 1184; ENABLE-NEXT: cmovnel %eax, %ecx 1185; ENABLE-NEXT: movb %cl, _c(%rip) 1186; ENABLE-NEXT: je LBB14_4 1187; ENABLE-NEXT: ## %bb.1: ## %for.body.lr.ph 1188; ENABLE-NEXT: ## InlineAsm Start 1189; ENABLE-NEXT: nop 1190; ENABLE-NEXT: ## InlineAsm End 1191; ENABLE-NEXT: .p2align 4 1192; ENABLE-NEXT: LBB14_2: ## %for.body 1193; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1194; ENABLE-NEXT: cmpl %esi, %edi 1195; ENABLE-NEXT: setl %al 1196; ENABLE-NEXT: xorl %esi, %esi 1197; ENABLE-NEXT: movb %al, %sil 1198; ENABLE-NEXT: incb %dl 1199; ENABLE-NEXT: cmpb $45, %dl 1200; ENABLE-NEXT: jl LBB14_2 1201; ENABLE-NEXT: ## %bb.3: ## %for.cond.for.end_crit_edge 1202; ENABLE-NEXT: movq _a@GOTPCREL(%rip), %rax 1203; ENABLE-NEXT: movl %esi, (%rax) 1204; ENABLE-NEXT: LBB14_4: ## %for.end 1205; ENABLE-NEXT: xorl %edi, %edi 1206; ENABLE-NEXT: callq _varfunc 1207; ENABLE-NEXT: xorl %eax, %eax 1208; ENABLE-NEXT: addq $16, %rsp 1209; ENABLE-NEXT: popq %rbx 1210; ENABLE-NEXT: retq 1211; 1212; DISABLE-LABEL: useLEAForPrologue: 1213; DISABLE: ## %bb.0: ## %entry 1214; DISABLE-NEXT: pushq %rbx 1215; DISABLE-NEXT: subq $16, %rsp 1216; DISABLE-NEXT: xorl %eax, %eax 1217; DISABLE-NEXT: cmpb $0, _b(%rip) 1218; DISABLE-NEXT: movl $48, %ecx 1219; DISABLE-NEXT: cmovnel %eax, %ecx 1220; DISABLE-NEXT: movb %cl, _c(%rip) 1221; DISABLE-NEXT: je LBB14_4 1222; DISABLE-NEXT: ## %bb.1: ## %for.body.lr.ph 1223; DISABLE-NEXT: ## InlineAsm Start 1224; DISABLE-NEXT: nop 1225; DISABLE-NEXT: ## InlineAsm End 1226; DISABLE-NEXT: .p2align 4 1227; DISABLE-NEXT: LBB14_2: ## %for.body 1228; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1229; DISABLE-NEXT: cmpl %esi, %edi 1230; DISABLE-NEXT: setl %al 1231; DISABLE-NEXT: xorl %esi, %esi 1232; DISABLE-NEXT: movb %al, %sil 1233; DISABLE-NEXT: incb %dl 1234; DISABLE-NEXT: cmpb $45, %dl 1235; DISABLE-NEXT: jl LBB14_2 1236; DISABLE-NEXT: ## %bb.3: ## %for.cond.for.end_crit_edge 1237; DISABLE-NEXT: movq _a@GOTPCREL(%rip), %rax 1238; DISABLE-NEXT: movl %esi, (%rax) 1239; DISABLE-NEXT: LBB14_4: ## %for.end 1240; DISABLE-NEXT: xorl %edi, %edi 1241; DISABLE-NEXT: callq _varfunc 1242; DISABLE-NEXT: xorl %eax, %eax 1243; DISABLE-NEXT: addq $16, %rsp 1244; DISABLE-NEXT: popq %rbx 1245; DISABLE-NEXT: retq 1246entry: 1247 %tmp = alloca i3 1248 %.b = load i1, ptr @b, align 1 1249 %bool = select i1 %.b, i8 0, i8 48 1250 store i8 %bool, ptr @c, align 1 1251 br i1 %.b, label %for.body.lr.ph, label %for.end 1252 1253for.body.lr.ph: ; preds = %entry 1254 tail call void asm sideeffect "nop", "~{ebx}"() 1255 br label %for.body 1256 1257for.body: ; preds = %for.body.lr.ph, %for.body 1258 %inc6 = phi i8 [ %c, %for.body.lr.ph ], [ %inc, %for.body ] 1259 %cond5 = phi i32 [ %a, %for.body.lr.ph ], [ %conv3, %for.body ] 1260 %cmp2 = icmp slt i32 %d, %cond5 1261 %conv3 = zext i1 %cmp2 to i32 1262 %inc = add i8 %inc6, 1 1263 %cmp = icmp slt i8 %inc, 45 1264 br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge 1265 1266for.cond.for.end_crit_edge: ; preds = %for.body 1267 store i32 %conv3, ptr @a, align 4 1268 br label %for.end 1269 1270for.end: ; preds = %for.cond.for.end_crit_edge, %entry 1271 %call = tail call i32 (ptr) @varfunc(ptr null) 1272 ret i32 0 1273} 1274 1275declare i32 @varfunc(ptr nocapture readonly) 1276 1277@sum1 = external hidden thread_local global i32, align 4 1278 1279 1280; Function Attrs: nounwind 1281; Make sure the TLS call used to access @sum1 happens after the prologue 1282; and before the epilogue. 1283; TLS calls used to be wrongly model and shrink-wrapping would have inserted 1284; the prologue and epilogue just around the call to doSomething. 1285; PR25820. 1286define i32 @tlsCall(i1 %bool1, i32 %arg, ptr readonly dereferenceable(4) %sum1) #3 { 1287; ENABLE-LABEL: tlsCall: 1288; ENABLE: ## %bb.0: ## %entry 1289; ENABLE-NEXT: pushq %rax 1290; ENABLE-NEXT: testb $1, %dil 1291; ENABLE-NEXT: je LBB15_2 1292; ENABLE-NEXT: ## %bb.1: ## %main 1293; ENABLE-NEXT: movl (%rdx), %ecx 1294; ENABLE-NEXT: movq _sum1@TLVP(%rip), %rdi 1295; ENABLE-NEXT: callq *(%rdi) 1296; ENABLE-NEXT: movl %ecx, (%rax) 1297; ENABLE-NEXT: jmp LBB15_3 1298; ENABLE-NEXT: LBB15_2: ## %else 1299; ENABLE-NEXT: xorl %edi, %edi 1300; ENABLE-NEXT: xorl %esi, %esi 1301; ENABLE-NEXT: callq _doSomething 1302; ENABLE-NEXT: movl %eax, %esi 1303; ENABLE-NEXT: LBB15_3: ## %exit 1304; ENABLE-NEXT: movl %esi, %eax 1305; ENABLE-NEXT: popq %rcx 1306; ENABLE-NEXT: retq 1307; 1308; DISABLE-LABEL: tlsCall: 1309; DISABLE: ## %bb.0: ## %entry 1310; DISABLE-NEXT: pushq %rax 1311; DISABLE-NEXT: testb $1, %dil 1312; DISABLE-NEXT: je LBB15_2 1313; DISABLE-NEXT: ## %bb.1: ## %main 1314; DISABLE-NEXT: movl (%rdx), %ecx 1315; DISABLE-NEXT: movq _sum1@TLVP(%rip), %rdi 1316; DISABLE-NEXT: callq *(%rdi) 1317; DISABLE-NEXT: movl %ecx, (%rax) 1318; DISABLE-NEXT: jmp LBB15_3 1319; DISABLE-NEXT: LBB15_2: ## %else 1320; DISABLE-NEXT: xorl %edi, %edi 1321; DISABLE-NEXT: xorl %esi, %esi 1322; DISABLE-NEXT: callq _doSomething 1323; DISABLE-NEXT: movl %eax, %esi 1324; DISABLE-NEXT: LBB15_3: ## %exit 1325; DISABLE-NEXT: movl %esi, %eax 1326; DISABLE-NEXT: popq %rcx 1327; DISABLE-NEXT: retq 1328entry: 1329 br i1 %bool1, label %main, label %else 1330 1331main: 1332 %tmp1 = load i32, ptr %sum1, align 4 1333 store i32 %tmp1, ptr @sum1, align 4 1334 br label %exit 1335 1336else: 1337 %call = call i32 @doSomething(i32 0, ptr null) 1338 br label %exit 1339 1340exit: 1341 %res = phi i32 [ %arg, %main], [ %call, %else ] 1342 ret i32 %res 1343} 1344 1345attributes #3 = { nounwind } 1346 1347@irreducibleCFGa = common global i32 0, align 4 1348@irreducibleCFGf = common global i8 0, align 1 1349@irreducibleCFGb = common global i32 0, align 4 1350 1351; Check that we do not run shrink-wrapping on irreducible CFGs until 1352; it is actually supported. 1353; At the moment, on those CFGs the loop information may be incorrect 1354; and since we use that information to do the placement, we may end up 1355; inserting the prologue/epilogue at incorrect places. 1356; PR25988. 1357; Make sure we emit missed optimization remarks for this. 1358; REMARKS: Pass: shrink-wrap 1359; REMARKS-NEXT: Name: UnsupportedIrreducibleCFG 1360; REMARKS-NEXT: Function: irreducibleCFG 1361; REMARKS-NEXT: Args: 1362; REMARKS-NEXT: - String: Irreducible CFGs are not supported yet 1363 1364define i32 @irreducibleCFG() #4 { 1365; ENABLE-LABEL: irreducibleCFG: 1366; ENABLE: ## %bb.0: ## %entry 1367; ENABLE-NEXT: pushq %rbp 1368; ENABLE-NEXT: .cfi_def_cfa_offset 16 1369; ENABLE-NEXT: .cfi_offset %rbp, -16 1370; ENABLE-NEXT: movq %rsp, %rbp 1371; ENABLE-NEXT: .cfi_def_cfa_register %rbp 1372; ENABLE-NEXT: pushq %rbx 1373; ENABLE-NEXT: pushq %rax 1374; ENABLE-NEXT: .cfi_offset %rbx, -24 1375; ENABLE-NEXT: movq _irreducibleCFGf@GOTPCREL(%rip), %rax 1376; ENABLE-NEXT: cmpb $0, (%rax) 1377; ENABLE-NEXT: je LBB16_2 1378; ENABLE-NEXT: .p2align 4 1379; ENABLE-NEXT: LBB16_1: ## %preheader 1380; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1381; ENABLE-NEXT: jmp LBB16_1 1382; ENABLE-NEXT: LBB16_2: ## %split 1383; ENABLE-NEXT: movq _irreducibleCFGb@GOTPCREL(%rip), %rax 1384; ENABLE-NEXT: cmpl $0, (%rax) 1385; ENABLE-NEXT: je LBB16_3 1386; ENABLE-NEXT: ## %bb.4: ## %for.body4.i 1387; ENABLE-NEXT: movq _irreducibleCFGa@GOTPCREL(%rip), %rax 1388; ENABLE-NEXT: movl (%rax), %edi 1389; ENABLE-NEXT: xorl %ebx, %ebx 1390; ENABLE-NEXT: xorl %eax, %eax 1391; ENABLE-NEXT: callq _something 1392; ENABLE-NEXT: jmp LBB16_5 1393; ENABLE-NEXT: LBB16_3: 1394; ENABLE-NEXT: xorl %ebx, %ebx 1395; ENABLE-NEXT: .p2align 4 1396; ENABLE-NEXT: LBB16_5: ## %for.inc 1397; ENABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1398; ENABLE-NEXT: incl %ebx 1399; ENABLE-NEXT: cmpl $7, %ebx 1400; ENABLE-NEXT: jl LBB16_5 1401; ENABLE-NEXT: ## %bb.6: ## %fn1.exit 1402; ENABLE-NEXT: xorl %eax, %eax 1403; ENABLE-NEXT: addq $8, %rsp 1404; ENABLE-NEXT: popq %rbx 1405; ENABLE-NEXT: popq %rbp 1406; ENABLE-NEXT: retq 1407; 1408; DISABLE-LABEL: irreducibleCFG: 1409; DISABLE: ## %bb.0: ## %entry 1410; DISABLE-NEXT: pushq %rbp 1411; DISABLE-NEXT: .cfi_def_cfa_offset 16 1412; DISABLE-NEXT: .cfi_offset %rbp, -16 1413; DISABLE-NEXT: movq %rsp, %rbp 1414; DISABLE-NEXT: .cfi_def_cfa_register %rbp 1415; DISABLE-NEXT: pushq %rbx 1416; DISABLE-NEXT: pushq %rax 1417; DISABLE-NEXT: .cfi_offset %rbx, -24 1418; DISABLE-NEXT: movq _irreducibleCFGf@GOTPCREL(%rip), %rax 1419; DISABLE-NEXT: cmpb $0, (%rax) 1420; DISABLE-NEXT: je LBB16_2 1421; DISABLE-NEXT: .p2align 4 1422; DISABLE-NEXT: LBB16_1: ## %preheader 1423; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1424; DISABLE-NEXT: jmp LBB16_1 1425; DISABLE-NEXT: LBB16_2: ## %split 1426; DISABLE-NEXT: movq _irreducibleCFGb@GOTPCREL(%rip), %rax 1427; DISABLE-NEXT: cmpl $0, (%rax) 1428; DISABLE-NEXT: je LBB16_3 1429; DISABLE-NEXT: ## %bb.4: ## %for.body4.i 1430; DISABLE-NEXT: movq _irreducibleCFGa@GOTPCREL(%rip), %rax 1431; DISABLE-NEXT: movl (%rax), %edi 1432; DISABLE-NEXT: xorl %ebx, %ebx 1433; DISABLE-NEXT: xorl %eax, %eax 1434; DISABLE-NEXT: callq _something 1435; DISABLE-NEXT: jmp LBB16_5 1436; DISABLE-NEXT: LBB16_3: 1437; DISABLE-NEXT: xorl %ebx, %ebx 1438; DISABLE-NEXT: .p2align 4 1439; DISABLE-NEXT: LBB16_5: ## %for.inc 1440; DISABLE-NEXT: ## =>This Inner Loop Header: Depth=1 1441; DISABLE-NEXT: incl %ebx 1442; DISABLE-NEXT: cmpl $7, %ebx 1443; DISABLE-NEXT: jl LBB16_5 1444; DISABLE-NEXT: ## %bb.6: ## %fn1.exit 1445; DISABLE-NEXT: xorl %eax, %eax 1446; DISABLE-NEXT: addq $8, %rsp 1447; DISABLE-NEXT: popq %rbx 1448; DISABLE-NEXT: popq %rbp 1449; DISABLE-NEXT: retq 1450entry: 1451 %i0 = load i32, ptr @irreducibleCFGa, align 4 1452 %.pr = load i8, ptr @irreducibleCFGf, align 1 1453 %bool = icmp eq i8 %.pr, 0 1454 br i1 %bool, label %split, label %preheader 1455 1456preheader: 1457 br label %preheader 1458 1459split: 1460 %i1 = load i32, ptr @irreducibleCFGb, align 4 1461 %tobool1.i = icmp ne i32 %i1, 0 1462 br i1 %tobool1.i, label %for.body4.i, label %for.cond8.i.preheader 1463 1464for.body4.i: 1465 %call.i = tail call i32 (...) @something(i32 %i0) 1466 br label %for.cond8 1467 1468for.cond8: 1469 %p1 = phi i32 [ %inc18.i, %for.inc ], [ 0, %for.body4.i ] 1470 %.pr1.pr = load i32, ptr @irreducibleCFGb, align 4 1471 br label %for.cond8.i.preheader 1472 1473for.cond8.i.preheader: 1474 %.pr1 = phi i32 [ %.pr1.pr, %for.cond8 ], [ %i1, %split ] 1475 %p13 = phi i32 [ %p1, %for.cond8 ], [ 0, %split ] 1476 br label %for.inc 1477 1478fn1.exit: 1479 ret i32 0 1480 1481for.inc: 1482 %inc18.i = add nuw nsw i32 %p13, 1 1483 %cmp = icmp slt i32 %inc18.i, 7 1484 br i1 %cmp, label %for.cond8, label %fn1.exit 1485} 1486 1487attributes #4 = { "frame-pointer"="all" } 1488 1489@x = external global i32, align 4 1490@y = external global i32, align 4 1491 1492; The post-dominator tree does not include the branch containing the infinite 1493; loop, which can occur into a misplacement of the restore block, if we're 1494; looking for the nearest common post-dominator of an "unreachable" block. 1495 1496define void @infiniteLoopNoSuccessor() #5 { 1497; ENABLE-LABEL: infiniteLoopNoSuccessor: 1498; ENABLE: ## %bb.0: 1499; ENABLE-NEXT: pushq %rbp 1500; ENABLE-NEXT: movq %rsp, %rbp 1501; ENABLE-NEXT: movq _x@GOTPCREL(%rip), %rax 1502; ENABLE-NEXT: cmpl $0, (%rax) 1503; ENABLE-NEXT: je LBB17_2 1504; ENABLE-NEXT: ## %bb.1: 1505; ENABLE-NEXT: movl $0, (%rax) 1506; ENABLE-NEXT: LBB17_2: 1507; ENABLE-NEXT: xorl %eax, %eax 1508; ENABLE-NEXT: callq _somethingElse 1509; ENABLE-NEXT: movq _y@GOTPCREL(%rip), %rax 1510; ENABLE-NEXT: cmpl $0, (%rax) 1511; ENABLE-NEXT: je LBB17_3 1512; ENABLE-NEXT: ## %bb.5: 1513; ENABLE-NEXT: popq %rbp 1514; ENABLE-NEXT: retq 1515; ENABLE-NEXT: LBB17_3: 1516; ENABLE-NEXT: xorl %eax, %eax 1517; ENABLE-NEXT: callq _something 1518; ENABLE-NEXT: .p2align 4 1519; ENABLE-NEXT: LBB17_4: ## =>This Inner Loop Header: Depth=1 1520; ENABLE-NEXT: xorl %eax, %eax 1521; ENABLE-NEXT: callq _somethingElse 1522; ENABLE-NEXT: jmp LBB17_4 1523; 1524; DISABLE-LABEL: infiniteLoopNoSuccessor: 1525; DISABLE: ## %bb.0: 1526; DISABLE-NEXT: pushq %rbp 1527; DISABLE-NEXT: movq %rsp, %rbp 1528; DISABLE-NEXT: movq _x@GOTPCREL(%rip), %rax 1529; DISABLE-NEXT: cmpl $0, (%rax) 1530; DISABLE-NEXT: je LBB17_2 1531; DISABLE-NEXT: ## %bb.1: 1532; DISABLE-NEXT: movl $0, (%rax) 1533; DISABLE-NEXT: LBB17_2: 1534; DISABLE-NEXT: xorl %eax, %eax 1535; DISABLE-NEXT: callq _somethingElse 1536; DISABLE-NEXT: movq _y@GOTPCREL(%rip), %rax 1537; DISABLE-NEXT: cmpl $0, (%rax) 1538; DISABLE-NEXT: je LBB17_3 1539; DISABLE-NEXT: ## %bb.5: 1540; DISABLE-NEXT: popq %rbp 1541; DISABLE-NEXT: retq 1542; DISABLE-NEXT: LBB17_3: 1543; DISABLE-NEXT: xorl %eax, %eax 1544; DISABLE-NEXT: callq _something 1545; DISABLE-NEXT: .p2align 4 1546; DISABLE-NEXT: LBB17_4: ## =>This Inner Loop Header: Depth=1 1547; DISABLE-NEXT: xorl %eax, %eax 1548; DISABLE-NEXT: callq _somethingElse 1549; DISABLE-NEXT: jmp LBB17_4 1550 %1 = load i32, ptr @x, align 4 1551 %2 = icmp ne i32 %1, 0 1552 br i1 %2, label %3, label %4 1553 1554; <label>:3: 1555 store i32 0, ptr @x, align 4 1556 br label %4 1557 1558; <label>:4: 1559 call void (...) @somethingElse() 1560 %5 = load i32, ptr @y, align 4 1561 %6 = icmp ne i32 %5, 0 1562 br i1 %6, label %10, label %7 1563 1564; <label>:7: 1565 %8 = call i32 (...) @something() 1566 br label %9 1567 1568; <label>:9: 1569 call void (...) @somethingElse() 1570 br label %9 1571 1572; <label>:10: 1573 ret void 1574} 1575 1576declare void @somethingElse(...) 1577 1578attributes #5 = { nounwind "frame-pointer"="non-leaf" } 1579