xref: /llvm-project/llvm/test/CodeGen/X86/x86-win64-shrink-wrapping.ll (revision 6e1a7ac53163c335868d5773b1b35b55828f329c)
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