1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2 ; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
3 ; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
5 ; RUN: llc -verify-machineinstrs -target-abi=elfv2 -mtriple=powerpc64-- \
6 ; RUN: -mcpu=pwr10 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
10 ; The tests check the behaviour of PC Relative tail calls. When using
11 ; PC Relative we are able to do more tail calling than we have done in
12 ; the past as we no longer need to restore the TOC pointer into R2 after
15 @Func = external local_unnamed_addr global i32 (...)*, align 8
16 @FuncLocal = common dso_local local_unnamed_addr global i32 (...)* null, align 8
18 ; No calls in this function but we assign the function pointers.
19 define dso_local void @AssignFuncPtr() local_unnamed_addr {
20 ; CHECK-LABEL: AssignFuncPtr:
21 ; CHECK: # %bb.0: # %entry
22 ; CHECK-NEXT: pld r3, Func@got@pcrel(0), 1
23 ; CHECK-NEXT: pld r4, Function@got@pcrel(0), 1
24 ; CHECK-NEXT: std r4, 0(r3)
25 ; CHECK-NEXT: pstd r4, FuncLocal@PCREL(0), 1
28 store i32 (...)* @Function, i32 (...)** @Func, align 8
29 store i32 (...)* @Function, i32 (...)** @FuncLocal, align 8
33 declare signext i32 @Function(...)
35 define dso_local void @TailCallLocalFuncPtr() local_unnamed_addr {
36 ; CHECK-LABEL: TailCallLocalFuncPtr:
37 ; CHECK: .localentry TailCallLocalFuncPtr, 1
38 ; CHECK-NEXT: # %bb.0: # %entry
39 ; CHECK-NEXT: pld r12, FuncLocal@PCREL(0), 1
40 ; CHECK-NEXT: mtctr r12
42 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
44 %0 = load i32 ()*, i32 ()** bitcast (i32 (...)** @FuncLocal to i32 ()**), align 8
45 %call = tail call signext i32 %0()
49 define dso_local void @TailCallExtrnFuncPtr() local_unnamed_addr {
50 ; CHECK-LABEL: TailCallExtrnFuncPtr:
51 ; CHECK: .localentry TailCallExtrnFuncPtr, 1
52 ; CHECK-NEXT: # %bb.0: # %entry
53 ; CHECK-NEXT: pld r3, Func@got@pcrel(0), 1
54 ; CHECK-NEXT: .Lpcrel0:
55 ; CHECK-NEXT: .reloc .Lpcrel0-8,R_PPC64_PCREL_OPT,.-(.Lpcrel0-8)
56 ; CHECK-NEXT: ld r12, 0(r3)
57 ; CHECK-NEXT: mtctr r12
59 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
61 %0 = load i32 ()*, i32 ()** bitcast (i32 (...)** @Func to i32 ()**), align 8
62 %call = tail call signext i32 %0()
66 define dso_local signext i32 @TailCallParamFuncPtr(i32 (...)* nocapture %passedfunc) local_unnamed_addr {
67 ; CHECK-LABEL: TailCallParamFuncPtr:
68 ; CHECK: .localentry TailCallParamFuncPtr, 1
69 ; CHECK-NEXT: # %bb.0: # %entry
70 ; CHECK-NEXT: mtctr r3
71 ; CHECK-NEXT: mr r12, r3
73 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
75 %callee.knr.cast = bitcast i32 (...)* %passedfunc to i32 ()*
76 %call = tail call signext i32 %callee.knr.cast()
80 define dso_local signext i32 @NoTailIndirectCall(i32 (...)* nocapture %passedfunc, i32 signext %a) local_unnamed_addr {
81 ; CHECK-LABEL: NoTailIndirectCall:
82 ; CHECK: .localentry NoTailIndirectCall, 1
83 ; CHECK-NEXT: # %bb.0: # %entry
85 ; CHECK-NEXT: .cfi_def_cfa_offset 48
86 ; CHECK-NEXT: .cfi_offset lr, 16
87 ; CHECK-NEXT: .cfi_offset r30, -16
88 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
89 ; CHECK-NEXT: std r0, 16(r1)
90 ; CHECK-NEXT: stdu r1, -48(r1)
91 ; CHECK-NEXT: mtctr r3
92 ; CHECK-NEXT: mr r12, r3
93 ; CHECK-NEXT: mr r30, r4
95 ; CHECK-NEXT: add r3, r3, r30
96 ; CHECK-NEXT: extsw r3, r3
97 ; CHECK-NEXT: addi r1, r1, 48
98 ; CHECK-NEXT: ld r0, 16(r1)
99 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
100 ; CHECK-NEXT: mtlr r0
103 %callee.knr.cast = bitcast i32 (...)* %passedfunc to i32 ()*
104 %call = tail call signext i32 %callee.knr.cast()
105 %add = add nsw i32 %call, %a
109 define dso_local signext i32 @TailCallDirect() local_unnamed_addr {
110 ; CHECK-LABEL: TailCallDirect:
111 ; CHECK: .localentry TailCallDirect, 1
112 ; CHECK-NEXT: # %bb.0: # %entry
113 ; CHECK-NEXT: b Function@notoc
114 ; CHECK-NEXT: #TC_RETURNd8 Function@notoc 0
116 %call = tail call signext i32 bitcast (i32 (...)* @Function to i32 ()*)()
120 define dso_local signext i32 @NoTailCallDirect(i32 signext %a) local_unnamed_addr {
121 ; CHECK-LABEL: NoTailCallDirect:
122 ; CHECK: .localentry NoTailCallDirect, 1
123 ; CHECK-NEXT: # %bb.0: # %entry
124 ; CHECK-NEXT: mflr r0
125 ; CHECK-NEXT: .cfi_def_cfa_offset 48
126 ; CHECK-NEXT: .cfi_offset lr, 16
127 ; CHECK-NEXT: .cfi_offset r30, -16
128 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
129 ; CHECK-NEXT: std r0, 16(r1)
130 ; CHECK-NEXT: stdu r1, -48(r1)
131 ; CHECK-NEXT: mr r30, r3
132 ; CHECK-NEXT: bl Function@notoc
133 ; CHECK-NEXT: add r3, r3, r30
134 ; CHECK-NEXT: extsw r3, r3
135 ; CHECK-NEXT: addi r1, r1, 48
136 ; CHECK-NEXT: ld r0, 16(r1)
137 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
138 ; CHECK-NEXT: mtlr r0
141 %call = tail call signext i32 bitcast (i32 (...)* @Function to i32 ()*)()
142 %add = add nsw i32 %call, %a
146 define dso_local signext i32 @TailCallDirectLocal() local_unnamed_addr {
147 ; CHECK-LABEL: TailCallDirectLocal:
148 ; CHECK: .localentry TailCallDirectLocal, 1
149 ; CHECK-NEXT: # %bb.0: # %entry
150 ; CHECK-NEXT: b LocalFunction@notoc
151 ; CHECK-NEXT: #TC_RETURNd8 LocalFunction@notoc 0
153 %call = tail call fastcc signext i32 @LocalFunction()
157 define dso_local signext i32 @NoTailCallDirectLocal(i32 signext %a) local_unnamed_addr {
158 ; CHECK-LABEL: NoTailCallDirectLocal:
159 ; CHECK: .localentry NoTailCallDirectLocal, 1
160 ; CHECK-NEXT: # %bb.0: # %entry
161 ; CHECK-NEXT: mflr r0
162 ; CHECK-NEXT: .cfi_def_cfa_offset 48
163 ; CHECK-NEXT: .cfi_offset lr, 16
164 ; CHECK-NEXT: .cfi_offset r30, -16
165 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
166 ; CHECK-NEXT: std r0, 16(r1)
167 ; CHECK-NEXT: stdu r1, -48(r1)
168 ; CHECK-NEXT: mr r30, r3
169 ; CHECK-NEXT: bl LocalFunction@notoc
170 ; CHECK-NEXT: add r3, r3, r30
171 ; CHECK-NEXT: extsw r3, r3
172 ; CHECK-NEXT: addi r1, r1, 48
173 ; CHECK-NEXT: ld r0, 16(r1)
174 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
175 ; CHECK-NEXT: mtlr r0
178 %call = tail call fastcc signext i32 @LocalFunction()
179 %add = add nsw i32 %call, %a
183 define dso_local signext i32 @TailCallAbs() local_unnamed_addr {
184 ; CHECK-LABEL: TailCallAbs:
185 ; CHECK: .localentry TailCallAbs, 1
186 ; CHECK-NEXT: # %bb.0: # %entry
187 ; CHECK-NEXT: li r3, 400
188 ; CHECK-NEXT: li r12, 400
189 ; CHECK-NEXT: mtctr r3
191 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
193 %call = tail call signext i32 inttoptr (i64 400 to i32 ()*)()
197 define dso_local signext i32 @NoTailCallAbs(i32 signext %a) local_unnamed_addr {
198 ; CHECK-LABEL: NoTailCallAbs:
199 ; CHECK: .localentry NoTailCallAbs, 1
200 ; CHECK-NEXT: # %bb.0: # %entry
201 ; CHECK-NEXT: mflr r0
202 ; CHECK-NEXT: .cfi_def_cfa_offset 48
203 ; CHECK-NEXT: .cfi_offset lr, 16
204 ; CHECK-NEXT: .cfi_offset r30, -16
205 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
206 ; CHECK-NEXT: std r0, 16(r1)
207 ; CHECK-NEXT: stdu r1, -48(r1)
208 ; CHECK-NEXT: mr r30, r3
209 ; CHECK-NEXT: li r3, 400
210 ; CHECK-NEXT: li r12, 400
211 ; CHECK-NEXT: mtctr r3
213 ; CHECK-NEXT: add r3, r3, r30
214 ; CHECK-NEXT: extsw r3, r3
215 ; CHECK-NEXT: addi r1, r1, 48
216 ; CHECK-NEXT: ld r0, 16(r1)
217 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
218 ; CHECK-NEXT: mtlr r0
221 %call = tail call signext i32 inttoptr (i64 400 to i32 ()*)()
222 %add = add nsw i32 %call, %a
226 ; Function Attrs: noinline
227 ; This function should be tail called and not inlined.
228 define internal fastcc signext i32 @LocalFunction() unnamed_addr #0 {
229 ; CHECK-LABEL: LocalFunction:
230 ; CHECK: .localentry LocalFunction, 1
231 ; CHECK-NEXT: # %bb.0: # %entry
233 ; CHECK-NEXT: li r3, 42
234 ; CHECK-NEXT: #NO_APP
235 ; CHECK-NEXT: extsw r3, r3
238 %0 = tail call i32 asm "li $0, 42", "=&r"()
242 attributes #0 = { noinline }