1 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
2 ; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names < %s \
3 ; RUN: | FileCheck %s --check-prefixes=CHECK-S,CHECK-ALL
4 ; RUN: llc -verify-machineinstrs -target-abi=elfv2 -mtriple=powerpc64-- \
5 ; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names < %s \
6 ; RUN: | FileCheck %s --check-prefixes=CHECK-S,CHECK-ALL
7 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
8 ; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names < %s \
9 ; RUN: | FileCheck %s --check-prefixes=CHECK-P9,CHECK-ALL
11 @globalVar = common dso_local local_unnamed_addr global i32 0, align 4
12 @externGlobalVar = external local_unnamed_addr global i32, align 4
13 @indirectCall = common dso_local local_unnamed_addr global ptr null, align 8
15 ; This funcion needs to remain as noinline.
16 ; The compiler needs to know this function is local but must be forced to call
17 ; it. The only thing we really need to check here is that st_other=0 and
18 ; so we make sure that there is no .localentry.
19 define dso_local signext i32 @localCall(i32 signext %a) local_unnamed_addr #0 {
20 ; CHECK-ALL-LABEL: localCall:
21 ; CHECK-S-NOT: .localentry
22 ; CHECK-S: addi r3, r3, 5
23 ; CHECK-S-NEXT: extsw r3, r3
26 %add = add nsw i32 %a, 5
30 define dso_local signext i32 @DirectCallLocal1(i32 signext %a, i32 signext %b) local_unnamed_addr {
31 ; CHECK-ALL-LABEL: DirectCallLocal1:
32 ; CHECK-S: .localentry DirectCallLocal1
33 ; CHECK-S: # %bb.0: # %entry
34 ; CHECK-S-NEXT: mflr r0
35 ; CHECK-S-NEXT: std r0, 16(r1)
36 ; CHECK-S-NEXT: stdu r1, -32(r1)
37 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
38 ; CHECK-S-NEXT: .cfi_offset lr, 16
39 ; CHECK-S-NEXT: add r3, r4, r3
40 ; CHECK-S-NEXT: extsw r3, r3
41 ; CHECK-S-NEXT: bl localCall@notoc
42 ; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1
43 ; CHECK-S-NEXT: mullw r3, r4, r3
44 ; CHECK-S-NEXT: extsw r3, r3
45 ; CHECK-S-NEXT: addi r1, r1, 32
46 ; CHECK-S-NEXT: ld r0, 16(r1)
47 ; CHECK-S-NEXT: mtlr r0
50 %add = add nsw i32 %b, %a
51 %call = tail call signext i32 @localCall(i32 signext %add)
52 %0 = load i32, ptr @globalVar, align 4
53 %mul = mul nsw i32 %0, %call
57 define dso_local signext i32 @DirectCallLocal2(i32 signext %a, i32 signext %b) local_unnamed_addr {
58 ; CHECK-ALL-LABEL: DirectCallLocal2:
59 ; CHECK-S: .localentry DirectCallLocal2
60 ; CHECK-S: # %bb.0: # %entry
61 ; CHECK-S-NEXT: mflr r0
62 ; CHECK-S-NEXT: std r0, 16(r1)
63 ; CHECK-S-NEXT: stdu r1, -32(r1)
64 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
65 ; CHECK-S-NEXT: .cfi_offset lr, 16
66 ; CHECK-S-NEXT: add r3, r4, r3
67 ; CHECK-S-NEXT: extsw r3, r3
68 ; CHECK-S-NEXT: bl localCall@notoc
69 ; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1
70 ; CHECK-S-NEXT: .Lpcrel0:
71 ; CHECK-S-NEXT: .reloc .Lpcrel0-8,R_PPC64_PCREL_OPT,.-(.Lpcrel0-8)
72 ; CHECK-S-NEXT: lwz r4, 0(r4)
73 ; CHECK-S-NEXT: mullw r3, r4, r3
74 ; CHECK-S-NEXT: extsw r3, r3
75 ; CHECK-S-NEXT: addi r1, r1, 32
76 ; CHECK-S-NEXT: ld r0, 16(r1)
77 ; CHECK-S-NEXT: mtlr r0
80 %add = add nsw i32 %b, %a
81 %call = tail call signext i32 @localCall(i32 signext %add)
82 %0 = load i32, ptr @externGlobalVar, align 4
83 %mul = mul nsw i32 %0, %call
87 define dso_local signext i32 @DirectCallLocalNoGlobal(i32 signext %a, i32 signext %b) local_unnamed_addr {
88 ; CHECK-ALL-LABEL: DirectCallLocalNoGlobal:
89 ; CHECK-S: .localentry DirectCallLocalNoGlobal, 1
90 ; CHECK-S-NEXT: # %bb.0: # %entry
91 ; CHECK-S-NEXT: mflr r0
92 ; CHECK-S-NEXT: .cfi_def_cfa_offset 48
93 ; CHECK-S-NEXT: .cfi_offset lr, 16
94 ; CHECK-S-NEXT: .cfi_offset r30, -16
95 ; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill
96 ; CHECK-S-NEXT: std r0, 16(r1)
97 ; CHECK-S-NEXT: stdu r1, -48(r1)
98 ; CHECK-S-NEXT: mr r30, r4
99 ; CHECK-S-NEXT: bl localCall@notoc
100 ; CHECK-S-NEXT: add r3, r3, r30
101 ; CHECK-S-NEXT: extsw r3, r3
102 ; CHECK-S-NEXT: addi r1, r1, 48
103 ; CHECK-S-NEXT: ld r0, 16(r1)
104 ; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
105 ; CHECK-S-NEXT: mtlr r0
108 %call = tail call signext i32 @localCall(i32 signext %a)
109 %add = add nsw i32 %call, %b
113 define dso_local signext i32 @DirectCallExtern1(i32 signext %a, i32 signext %b) local_unnamed_addr {
114 ; CHECK-ALL-LABEL: DirectCallExtern1:
115 ; CHECK-S: .localentry DirectCallExtern1
116 ; CHECK-S: # %bb.0: # %entry
117 ; CHECK-S-NEXT: mflr r0
118 ; CHECK-S-NEXT: std r0, 16(r1)
119 ; CHECK-S-NEXT: stdu r1, -32(r1)
120 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
121 ; CHECK-S-NEXT: .cfi_offset lr, 16
122 ; CHECK-S-NEXT: add r3, r4, r3
123 ; CHECK-S-NEXT: extsw r3, r3
124 ; CHECK-S-NEXT: bl externCall@notoc
125 ; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1
126 ; CHECK-S-NEXT: mullw r3, r4, r3
127 ; CHECK-S-NEXT: extsw r3, r3
128 ; CHECK-S-NEXT: addi r1, r1, 32
129 ; CHECK-S-NEXT: ld r0, 16(r1)
130 ; CHECK-S-NEXT: mtlr r0
133 %add = add nsw i32 %b, %a
134 %call = tail call signext i32 @externCall(i32 signext %add)
135 %0 = load i32, ptr @globalVar, align 4
136 %mul = mul nsw i32 %0, %call
140 declare signext i32 @externCall(i32 signext) local_unnamed_addr
142 define dso_local signext i32 @DirectCallExtern2(i32 signext %a, i32 signext %b) local_unnamed_addr {
143 ; CHECK-ALL-LABEL: DirectCallExtern2:
144 ; CHECK-S: .localentry DirectCallExtern2
145 ; CHECK-S: # %bb.0: # %entry
146 ; CHECK-S-NEXT: mflr r0
147 ; CHECK-S-NEXT: std r0, 16(r1)
148 ; CHECK-S-NEXT: stdu r1, -32(r1)
149 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
150 ; CHECK-S-NEXT: .cfi_offset lr, 16
151 ; CHECK-S-NEXT: add r3, r4, r3
152 ; CHECK-S-NEXT: extsw r3, r3
153 ; CHECK-S-NEXT: bl externCall@notoc
154 ; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1
155 ; CHECK-S-NEXT: .Lpcrel1:
156 ; CHECK-S-NEXT: .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
157 ; CHECK-S-NEXT: lwz r4, 0(r4)
158 ; CHECK-S-NEXT: mullw r3, r4, r3
159 ; CHECK-S-NEXT: extsw r3, r3
160 ; CHECK-S-NEXT: addi r1, r1, 32
161 ; CHECK-S-NEXT: ld r0, 16(r1)
162 ; CHECK-S-NEXT: mtlr r0
165 %add = add nsw i32 %b, %a
166 %call = tail call signext i32 @externCall(i32 signext %add)
167 %0 = load i32, ptr @externGlobalVar, align 4
168 %mul = mul nsw i32 %0, %call
172 define dso_local signext i32 @DirectCallExternNoGlobal(i32 signext %a, i32 signext %b) local_unnamed_addr {
173 ; CHECK-ALL-LABEL: DirectCallExternNoGlobal:
174 ; CHECK-S: .localentry DirectCallExternNoGlobal, 1
175 ; CHECK-P9: .localentry DirectCallExternNoGlobal, .Lfunc_lep6-.Lfunc_gep6
176 ; CHECK-ALL: # %bb.0: # %entry
177 ; CHECK-S-NEXT: mflr r0
178 ; CHECK-S-NEXT: .cfi_def_cfa_offset 48
179 ; CHECK-S-NEXT: .cfi_offset lr, 16
180 ; CHECK-S-NEXT: .cfi_offset r30, -16
181 ; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill
182 ; CHECK-S-NEXT: std r0, 16(r1)
183 ; CHECK-S-NEXT: stdu r1, -48(r1)
184 ; CHECK-S-NEXT: mr r30, r4
185 ; CHECK-S-NEXT: bl externCall@notoc
186 ; CHECK-S-NEXT: add r3, r3, r30
187 ; CHECK-S-NEXT: extsw r3, r3
188 ; CHECK-S-NEXT: addi r1, r1, 48
189 ; CHECK-S-NEXT: ld r0, 16(r1)
190 ; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
191 ; CHECK-S-NEXT: mtlr r0
194 %call = tail call signext i32 @externCall(i32 signext %a)
195 %add = add nsw i32 %call, %b
199 define dso_local signext i32 @TailCallLocal1(i32 signext %a) local_unnamed_addr {
200 ; CHECK-ALL-LABEL: TailCallLocal1:
201 ; CHECK-S: .localentry TailCallLocal1
202 ; CHECK-S: # %bb.0: # %entry
203 ; CHECK-S: plwz r4, globalVar@PCREL(0), 1
204 ; CHECK-S-NEXT: add r3, r4, r3
205 ; CHECK-S-NEXT: extsw r3, r3
206 ; CHECK-S-NEXT: b localCall@notoc
208 %0 = load i32, ptr @globalVar, align 4
209 %add = add nsw i32 %0, %a
210 %call = tail call signext i32 @localCall(i32 signext %add)
214 define dso_local signext i32 @TailCallLocal2(i32 signext %a) local_unnamed_addr {
215 ; CHECK-ALL-LABEL: TailCallLocal2:
216 ; CHECK-S: .localentry TailCallLocal2
217 ; CHECK-S: # %bb.0: # %entry
218 ; CHECK-S: pld r4, externGlobalVar@got@pcrel(0), 1
219 ; CHECK-S-NEXT: .Lpcrel2:
220 ; CHECK-S-NEXT: .reloc .Lpcrel2-8,R_PPC64_PCREL_OPT,.-(.Lpcrel2-8)
221 ; CHECK-S-NEXT: lwz r4, 0(r4)
222 ; CHECK-S-NEXT: add r3, r4, r3
223 ; CHECK-S-NEXT: extsw r3, r3
224 ; CHECK-S-NEXT: b localCall@notoc
226 %0 = load i32, ptr @externGlobalVar, align 4
227 %add = add nsw i32 %0, %a
228 %call = tail call signext i32 @localCall(i32 signext %add)
232 define dso_local signext i32 @TailCallLocalNoGlobal(i32 signext %a) local_unnamed_addr {
233 ; CHECK-ALL-LABEL: TailCallLocalNoGlobal:
234 ; CHECK-S: .localentry TailCallLocalNoGlobal, 1
235 ; CHECK-P9: .localentry TailCallLocalNoGlobal, .Lfunc_lep9-.Lfunc_gep9
236 ; CHECK-ALL: # %bb.0: # %entry
237 ; CHECK-S: b localCall@notoc
239 %call = tail call signext i32 @localCall(i32 signext %a)
243 define dso_local signext i32 @TailCallExtern1(i32 signext %a) local_unnamed_addr {
244 ; CHECK-ALL-LABEL: TailCallExtern1:
245 ; CHECK-S: .localentry TailCallExtern1
246 ; CHECK-S: # %bb.0: # %entry
247 ; CHECK-S: plwz r4, globalVar@PCREL(0), 1
248 ; CHECK-S-NEXT: add r3, r4, r3
249 ; CHECK-S-NEXT: extsw r3, r3
250 ; CHECK-S-NEXT: b externCall@notoc
252 %0 = load i32, ptr @globalVar, align 4
253 %add = add nsw i32 %0, %a
254 %call = tail call signext i32 @externCall(i32 signext %add)
258 define dso_local signext i32 @TailCallExtern2(i32 signext %a) local_unnamed_addr {
259 ; CHECK-ALL-LABEL: TailCallExtern2:
260 ; CHECK-S: .localentry TailCallExtern2
261 ; CHECK-S: # %bb.0: # %entry
262 ; CHECK-S: pld r4, externGlobalVar@got@pcrel(0), 1
263 ; CHECK-S-NEXT: .Lpcrel3:
264 ; CHECK-S-NEXT: .reloc .Lpcrel3-8,R_PPC64_PCREL_OPT,.-(.Lpcrel3-8)
265 ; CHECK-S-NEXT: lwz r4, 0(r4)
266 ; CHECK-S-NEXT: add r3, r4, r3
267 ; CHECK-S-NEXT: extsw r3, r3
268 ; CHECK-S-NEXT: b externCall@notoc
270 %0 = load i32, ptr @externGlobalVar, align 4
271 %add = add nsw i32 %0, %a
272 %call = tail call signext i32 @externCall(i32 signext %add)
276 define dso_local signext i32 @TailCallExternNoGlobal(i32 signext %a) local_unnamed_addr {
277 ; CHECK-ALL-LABEL: TailCallExternNoGlobal:
278 ; CHECK-S: .localentry TailCallExternNoGlobal, 1
279 ; CHECK-S-NEXT: # %bb.0: # %entry
280 ; CHECK-S-NEXT: b externCall@notoc
281 ; CHECK-S-NEXT: #TC_RETURNd8 externCall@notoc
283 %call = tail call signext i32 @externCall(i32 signext %a)
287 define dso_local signext i32 @IndirectCall1(i32 signext %a, i32 signext %b) local_unnamed_addr {
288 ; CHECK-ALL-LABEL: IndirectCall1:
289 ; CHECK-S: # %bb.0: # %entry
290 ; CHECK-S-NEXT: mflr r0
291 ; CHECK-S-NEXT: std r0, 16(r1)
292 ; CHECK-S-NEXT: stdu r1, -32(r1)
293 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
294 ; CHECK-S-NEXT: .cfi_offset lr, 16
295 ; CHECK-S-NEXT: pld r12, indirectCall@PCREL(0), 1
296 ; CHECK-S-NEXT: add r3, r4, r3
297 ; CHECK-S-NEXT: extsw r3, r3
298 ; CHECK-S-NEXT: mtctr r12
299 ; CHECK-S-NEXT: bctrl
300 ; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1
301 ; CHECK-S-NEXT: mullw r3, r4, r3
302 ; CHECK-S-NEXT: extsw r3, r3
303 ; CHECK-S-NEXT: addi r1, r1, 32
304 ; CHECK-S-NEXT: ld r0, 16(r1)
305 ; CHECK-S-NEXT: mtlr r0
308 %add = add nsw i32 %b, %a
309 %0 = load ptr, ptr @indirectCall, align 8
310 %call = tail call signext i32 %0(i32 signext %add)
311 %1 = load i32, ptr @globalVar, align 4
312 %mul = mul nsw i32 %1, %call
316 define dso_local signext i32 @IndirectCall2(i32 signext %a, i32 signext %b) local_unnamed_addr {
317 ; CHECK-ALL-LABEL: IndirectCall2:
318 ; CHECK-S: # %bb.0: # %entry
319 ; CHECK-S-NEXT: mflr r0
320 ; CHECK-S-NEXT: std r0, 16(r1)
321 ; CHECK-S-NEXT: stdu r1, -32(r1)
322 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
323 ; CHECK-S-NEXT: .cfi_offset lr, 16
324 ; CHECK-S-NEXT: pld r12, indirectCall@PCREL(0), 1
325 ; CHECK-S-NEXT: add r3, r4, r3
326 ; CHECK-S-NEXT: extsw r3, r3
327 ; CHECK-S-NEXT: mtctr r12
328 ; CHECK-S-NEXT: bctrl
329 ; CHECK-S-NEXT: pld r4, externGlobalVar@got@pcrel(0), 1
330 ; CHECK-S-NEXT: .Lpcrel4:
331 ; CHECK-S-NEXT: .reloc .Lpcrel4-8,R_PPC64_PCREL_OPT,.-(.Lpcrel4-8)
332 ; CHECK-S-NEXT: lwz r4, 0(r4)
333 ; CHECK-S-NEXT: mullw r3, r4, r3
334 ; CHECK-S-NEXT: extsw r3, r3
335 ; CHECK-S-NEXT: addi r1, r1, 32
336 ; CHECK-S-NEXT: ld r0, 16(r1)
337 ; CHECK-S-NEXT: mtlr r0
340 %add = add nsw i32 %b, %a
341 %0 = load ptr, ptr @indirectCall, align 8
342 %call = tail call signext i32 %0(i32 signext %add)
343 %1 = load i32, ptr @externGlobalVar, align 4
344 %mul = mul nsw i32 %1, %call
348 define dso_local signext i32 @IndirectCall3(i32 signext %a, i32 signext %b, ptr nocapture %call_param) local_unnamed_addr {
349 ; CHECK-ALL-LABEL: IndirectCall3:
350 ; CHECK-S: # %bb.0: # %entry
351 ; CHECK-S-NEXT: mflr r0
352 ; CHECK-S-NEXT: std r0, 16(r1)
353 ; CHECK-S-NEXT: stdu r1, -32(r1)
354 ; CHECK-S-NEXT: .cfi_def_cfa_offset 32
355 ; CHECK-S-NEXT: .cfi_offset lr, 16
356 ; CHECK-S-NEXT: add r3, r4, r3
357 ; CHECK-S-NEXT: mr r12, r5
358 ; CHECK-S-NEXT: mtctr r5
359 ; CHECK-S-NEXT: extsw r3, r3
360 ; CHECK-S-NEXT: bctrl
361 ; CHECK-S-NEXT: plwz r4, globalVar@PCREL(0), 1
362 ; CHECK-S-NEXT: mullw r3, r4, r3
363 ; CHECK-S-NEXT: extsw r3, r3
364 ; CHECK-S-NEXT: addi r1, r1, 32
365 ; CHECK-S-NEXT: ld r0, 16(r1)
366 ; CHECK-S-NEXT: mtlr r0
369 %add = add nsw i32 %b, %a
370 %call = tail call signext i32 %call_param(i32 signext %add)
371 %0 = load i32, ptr @globalVar, align 4
372 %mul = mul nsw i32 %0, %call
376 define dso_local signext i32 @IndirectCallNoGlobal(i32 signext %a, i32 signext %b, ptr nocapture %call_param) local_unnamed_addr {
377 ; CHECK-ALL-LABEL: IndirectCallNoGlobal:
378 ; CHECK-S: # %bb.0: # %entry
379 ; CHECK-S-NEXT: mflr r0
380 ; CHECK-S-NEXT: .cfi_def_cfa_offset 48
381 ; CHECK-S-NEXT: .cfi_offset lr, 16
382 ; CHECK-S-NEXT: .cfi_offset r30, -16
383 ; CHECK-S-NEXT: std r30, -16(r1) # 8-byte Folded Spill
384 ; CHECK-S-NEXT: std r0, 16(r1)
385 ; CHECK-S-NEXT: stdu r1, -48(r1)
386 ; CHECK-S-NEXT: mr r12, r5
387 ; CHECK-S-NEXT: mtctr r5
388 ; CHECK-S-NEXT: mr r30, r4
389 ; CHECK-S-NEXT: bctrl
390 ; CHECK-S-NEXT: add r3, r3, r30
391 ; CHECK-S-NEXT: extsw r3, r3
392 ; CHECK-S-NEXT: addi r1, r1, 48
393 ; CHECK-S-NEXT: ld r0, 16(r1)
394 ; CHECK-S-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
395 ; CHECK-S-NEXT: mtlr r0
398 %call = tail call signext i32 %call_param(i32 signext %a)
399 %add = add nsw i32 %call, %b
403 define dso_local signext i32 @IndirectCallOnly(i32 signext %a, ptr nocapture %call_param) local_unnamed_addr {
404 ; CHECK-ALL-LABEL: IndirectCallOnly:
405 ; CHECK-S: # %bb.0: # %entry
406 ; CHECK-S-NEXT: mtctr r4
407 ; CHECK-S-NEXT: mr r12, r4
409 ; CHECK-S-NEXT: #TC_RETURNr8 ctr
411 %call = tail call signext i32 %call_param(i32 signext %a)
415 attributes #0 = { noinline }