| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 |
| ; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=ENABLE |
| ; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=DISABLE |
| |
| target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" |
| target triple = "x86_64--windows-gnu" |
| |
| ; The output of this function with or without shrink-wrapping |
| ; shouldn't change. |
| ; Indeed, the epilogue block would have been if.else, meaning |
| ; after the pops, we will have additional instruction (jump, mov, |
| ; etc.) prior to the return and this is forbidden for Win64. |
| define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) #0 { |
| ; ENABLE-LABEL: loopInfoSaveOutsideLoop: |
| ; ENABLE: # %bb.0: # %entry |
| ; ENABLE-NEXT: pushq %rbx |
| ; ENABLE-NEXT: .seh_pushreg %rbx |
| ; ENABLE-NEXT: .seh_endprologue |
| ; ENABLE-NEXT: testl %ecx, %ecx |
| ; ENABLE-NEXT: je .LBB0_4 |
| ; ENABLE-NEXT: # %bb.1: # %for.preheader |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: nop |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: xorl %eax, %eax |
| ; ENABLE-NEXT: movl $10, %ecx |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: movl $1, %edx |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: .p2align 4, 0x90 |
| ; ENABLE-NEXT: .LBB0_2: # %for.body |
| ; ENABLE-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; ENABLE-NEXT: addl %edx, %eax |
| ; ENABLE-NEXT: decl %ecx |
| ; ENABLE-NEXT: jne .LBB0_2 |
| ; ENABLE-NEXT: # %bb.3: # %for.end |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: nop |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: shll $3, %eax |
| ; ENABLE-NEXT: jmp .LBB0_5 |
| ; ENABLE-NEXT: .LBB0_4: # %if.else |
| ; ENABLE-NEXT: movl %edx, %eax |
| ; ENABLE-NEXT: addl %edx, %eax |
| ; ENABLE-NEXT: .LBB0_5: # %if.end |
| ; ENABLE-NEXT: popq %rbx |
| ; ENABLE-NEXT: retq |
| ; ENABLE-NEXT: .seh_endproc |
| ; |
| ; DISABLE-LABEL: loopInfoSaveOutsideLoop: |
| ; DISABLE: # %bb.0: # %entry |
| ; DISABLE-NEXT: pushq %rbx |
| ; DISABLE-NEXT: .seh_pushreg %rbx |
| ; DISABLE-NEXT: .seh_endprologue |
| ; DISABLE-NEXT: testl %ecx, %ecx |
| ; DISABLE-NEXT: je .LBB0_4 |
| ; DISABLE-NEXT: # %bb.1: # %for.preheader |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: nop |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: xorl %eax, %eax |
| ; DISABLE-NEXT: movl $10, %ecx |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: movl $1, %edx |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: .p2align 4, 0x90 |
| ; DISABLE-NEXT: .LBB0_2: # %for.body |
| ; DISABLE-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; DISABLE-NEXT: addl %edx, %eax |
| ; DISABLE-NEXT: decl %ecx |
| ; DISABLE-NEXT: jne .LBB0_2 |
| ; DISABLE-NEXT: # %bb.3: # %for.end |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: nop |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: shll $3, %eax |
| ; DISABLE-NEXT: jmp .LBB0_5 |
| ; DISABLE-NEXT: .LBB0_4: # %if.else |
| ; DISABLE-NEXT: movl %edx, %eax |
| ; DISABLE-NEXT: addl %edx, %eax |
| ; DISABLE-NEXT: .LBB0_5: # %if.end |
| ; DISABLE-NEXT: popq %rbx |
| ; DISABLE-NEXT: retq |
| ; DISABLE-NEXT: .seh_endproc |
| entry: |
| %tobool = icmp eq i32 %cond, 0 |
| br i1 %tobool, label %if.else, label %for.preheader |
| |
| for.preheader: ; preds = %entry |
| tail call void asm "nop", ""() |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %for.preheader |
| %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] |
| %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] |
| %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() |
| %add = add nsw i32 %call, %sum.04 |
| %inc = add nuw nsw i32 %i.05, 1 |
| %exitcond = icmp eq i32 %inc, 10 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void asm "nop", "~{ebx}"() |
| %shl = shl i32 %add, 3 |
| br label %if.end |
| |
| if.else: ; preds = %entry |
| %mul = shl nsw i32 %N, 1 |
| br label %if.end |
| |
| if.end: ; preds = %if.else, %for.end |
| %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] |
| ret i32 %sum.1 |
| } |
| |
| ; When we can sink the epilogue of the function into an existing exit block, |
| ; this is Ok for shrink-wrapping to kicks in. |
| define i32 @loopInfoSaveOutsideLoop2(i32 %cond, i32 %N) #0 { |
| ; ENABLE-LABEL: loopInfoSaveOutsideLoop2: |
| ; ENABLE: # %bb.0: # %entry |
| ; ENABLE-NEXT: testl %ecx, %ecx |
| ; ENABLE-NEXT: je .LBB1_4 |
| ; ENABLE-NEXT: # %bb.1: # %for.preheader |
| ; ENABLE-NEXT: pushq %rbx |
| ; ENABLE-NEXT: .seh_pushreg %rbx |
| ; ENABLE-NEXT: .seh_endprologue |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: nop |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: xorl %eax, %eax |
| ; ENABLE-NEXT: movl $10, %ecx |
| ; ENABLE-NEXT: .p2align 4, 0x90 |
| ; ENABLE-NEXT: .LBB1_2: # %for.body |
| ; ENABLE-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: movl $1, %edx |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: addl %edx, %eax |
| ; ENABLE-NEXT: decl %ecx |
| ; ENABLE-NEXT: jne .LBB1_2 |
| ; ENABLE-NEXT: # %bb.3: # %for.end |
| ; ENABLE-NEXT: #APP |
| ; ENABLE-NEXT: nop |
| ; ENABLE-NEXT: #NO_APP |
| ; ENABLE-NEXT: shll $3, %eax |
| ; ENABLE-NEXT: popq %rbx |
| ; ENABLE-NEXT: retq |
| ; ENABLE-NEXT: .LBB1_4: # %if.else |
| ; ENABLE-NEXT: addl %edx, %edx |
| ; ENABLE-NEXT: movl %edx, %eax |
| ; ENABLE-NEXT: retq |
| ; ENABLE-NEXT: .seh_endproc |
| ; |
| ; DISABLE-LABEL: loopInfoSaveOutsideLoop2: |
| ; DISABLE: # %bb.0: # %entry |
| ; DISABLE-NEXT: pushq %rbx |
| ; DISABLE-NEXT: .seh_pushreg %rbx |
| ; DISABLE-NEXT: .seh_endprologue |
| ; DISABLE-NEXT: testl %ecx, %ecx |
| ; DISABLE-NEXT: je .LBB1_4 |
| ; DISABLE-NEXT: # %bb.1: # %for.preheader |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: nop |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: xorl %eax, %eax |
| ; DISABLE-NEXT: movl $10, %ecx |
| ; DISABLE-NEXT: .p2align 4, 0x90 |
| ; DISABLE-NEXT: .LBB1_2: # %for.body |
| ; DISABLE-NEXT: # =>This Inner Loop Header: Depth=1 |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: movl $1, %edx |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: addl %edx, %eax |
| ; DISABLE-NEXT: decl %ecx |
| ; DISABLE-NEXT: jne .LBB1_2 |
| ; DISABLE-NEXT: # %bb.3: # %for.end |
| ; DISABLE-NEXT: #APP |
| ; DISABLE-NEXT: nop |
| ; DISABLE-NEXT: #NO_APP |
| ; DISABLE-NEXT: shll $3, %eax |
| ; DISABLE-NEXT: jmp .LBB1_5 |
| ; DISABLE-NEXT: .LBB1_4: # %if.else |
| ; DISABLE-NEXT: addl %edx, %edx |
| ; DISABLE-NEXT: movl %edx, %eax |
| ; DISABLE-NEXT: .LBB1_5: # %if.end |
| ; DISABLE-NEXT: popq %rbx |
| ; DISABLE-NEXT: retq |
| ; DISABLE-NEXT: .seh_endproc |
| entry: |
| %tobool = icmp eq i32 %cond, 0 |
| br i1 %tobool, label %if.else, label %for.preheader |
| |
| for.preheader: ; preds = %entry |
| tail call void asm "nop", ""() |
| br label %for.body |
| |
| for.body: ; preds = %for.body, %for.preheader |
| %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] |
| %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] |
| %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() |
| %add = add nsw i32 %call, %sum.04 |
| %inc = add nuw nsw i32 %i.05, 1 |
| %exitcond = icmp eq i32 %inc, 10 |
| br i1 %exitcond, label %for.end, label %for.body |
| |
| for.end: ; preds = %for.body |
| tail call void asm "nop", "~{ebx}"() |
| %shl = shl i32 %add, 3 |
| ret i32 %shl |
| |
| if.else: ; preds = %entry |
| %mul = shl nsw i32 %N, 1 |
| br label %if.end |
| |
| if.end: ; preds = %if.else, %for.end |
| ret i32 %mul |
| } |
| |
| attributes #0 = { uwtable } |