1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 2; RUN: llc %s -o - -enable-shrink-wrap=true | FileCheck %s --check-prefix=ENABLE 3; RUN: llc %s -o - -enable-shrink-wrap=false | FileCheck %s --check-prefix=DISABLE 4 5target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" 6target triple = "x86_64--windows-gnu" 7 8; The output of this function with or without shrink-wrapping 9; shouldn't change. 10; Indeed, the epilogue block would have been if.else, meaning 11; after the pops, we will have additional instruction (jump, mov, 12; etc.) prior to the return and this is forbidden for Win64. 13define i32 @loopInfoSaveOutsideLoop(i32 %cond, i32 %N) #0 { 14; ENABLE-LABEL: loopInfoSaveOutsideLoop: 15; ENABLE: # %bb.0: # %entry 16; ENABLE-NEXT: pushq %rbx 17; ENABLE-NEXT: .seh_pushreg %rbx 18; ENABLE-NEXT: .seh_endprologue 19; ENABLE-NEXT: testl %ecx, %ecx 20; ENABLE-NEXT: je .LBB0_5 21; ENABLE-NEXT: # %bb.1: # %for.preheader 22; ENABLE-NEXT: #APP 23; ENABLE-NEXT: nop 24; ENABLE-NEXT: #NO_APP 25; ENABLE-NEXT: xorl %eax, %eax 26; ENABLE-NEXT: movl $10, %ecx 27; ENABLE-NEXT: #APP 28; ENABLE-NEXT: movl $1, %edx 29; ENABLE-NEXT: #NO_APP 30; ENABLE-NEXT: .p2align 4 31; ENABLE-NEXT: .LBB0_2: # %for.body 32; ENABLE-NEXT: # =>This Inner Loop Header: Depth=1 33; ENABLE-NEXT: addl %edx, %eax 34; ENABLE-NEXT: decl %ecx 35; ENABLE-NEXT: jne .LBB0_2 36; ENABLE-NEXT: # %bb.3: # %for.end 37; ENABLE-NEXT: #APP 38; ENABLE-NEXT: nop 39; ENABLE-NEXT: #NO_APP 40; ENABLE-NEXT: shll $3, %eax 41; ENABLE-NEXT: popq %rbx 42; ENABLE-NEXT: retq 43; ENABLE-NEXT: .LBB0_5: # %if.else 44; ENABLE-NEXT: movl %edx, %eax 45; ENABLE-NEXT: addl %edx, %eax 46; ENABLE-NEXT: popq %rbx 47; ENABLE-NEXT: retq 48; ENABLE-NEXT: .seh_endproc 49; 50; DISABLE-LABEL: loopInfoSaveOutsideLoop: 51; DISABLE: # %bb.0: # %entry 52; DISABLE-NEXT: pushq %rbx 53; DISABLE-NEXT: .seh_pushreg %rbx 54; DISABLE-NEXT: .seh_endprologue 55; DISABLE-NEXT: testl %ecx, %ecx 56; DISABLE-NEXT: je .LBB0_5 57; DISABLE-NEXT: # %bb.1: # %for.preheader 58; DISABLE-NEXT: #APP 59; DISABLE-NEXT: nop 60; DISABLE-NEXT: #NO_APP 61; DISABLE-NEXT: xorl %eax, %eax 62; DISABLE-NEXT: movl $10, %ecx 63; DISABLE-NEXT: #APP 64; DISABLE-NEXT: movl $1, %edx 65; DISABLE-NEXT: #NO_APP 66; DISABLE-NEXT: .p2align 4 67; DISABLE-NEXT: .LBB0_2: # %for.body 68; DISABLE-NEXT: # =>This Inner Loop Header: Depth=1 69; DISABLE-NEXT: addl %edx, %eax 70; DISABLE-NEXT: decl %ecx 71; DISABLE-NEXT: jne .LBB0_2 72; DISABLE-NEXT: # %bb.3: # %for.end 73; DISABLE-NEXT: #APP 74; DISABLE-NEXT: nop 75; DISABLE-NEXT: #NO_APP 76; DISABLE-NEXT: shll $3, %eax 77; DISABLE-NEXT: popq %rbx 78; DISABLE-NEXT: retq 79; DISABLE-NEXT: .LBB0_5: # %if.else 80; DISABLE-NEXT: movl %edx, %eax 81; DISABLE-NEXT: addl %edx, %eax 82; DISABLE-NEXT: popq %rbx 83; DISABLE-NEXT: retq 84; DISABLE-NEXT: .seh_endproc 85entry: 86 %tobool = icmp eq i32 %cond, 0 87 br i1 %tobool, label %if.else, label %for.preheader 88 89for.preheader: ; preds = %entry 90 tail call void asm "nop", ""() 91 br label %for.body 92 93for.body: ; preds = %for.body, %for.preheader 94 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 95 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 96 %call = tail call i32 asm "movl $$1, $0", "=r,~{ebx}"() 97 %add = add nsw i32 %call, %sum.04 98 %inc = add nuw nsw i32 %i.05, 1 99 %exitcond = icmp eq i32 %inc, 10 100 br i1 %exitcond, label %for.end, label %for.body 101 102for.end: ; preds = %for.body 103 tail call void asm "nop", "~{ebx}"() 104 %shl = shl i32 %add, 3 105 br label %if.end 106 107if.else: ; preds = %entry 108 %mul = shl nsw i32 %N, 1 109 br label %if.end 110 111if.end: ; preds = %if.else, %for.end 112 %sum.1 = phi i32 [ %shl, %for.end ], [ %mul, %if.else ] 113 ret i32 %sum.1 114} 115 116; When we can sink the epilogue of the function into an existing exit block, 117; this is Ok for shrink-wrapping to kicks in. 118define i32 @loopInfoSaveOutsideLoop2(i32 %cond, i32 %N) #0 { 119; ENABLE-LABEL: loopInfoSaveOutsideLoop2: 120; ENABLE: # %bb.0: # %entry 121; ENABLE-NEXT: testl %ecx, %ecx 122; ENABLE-NEXT: je .LBB1_4 123; ENABLE-NEXT: # %bb.1: # %for.preheader 124; ENABLE-NEXT: pushq %rbx 125; ENABLE-NEXT: .seh_pushreg %rbx 126; ENABLE-NEXT: .seh_endprologue 127; ENABLE-NEXT: #APP 128; ENABLE-NEXT: nop 129; ENABLE-NEXT: #NO_APP 130; ENABLE-NEXT: xorl %eax, %eax 131; ENABLE-NEXT: movl $10, %ecx 132; ENABLE-NEXT: .p2align 4 133; ENABLE-NEXT: .LBB1_2: # %for.body 134; ENABLE-NEXT: # =>This Inner Loop Header: Depth=1 135; ENABLE-NEXT: #APP 136; ENABLE-NEXT: movl $1, %edx 137; ENABLE-NEXT: #NO_APP 138; ENABLE-NEXT: addl %edx, %eax 139; ENABLE-NEXT: decl %ecx 140; ENABLE-NEXT: jne .LBB1_2 141; ENABLE-NEXT: # %bb.3: # %for.end 142; ENABLE-NEXT: #APP 143; ENABLE-NEXT: nop 144; ENABLE-NEXT: #NO_APP 145; ENABLE-NEXT: shll $3, %eax 146; ENABLE-NEXT: popq %rbx 147; ENABLE-NEXT: retq 148; ENABLE-NEXT: .LBB1_4: # %if.else 149; ENABLE-NEXT: addl %edx, %edx 150; ENABLE-NEXT: movl %edx, %eax 151; ENABLE-NEXT: retq 152; ENABLE-NEXT: .seh_endproc 153; 154; DISABLE-LABEL: loopInfoSaveOutsideLoop2: 155; DISABLE: # %bb.0: # %entry 156; DISABLE-NEXT: pushq %rbx 157; DISABLE-NEXT: .seh_pushreg %rbx 158; DISABLE-NEXT: .seh_endprologue 159; DISABLE-NEXT: testl %ecx, %ecx 160; DISABLE-NEXT: je .LBB1_5 161; DISABLE-NEXT: # %bb.1: # %for.preheader 162; DISABLE-NEXT: #APP 163; DISABLE-NEXT: nop 164; DISABLE-NEXT: #NO_APP 165; DISABLE-NEXT: xorl %eax, %eax 166; DISABLE-NEXT: movl $10, %ecx 167; DISABLE-NEXT: .p2align 4 168; DISABLE-NEXT: .LBB1_2: # %for.body 169; DISABLE-NEXT: # =>This Inner Loop Header: Depth=1 170; DISABLE-NEXT: #APP 171; DISABLE-NEXT: movl $1, %edx 172; DISABLE-NEXT: #NO_APP 173; DISABLE-NEXT: addl %edx, %eax 174; DISABLE-NEXT: decl %ecx 175; DISABLE-NEXT: jne .LBB1_2 176; DISABLE-NEXT: # %bb.3: # %for.end 177; DISABLE-NEXT: #APP 178; DISABLE-NEXT: nop 179; DISABLE-NEXT: #NO_APP 180; DISABLE-NEXT: shll $3, %eax 181; DISABLE-NEXT: popq %rbx 182; DISABLE-NEXT: retq 183; DISABLE-NEXT: .LBB1_5: # %if.else 184; DISABLE-NEXT: addl %edx, %edx 185; DISABLE-NEXT: movl %edx, %eax 186; DISABLE-NEXT: popq %rbx 187; DISABLE-NEXT: retq 188; DISABLE-NEXT: .seh_endproc 189entry: 190 %tobool = icmp eq i32 %cond, 0 191 br i1 %tobool, label %if.else, label %for.preheader 192 193for.preheader: ; preds = %entry 194 tail call void asm "nop", ""() 195 br label %for.body 196 197for.body: ; preds = %for.body, %for.preheader 198 %i.05 = phi i32 [ %inc, %for.body ], [ 0, %for.preheader ] 199 %sum.04 = phi i32 [ %add, %for.body ], [ 0, %for.preheader ] 200 %call = tail call i32 asm sideeffect "movl $$1, $0", "=r,~{ebx}"() 201 %add = add nsw i32 %call, %sum.04 202 %inc = add nuw nsw i32 %i.05, 1 203 %exitcond = icmp eq i32 %inc, 10 204 br i1 %exitcond, label %for.end, label %for.body 205 206for.end: ; preds = %for.body 207 tail call void asm "nop", "~{ebx}"() 208 %shl = shl i32 %add, 3 209 ret i32 %shl 210 211if.else: ; preds = %entry 212 %mul = shl nsw i32 %N, 1 213 br label %if.end 214 215if.end: ; preds = %if.else, %for.end 216 ret i32 %mul 217} 218 219attributes #0 = { uwtable } 220