1 ; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=CHECK --check-prefix=ENABLE 2 ; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=CHECK --check-prefix=DISABLE 3 4 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 5 target triple = "x86_64--windows-gnu" 6 7 ; The output of this function with or without shrink-wrapping 8 ; shouldn't change. 9 ; Indeed, the epilogue block would have been if.else, meaning 10 ; after the pops, we will have additional instruction (jump, mov, 11 ; etc.) prior to the return and this is forbidden for Win64. 12 ; CHECK-LABEL: loopInfoSaveOutsideLoop: 13 ; CHECK: push 14 ; CHECK-NOT: popq 15 ; CHECK: popq 16 ; CHECK-NOT: popq 17 ; CHECK-NEXT: retq 18 define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) #0 { 19 entry: 20 %tobool = icmp eq i32 %cond, 0 21 br i1 %tobool, label %if.else, label %for.preheader 22 23 for.preheader: ; preds = %entry 24 tail call void asm "nop", ""() 25 br label %for.body 26 27 for.body: ; preds = %for.body, %for.preheader 28 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 29 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 30 %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() 31 %add = add nsw i32 %call, %sum.04 32 %inc = add nuw nsw i32 %i.05, 1 33 %exitcond = icmp eq i32 %inc, 10 34 br i1 %exitcond, label %for.end, label %for.body 35 36 for.end: ; preds = %for.body 37 tail call void asm "nop", "~{ebx}"() 38 %shl = shl i32 %add, 3 39 br label %if.end 40 41 if.else: ; preds = %entry 42 %mul = shl nsw i32 %N, 1 43 br label %if.end 44 45 if.end: ; preds = %if.else, %for.end 46 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 47 ret i32 %sum.1 48 } 49 50 ; When we can sink the epilogue of the function into an existing exit block, 51 ; this is Ok for shrink-wrapping to kicks in. 52 ; CHECK-LABEL: loopInfoSaveOutsideLoop2: 53 ; ENABLE: testl %ecx, %ecx 54 ; ENABLE-NEXT: je [[ELSE_LABEL:.LBB[0-9_]+]] 55 ; 56 ; Prologue code. 57 ; Make sure we save the CSR used in the inline asm: rbx. 58 ; CHECK: pushq %rbx 59 ; 60 ; DISABLE: testl %ecx, %ecx 61 ; DISABLE-NEXT: je [[ELSE_LABEL:.LBB[0-9_]+]] 62 ; 63 ; CHECK: nop 64 ; CHECK: xorl [[SUM:%eax]], [[SUM]] 65 ; CHECK-NEXT: movl $10, [[IV:%e[a-z]+]] 66 ; 67 ; CHECK: [[LOOP_LABEL:.LBB[0-9_]+]]: # %for.body 68 ; CHECK: movl $1, [[TMP:%e[a-z]+]] 69 ; CHECK: addl [[TMP]], [[SUM]] 70 ; CHECK-NEXT: decl [[IV]] 71 ; CHECK-NEXT: jne [[LOOP_LABEL]] 72 ; Next BB. 73 ; CHECK: nop 74 ; CHECK: shll $3, [[SUM]] 75 ; 76 ; DISABLE: jmp [[EPILOG_BB:.LBB[0-9_]+]] 77 ; 78 ; ENABLE-NEXT: popq %rbx 79 ; ENABLE-NEXT: retq 80 ; 81 ; CHECK: [[ELSE_LABEL]]: # %if.else 82 ; Shift second argument by one and store into returned register. 83 ; CHECK: addl %edx, %edx 84 ; CHECK: movl %edx, %eax 85 ; 86 ; DISABLE: [[EPILOG_BB]]: # %if.end 87 ; DISABLE-NEXT: popq %rbx 88 ; 89 ; CHECK: retq 90 ; 91 define i32 @loopInfoSaveOutsideLoop2(i32 %cond, i32 %N) #0 { 92 entry: 93 %tobool = icmp eq i32 %cond, 0 94 br i1 %tobool, label %if.else, label %for.preheader 95 96 for.preheader: ; preds = %entry 97 tail call void asm "nop", ""() 98 br label %for.body 99 100 for.body: ; preds = %for.body, %for.preheader 101 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 102 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 103 %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() 104 %add = add nsw i32 %call, %sum.04 105 %inc = add nuw nsw i32 %i.05, 1 106 %exitcond = icmp eq i32 %inc, 10 107 br i1 %exitcond, label %for.end, label %for.body 108 109 for.end: ; preds = %for.body 110 tail call void asm "nop", "~{ebx}"() 111 %shl = shl i32 %add, 3 112 ret i32 %shl 113 114 if.else: ; preds = %entry 115 %mul = shl nsw i32 %N, 1 116 br label %if.end 117 118 if.end: ; preds = %if.else, %for.end 119 ret i32 %mul 120 } 121 122 attributes #0 = { uwtable } 123