1; RUN: llc %s -o - | FileCheck %s
2;
3; Note: This test cannot be merged with the shrink-wrapping tests
4; because the booleans set on the command line take precedence on
5; the target logic that disable shrink-wrapping.
6target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
7target triple = "x86_64-apple-macosx"
8
9
10; This test checks that we do not use shrink-wrapping when
11; the function does not have any frame pointer and may unwind.
12; This is a workaround for a limitation in the emission of
13; the CFI directives, that are not correct in such case.
14; PR25614
15;
16; No shrink-wrapping should occur here, until the CFI information are fixed.
17; CHECK-LABEL: framelessUnwind:
18;
19; Prologue code.
20; (What we push does not matter. It should be some random sratch register.)
21; CHECK: pushq
22;
23; Compare the arguments and jump to exit.
24; After the prologue is set.
25; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
26; CHECK-NEXT: cmpl %esi, [[ARG0CPY]]
27; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
28;
29; Store %a in the alloca.
30; CHECK: movl [[ARG0CPY]], 4(%rsp)
31; Set the alloca address in the second argument.
32; CHECK-NEXT: leaq 4(%rsp), %rsi
33; Set the first argument to zero.
34; CHECK-NEXT: xorl %edi, %edi
35; CHECK-NEXT: callq _doSomething
36;
37; CHECK: [[EXIT_LABEL]]:
38;
39; Without shrink-wrapping, epilogue is in the exit block.
40; Epilogue code. (What we pop does not matter.)
41; CHECK-NEXT: popq
42;
43; CHECK-NEXT: retq
44define i32 @framelessUnwind(i32 %a, i32 %b) #0 {
45  %tmp = alloca i32, align 4
46  %tmp2 = icmp slt i32 %a, %b
47  br i1 %tmp2, label %true, label %false
48
49true:
50  store i32 %a, i32* %tmp, align 4
51  %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
52  br label %false
53
54false:
55  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
56  ret i32 %tmp.0
57}
58
59declare i32 @doSomething(i32, i32*)
60
61attributes #0 = { "no-frame-pointer-elim"="false" }
62
63; Shrink-wrapping should occur here. We have a frame pointer.
64; CHECK-LABEL: frameUnwind:
65;
66; Compare the arguments and jump to exit.
67; No prologue needed.
68;
69; Compare the arguments and jump to exit.
70; After the prologue is set.
71; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
72; CHECK-NEXT: cmpl %esi, [[ARG0CPY]]
73; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
74;
75; Prologue code.
76; CHECK: pushq %rbp
77; CHECK: movq %rsp, %rbp
78;
79; Store %a in the alloca.
80; CHECK: movl [[ARG0CPY]], -4(%rbp)
81; Set the alloca address in the second argument.
82; CHECK-NEXT: leaq -4(%rbp), %rsi
83; Set the first argument to zero.
84; CHECK-NEXT: xorl %edi, %edi
85; CHECK-NEXT: callq _doSomething
86;
87; Epilogue code. (What we pop does not matter.)
88; CHECK: popq %rbp
89;
90; CHECK: [[EXIT_LABEL]]:
91; CHECK-NEXT: retq
92define i32 @frameUnwind(i32 %a, i32 %b) #1 {
93  %tmp = alloca i32, align 4
94  %tmp2 = icmp slt i32 %a, %b
95  br i1 %tmp2, label %true, label %false
96
97true:
98  store i32 %a, i32* %tmp, align 4
99  %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
100  br label %false
101
102false:
103  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
104  ret i32 %tmp.0
105}
106
107attributes #1 = { "no-frame-pointer-elim"="true" }
108
109; Shrink-wrapping should occur here. We do not have to unwind.
110; CHECK-LABEL: framelessnoUnwind:
111;
112; Compare the arguments and jump to exit.
113; No prologue needed.
114;
115; Compare the arguments and jump to exit.
116; After the prologue is set.
117; CHECK: movl %edi, [[ARG0CPY:%e[a-z]+]]
118; CHECK-NEXT: cmpl %esi, [[ARG0CPY]]
119; CHECK-NEXT: jge [[EXIT_LABEL:LBB[0-9_]+]]
120;
121; Prologue code.
122; (What we push does not matter. It should be some random sratch register.)
123; CHECK: pushq
124;
125; Store %a in the alloca.
126; CHECK: movl [[ARG0CPY]], 4(%rsp)
127; Set the alloca address in the second argument.
128; CHECK-NEXT: leaq 4(%rsp), %rsi
129; Set the first argument to zero.
130; CHECK-NEXT: xorl %edi, %edi
131; CHECK-NEXT: callq _doSomething
132;
133; Epilogue code.
134; CHECK-NEXT: addq
135;
136; CHECK: [[EXIT_LABEL]]:
137; CHECK-NEXT: retq
138define i32 @framelessnoUnwind(i32 %a, i32 %b) #2 {
139  %tmp = alloca i32, align 4
140  %tmp2 = icmp slt i32 %a, %b
141  br i1 %tmp2, label %true, label %false
142
143true:
144  store i32 %a, i32* %tmp, align 4
145  %tmp4 = call i32 @doSomething(i32 0, i32* %tmp)
146  br label %false
147
148false:
149  %tmp.0 = phi i32 [ %tmp4, %true ], [ %a, %0 ]
150  ret i32 %tmp.0
151}
152
153attributes #2 = { "no-frame-pointer-elim"="false" nounwind }
154
155
156; Check that we generate correct code for segmented stack.
157; We used to emit the code at the entry point of the function
158; instead of just before the prologue.
159; For now, shrink-wrapping is disabled on segmented stack functions: PR26107.
160;
161; CHECK-LABEL: segmentedStack:
162; CHECK: cmpq
163; CHECK-NEXT: ja [[ENTRY_LABEL:LBB[0-9_]+]]
164;
165; CHECK: callq ___morestack
166; CHECK-NEXT: retq
167;
168; CHECK: [[ENTRY_LABEL]]:
169; Prologue
170; CHECK: push
171;
172; In PR26107, we use to drop these two basic blocks, because
173; the segmentedStack entry block was jumping directly to
174; the place where the prologue is actually needed, which is
175; the call to memcmp.
176; Then, those two basic blocks did not have any predecessors
177; anymore and were removed.
178;
179; Check if vk1 is null
180; CHECK: testq %rdi, %rdi
181; CHECK-NEXT: je [[STRINGS_EQUAL:LBB[0-9_]+]]
182;
183; Check if vk2 is null
184; CHECK: testq %rsi, %rsi
185; CHECK-NEXT:  je [[STRINGS_EQUAL]]
186;
187; CHECK: [[STRINGS_EQUAL]]
188; CHECK: popq
189define zeroext i1 @segmentedStack(i8* readonly %vk1, i8* readonly %vk2, i64 %key_size) #5 {
190entry:
191  %cmp.i = icmp eq i8* %vk1, null
192  %cmp1.i = icmp eq i8* %vk2, null
193  %brmerge.i = or i1 %cmp.i, %cmp1.i
194  %cmp1.mux.i = and i1 %cmp.i, %cmp1.i
195  br i1 %brmerge.i, label %__go_ptr_strings_equal.exit, label %if.end4.i
196
197if.end4.i:                                        ; preds = %entry
198  %tmp = getelementptr inbounds i8, i8* %vk1, i64 8
199  %tmp1 = bitcast i8* %tmp to i64*
200  %tmp2 = load i64, i64* %tmp1, align 8
201  %tmp3 = getelementptr inbounds i8, i8* %vk2, i64 8
202  %tmp4 = bitcast i8* %tmp3 to i64*
203  %tmp5 = load i64, i64* %tmp4, align 8
204  %cmp.i.i = icmp eq i64 %tmp2, %tmp5
205  br i1 %cmp.i.i, label %land.rhs.i.i, label %__go_ptr_strings_equal.exit
206
207land.rhs.i.i:                                     ; preds = %if.end4.i
208  %tmp6 = bitcast i8* %vk2 to i8**
209  %tmp7 = load i8*, i8** %tmp6, align 8
210  %tmp8 = bitcast i8* %vk1 to i8**
211  %tmp9 = load i8*, i8** %tmp8, align 8
212  %call.i.i = tail call i32 @memcmp(i8* %tmp9, i8* %tmp7, i64 %tmp2) #5
213  %cmp4.i.i = icmp eq i32 %call.i.i, 0
214  br label %__go_ptr_strings_equal.exit
215
216__go_ptr_strings_equal.exit:                      ; preds = %land.rhs.i.i, %if.end4.i, %entry
217  %retval.0.i = phi i1 [ %cmp1.mux.i, %entry ], [ false, %if.end4.i ], [ %cmp4.i.i, %land.rhs.i.i ]
218  ret i1 %retval.0.i
219}
220
221; Function Attrs: nounwind readonly
222declare i32 @memcmp(i8* nocapture, i8* nocapture, i64) #5
223
224attributes #5 = { nounwind readonly ssp uwtable "split-stack" }
225