1; RUN: llc < %s -mtriple=x86_64-apple-darwin -mcpu=corei7 -disable-fp-elim | FileCheck %s
2;
3; Note: Print verbose stackmaps using -debug-only=stackmaps.
4
5; CHECK-LABEL:  .section  __LLVM_STACKMAPS,__llvm_stackmaps
6; CHECK-NEXT:  __LLVM_StackMaps:
7; CHECK-NEXT:   .long   0
8; Num LargeConstants
9; CHECK-NEXT:   .long   3
10; CHECK-NEXT:   .quad   2147483648
11; CHECK-NEXT:   .quad   4294967295
12; CHECK-NEXT:   .quad   4294967296
13; Num Callsites
14; CHECK-NEXT:   .long   18
15
16; Constant arguments
17;
18; CHECK-NEXT:   .quad   1
19; CHECK-NEXT:   .long   L{{.*}}-_constantargs
20; CHECK-NEXT:   .short  0
21; CHECK-NEXT:   .short  12
22; SmallConstant
23; CHECK-NEXT:   .byte   4
24; CHECK-NEXT:   .byte   8
25; CHECK-NEXT:   .short  0
26; CHECK-NEXT:   .long   -1
27; SmallConstant
28; CHECK-NEXT:   .byte   4
29; CHECK-NEXT:   .byte   8
30; CHECK-NEXT:   .short  0
31; CHECK-NEXT:   .long   -1
32; SmallConstant
33; CHECK-NEXT:   .byte   4
34; CHECK-NEXT:   .byte   8
35; CHECK-NEXT:   .short  0
36; CHECK-NEXT:   .long   65536
37; SmallConstant
38; CHECK-NEXT:   .byte   4
39; CHECK-NEXT:   .byte   8
40; CHECK-NEXT:   .short  0
41; CHECK-NEXT:   .long   2000000000
42; SmallConstant
43; CHECK-NEXT:   .byte   4
44; CHECK-NEXT:   .byte   8
45; CHECK-NEXT:   .short  0
46; CHECK-NEXT:   .long   2147483647
47; SmallConstant
48; CHECK-NEXT:   .byte   4
49; CHECK-NEXT:   .byte   8
50; CHECK-NEXT:   .short  0
51; CHECK-NEXT:   .long   -1
52; SmallConstant
53; CHECK-NEXT:   .byte   4
54; CHECK-NEXT:   .byte   8
55; CHECK-NEXT:   .short  0
56; CHECK-NEXT:   .long   -1
57; SmallConstant
58; CHECK-NEXT:   .byte   4
59; CHECK-NEXT:   .byte   8
60; CHECK-NEXT:   .short  0
61; CHECK-NEXT:   .long   0
62; LargeConstant at index 0
63; CHECK-NEXT:   .byte   5
64; CHECK-NEXT:   .byte   8
65; CHECK-NEXT:   .short  0
66; CHECK-NEXT:   .long   0
67; LargeConstant at index 1
68; CHECK-NEXT:   .byte   5
69; CHECK-NEXT:   .byte   8
70; CHECK-NEXT:   .short  0
71; CHECK-NEXT:   .long   1
72; LargeConstant at index 2
73; CHECK-NEXT:   .byte   5
74; CHECK-NEXT:   .byte   8
75; CHECK-NEXT:   .short  0
76; CHECK-NEXT:   .long   2
77; SmallConstant
78; CHECK-NEXT:   .byte   4
79; CHECK-NEXT:   .byte   8
80; CHECK-NEXT:   .short  0
81; CHECK-NEXT:   .long   -1
82
83define void @constantargs() {
84entry:
85  %0 = inttoptr i64 12345 to i8*
86  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 1, i32 15, i8* %0, i32 0, i16 65535, i16 -1, i32 65536, i32 2000000000, i32 2147483647, i32 -1, i32 4294967295, i32 4294967296, i64 2147483648, i64 4294967295, i64 4294967296, i64 -1)
87  ret void
88}
89
90; Inline OSR Exit
91;
92; CHECK-LABEL:  .long   L{{.*}}-_osrinline
93; CHECK-NEXT:   .short  0
94; CHECK-NEXT:   .short  2
95; CHECK-NEXT:   .byte   1
96; CHECK-NEXT:   .byte   8
97; CHECK-NEXT:   .short  {{[0-9]+}}
98; CHECK-NEXT:   .long   0
99; CHECK-NEXT:   .byte   1
100; CHECK-NEXT:   .byte   8
101; CHECK-NEXT:   .short  {{[0-9]+}}
102; CHECK-NEXT:   .long  0
103define void @osrinline(i64 %a, i64 %b) {
104entry:
105  ; Runtime void->void call.
106  call void inttoptr (i64 -559038737 to void ()*)()
107  ; Followed by inline OSR patchpoint with 12-byte shadow and 2 live vars.
108  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 3, i32 12, i64 %a, i64 %b)
109  ret void
110}
111
112; Cold OSR Exit
113;
114; 2 live variables in register.
115;
116; CHECK-LABEL:  .long   L{{.*}}-_osrcold
117; CHECK-NEXT:   .short  0
118; CHECK-NEXT:   .short  2
119; CHECK-NEXT:   .byte   1
120; CHECK-NEXT:   .byte   8
121; CHECK-NEXT:   .short  {{[0-9]+}}
122; CHECK-NEXT:   .long   0
123; CHECK-NEXT:   .byte   1
124; CHECK-NEXT:   .byte   8
125; CHECK-NEXT:   .short  {{[0-9]+}}
126; CHECK-NEXT:   .long   0
127define void @osrcold(i64 %a, i64 %b) {
128entry:
129  %test = icmp slt i64 %a, %b
130  br i1 %test, label %ret, label %cold
131cold:
132  ; OSR patchpoint with 12-byte nop-slide and 2 live vars.
133  %thunk = inttoptr i64 -559038737 to i8*
134  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4, i32 15, i8* %thunk, i32 0, i64 %a, i64 %b)
135  unreachable
136ret:
137  ret void
138}
139
140; Property Read
141; CHECK-LABEL:  .long   L{{.*}}-_propertyRead
142; CHECK-NEXT:   .short  0
143; CHECK-NEXT:   .short  2
144; CHECK-NEXT:   .byte   1
145; CHECK-NEXT:   .byte   8
146; CHECK-NEXT:   .short  {{[0-9]+}}
147; CHECK-NEXT:   .long   0
148; CHECK-NEXT:   .byte   1
149; CHECK-NEXT:   .byte   8
150; CHECK-NEXT:   .short  {{[0-9]+}}
151; CHECK-NEXT:   .long   0
152define i64 @propertyRead(i64* %obj) {
153entry:
154  %resolveRead = inttoptr i64 -559038737 to i8*
155  %result = call anyregcc i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 5, i32 15, i8* %resolveRead, i32 1, i64* %obj)
156  %add = add i64 %result, 3
157  ret i64 %add
158}
159
160; Property Write
161; CHECK-LABEL:  .long   L{{.*}}-_propertyWrite
162; CHECK-NEXT:   .short  0
163; CHECK-NEXT:   .short  2
164; CHECK-NEXT:   .byte   1
165; CHECK-NEXT:   .byte   8
166; CHECK-NEXT:   .short  {{[0-9]+}}
167; CHECK-NEXT:   .long   0
168; CHECK-NEXT:   .byte   1
169; CHECK-NEXT:   .byte   8
170; CHECK-NEXT:   .short  {{[0-9]+}}
171; CHECK-NEXT:   .long   0
172define void @propertyWrite(i64 %dummy1, i64* %obj, i64 %dummy2, i64 %a) {
173entry:
174  %resolveWrite = inttoptr i64 -559038737 to i8*
175  call anyregcc void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 6, i32 15, i8* %resolveWrite, i32 2, i64* %obj, i64 %a)
176  ret void
177}
178
179; Void JS Call
180;
181; 2 live variables in registers.
182;
183; CHECK-LABEL:  .long   L{{.*}}-_jsVoidCall
184; CHECK-NEXT:   .short  0
185; CHECK-NEXT:   .short  2
186; CHECK-NEXT:   .byte   1
187; CHECK-NEXT:   .byte   8
188; CHECK-NEXT:   .short  {{[0-9]+}}
189; CHECK-NEXT:   .long   0
190; CHECK-NEXT:   .byte   1
191; CHECK-NEXT:   .byte   8
192; CHECK-NEXT:   .short  {{[0-9]+}}
193; CHECK-NEXT:   .long   0
194define void @jsVoidCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
195entry:
196  %resolveCall = inttoptr i64 -559038737 to i8*
197  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 7, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
198  ret void
199}
200
201; i64 JS Call
202;
203; 2 live variables in registers.
204;
205; CHECK-LABEL:  .long   L{{.*}}-_jsIntCall
206; CHECK-NEXT:   .short  0
207; CHECK-NEXT:   .short  2
208; CHECK-NEXT:   .byte   1
209; CHECK-NEXT:   .byte   8
210; CHECK-NEXT:   .short  {{[0-9]+}}
211; CHECK-NEXT:   .long   0
212; CHECK-NEXT:   .byte   1
213; CHECK-NEXT:   .byte   8
214; CHECK-NEXT:   .short  {{[0-9]+}}
215; CHECK-NEXT:   .long   0
216define i64 @jsIntCall(i64 %dummy1, i64* %obj, i64 %arg, i64 %l1, i64 %l2) {
217entry:
218  %resolveCall = inttoptr i64 -559038737 to i8*
219  %result = call i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 8, i32 15, i8* %resolveCall, i32 2, i64* %obj, i64 %arg, i64 %l1, i64 %l2)
220  %add = add i64 %result, 3
221  ret i64 %add
222}
223
224; Spilled stack map values.
225;
226; Verify 17 stack map entries.
227;
228; CHECK-LABEL:  .long L{{.*}}-_spilledValue
229; CHECK-NEXT:   .short 0
230; CHECK-NEXT:   .short 17
231;
232; Check that at least one is a spilled entry from RBP.
233; Location: Indirect RBP + ...
234; CHECK:        .byte 3
235; CHECK-NEXT:   .byte 8
236; CHECK-NEXT:   .short 6
237define void @spilledValue(i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16) {
238entry:
239  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 11, i32 15, i8* null, i32 5, i64 %arg0, i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16)
240  ret void
241}
242
243; Spilled stack map values.
244;
245; Verify 17 stack map entries.
246;
247; CHECK-LABEL:  .long L{{.*}}-_spilledStackMapValue
248; CHECK-NEXT:   .short 0
249; CHECK-NEXT:   .short 17
250;
251; Check that at least one is a spilled entry from RBP.
252; Location: Indirect RBP + ...
253; CHECK:        .byte 3
254; CHECK-NEXT:   .byte 8
255; CHECK-NEXT:   .short 6
256define webkit_jscc void @spilledStackMapValue(i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16) {
257entry:
258  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 12, i32 15, i64 %l0, i64 %l1, i64 %l2, i64 %l3, i64 %l4, i64 %l5, i64 %l6, i64 %l7, i64 %l8, i64 %l9, i64 %l10, i64 %l11, i64 %l12, i64 %l13, i64 %l14, i64 %l15, i64 %l16)
259  ret void
260}
261
262; Spill a subregister stackmap operand.
263;
264; CHECK-LABEL:  .long L{{.*}}-_spillSubReg
265; CHECK-NEXT:   .short 0
266; 4 locations
267; CHECK-NEXT:   .short 1
268;
269; Check that the subregister operand is a 4-byte spill.
270; Location: Indirect, 4-byte, RBP + ...
271; CHECK:        .byte 3
272; CHECK-NEXT:   .byte 4
273; CHECK-NEXT:   .short 6
274define void @spillSubReg(i64 %arg) #0 {
275bb:
276  br i1 undef, label %bb1, label %bb2
277
278bb1:
279  unreachable
280
281bb2:
282  %tmp = load i64* inttoptr (i64 140685446136880 to i64*)
283  br i1 undef, label %bb16, label %bb17
284
285bb16:
286  unreachable
287
288bb17:
289  %tmp32 = trunc i64 %tmp to i32
290  br i1 undef, label %bb60, label %bb61
291
292bb60:
293  tail call void asm sideeffect "nop", "~{ax},~{bx},~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
294  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 13, i32 5, i32 %tmp32)
295  unreachable
296
297bb61:
298  unreachable
299}
300
301; Map a single byte subregister. There is no DWARF register number, so
302; we expect the register to be encoded with the proper size and spill offset. We don't know which
303;
304; CHECK-LABEL:  .long L{{.*}}-_subRegOffset
305; CHECK-NEXT:   .short 0
306; 2 locations
307; CHECK-NEXT:   .short 2
308;
309; Check that the subregister operands are 1-byte spills.
310; Location 0: Register, 4-byte, AL
311; CHECK-NEXT:   .byte 1
312; CHECK-NEXT:   .byte 1
313; CHECK-NEXT:   .short 0
314; CHECK-NEXT:   .long 0
315;
316; Location 1: Register, 4-byte, BL
317; CHECK-NEXT:   .byte 1
318; CHECK-NEXT:   .byte 1
319; CHECK-NEXT:   .short 3
320; CHECK-NEXT:   .long 0
321define void @subRegOffset(i16 %arg) {
322  %v = mul i16 %arg, 5
323  %a0 = trunc i16 %v to i8
324  tail call void asm sideeffect "nop", "~{bx}"() nounwind
325  %arghi = lshr i16 %v, 8
326  %a1 = trunc i16 %arghi to i8
327  tail call void asm sideeffect "nop", "~{cx},~{dx},~{bp},~{si},~{di},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15}"() nounwind
328  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 14, i32 5, i8 %a0, i8 %a1)
329  ret void
330}
331
332; Map a constant value.
333;
334; CHECK-LABEL:  .long L{{.*}}-_liveConstant
335; CHECK-NEXT:   .short 0
336; 1 location
337; CHECK-NEXT:   .short 1
338; Loc 0: SmallConstant
339; CHECK-NEXT:   .byte   4
340; CHECK-NEXT:   .byte   8
341; CHECK-NEXT:   .short  0
342; CHECK-NEXT:   .long   33
343
344define void @liveConstant() {
345  tail call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 15, i32 5, i32 33)
346  ret void
347}
348
349; Directly map an alloca's address.
350;
351; Callsite 16
352; CHECK-LABEL:  .long L{{.*}}-_directFrameIdx
353; CHECK-NEXT:   .short 0
354; 1 location
355; CHECK-NEXT:   .short	1
356; Loc 0: Direct RBP - ofs
357; CHECK-NEXT:   .byte	2
358; CHECK-NEXT:   .byte	8
359; CHECK-NEXT:   .short	6
360; CHECK-NEXT:   .long
361
362; Callsite 17
363; CHECK-LABEL:  .long	L{{.*}}-_directFrameIdx
364; CHECK-NEXT:   .short	0
365; 2 locations
366; CHECK-NEXT:   .short	2
367; Loc 0: Direct RBP - ofs
368; CHECK-NEXT:   .byte	2
369; CHECK-NEXT:   .byte	8
370; CHECK-NEXT:   .short	6
371; CHECK-NEXT:   .long
372; Loc 1: Direct RBP - ofs
373; CHECK-NEXT:   .byte	2
374; CHECK-NEXT:   .byte	8
375; CHECK-NEXT:   .short	6
376; CHECK-NEXT:   .long
377define void @directFrameIdx() {
378entry:
379  %metadata1 = alloca i64, i32 3, align 8
380  store i64 11, i64* %metadata1
381  store i64 12, i64* %metadata1
382  store i64 13, i64* %metadata1
383  call void (i64, i32, ...)* @llvm.experimental.stackmap(i64 16, i32 0, i64* %metadata1)
384  %metadata2 = alloca i8, i32 4, align 8
385  %metadata3 = alloca i16, i32 4, align 8
386  call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 17, i32 5, i8* null, i32 0, i8* %metadata2, i16* %metadata3)
387  ret void
388}
389
390; Test a 64-bit ID.
391;
392; CHECK:        .quad 4294967295
393; CHECK-LABEL:  .long L{{.*}}-_longid
394; CHECK:        .quad 4294967296
395; CHECK-LABEL:  .long L{{.*}}-_longid
396; CHECK:        .quad 9223372036854775807
397; CHECK-LABEL:  .long L{{.*}}-_longid
398; CHECK:        .quad -1
399; CHECK-LABEL:  .long L{{.*}}-_longid
400define void @longid() {
401entry:
402  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967295, i32 0, i8* null, i32 0)
403  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 4294967296, i32 0, i8* null, i32 0)
404  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 9223372036854775807, i32 0, i8* null, i32 0)
405  tail call void (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.void(i64 -1, i32 0, i8* null, i32 0)
406  ret void
407}
408
409declare void @llvm.experimental.stackmap(i64, i32, ...)
410declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
411declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
412