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 ptr, align 8
16 @FuncLocal = common dso_local local_unnamed_addr global ptr 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 ptr @Function, ptr @Func, align 8
29 store ptr @Function, ptr @FuncLocal, align 8
33 declare signext i32 @Function(...)
35 define dso_local void @TailCallLocalFuncPtr() local_unnamed_addr {
36 ; CHECK-LABEL: TailCallLocalFuncPtr:
37 ; CHECK: # %bb.0: # %entry
38 ; CHECK-NEXT: pld r12, FuncLocal@PCREL(0), 1
39 ; CHECK-NEXT: mtctr r12
41 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
43 %0 = load ptr, ptr @FuncLocal, align 8
44 %call = tail call signext i32 %0()
48 define dso_local void @TailCallExtrnFuncPtr() local_unnamed_addr {
49 ; CHECK-LABEL: TailCallExtrnFuncPtr:
50 ; CHECK: # %bb.0: # %entry
51 ; CHECK-NEXT: pld r3, Func@got@pcrel(0), 1
52 ; CHECK-NEXT: .Lpcrel0:
53 ; CHECK-NEXT: .reloc .Lpcrel0-8,R_PPC64_PCREL_OPT,.-(.Lpcrel0-8)
54 ; CHECK-NEXT: ld r12, 0(r3)
55 ; CHECK-NEXT: mtctr r12
57 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
59 %0 = load ptr, ptr @Func, align 8
60 %call = tail call signext i32 %0()
64 define dso_local signext i32 @TailCallParamFuncPtr(ptr nocapture %passedfunc) local_unnamed_addr {
65 ; CHECK-LABEL: TailCallParamFuncPtr:
66 ; CHECK: # %bb.0: # %entry
67 ; CHECK-NEXT: mtctr r3
68 ; CHECK-NEXT: mr r12, r3
70 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
72 %call = tail call signext i32 %passedfunc()
76 define dso_local signext i32 @NoTailIndirectCall(ptr nocapture %passedfunc, i32 signext %a) local_unnamed_addr {
77 ; CHECK-LABEL: NoTailIndirectCall:
78 ; CHECK: # %bb.0: # %entry
80 ; CHECK-NEXT: .cfi_def_cfa_offset 48
81 ; CHECK-NEXT: .cfi_offset lr, 16
82 ; CHECK-NEXT: .cfi_offset r30, -16
83 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
84 ; CHECK-NEXT: std r0, 16(r1)
85 ; CHECK-NEXT: stdu r1, -48(r1)
86 ; CHECK-NEXT: mr r12, r3
87 ; CHECK-NEXT: mtctr r3
88 ; CHECK-NEXT: mr r30, r4
90 ; CHECK-NEXT: add r3, r3, r30
91 ; CHECK-NEXT: extsw r3, r3
92 ; CHECK-NEXT: addi r1, r1, 48
93 ; CHECK-NEXT: ld r0, 16(r1)
94 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
98 %call = tail call signext i32 %passedfunc()
99 %add = add nsw i32 %call, %a
103 define dso_local signext i32 @TailCallDirect() local_unnamed_addr {
104 ; CHECK-LABEL: TailCallDirect:
105 ; CHECK: # %bb.0: # %entry
106 ; CHECK-NEXT: b Function@notoc
107 ; CHECK-NEXT: #TC_RETURNd8 Function@notoc 0
109 %call = tail call signext i32 @Function()
113 define dso_local signext i32 @NoTailCallDirect(i32 signext %a) local_unnamed_addr {
114 ; CHECK-LABEL: NoTailCallDirect:
115 ; CHECK: # %bb.0: # %entry
116 ; CHECK-NEXT: mflr r0
117 ; CHECK-NEXT: .cfi_def_cfa_offset 48
118 ; CHECK-NEXT: .cfi_offset lr, 16
119 ; CHECK-NEXT: .cfi_offset r30, -16
120 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
121 ; CHECK-NEXT: std r0, 16(r1)
122 ; CHECK-NEXT: stdu r1, -48(r1)
123 ; CHECK-NEXT: mr r30, r3
124 ; CHECK-NEXT: bl Function@notoc
125 ; CHECK-NEXT: add r3, r3, r30
126 ; CHECK-NEXT: extsw r3, r3
127 ; CHECK-NEXT: addi r1, r1, 48
128 ; CHECK-NEXT: ld r0, 16(r1)
129 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
130 ; CHECK-NEXT: mtlr r0
133 %call = tail call signext i32 @Function()
134 %add = add nsw i32 %call, %a
138 define dso_local signext i32 @TailCallDirectLocal() local_unnamed_addr {
139 ; CHECK-LABEL: TailCallDirectLocal:
140 ; CHECK: # %bb.0: # %entry
141 ; CHECK-NEXT: b LocalFunction@notoc
142 ; CHECK-NEXT: #TC_RETURNd8 LocalFunction@notoc 0
144 %call = tail call fastcc signext i32 @LocalFunction()
148 define dso_local signext i32 @NoTailCallDirectLocal(i32 signext %a) local_unnamed_addr {
149 ; CHECK-LABEL: NoTailCallDirectLocal:
150 ; CHECK: # %bb.0: # %entry
151 ; CHECK-NEXT: mflr r0
152 ; CHECK-NEXT: .cfi_def_cfa_offset 48
153 ; CHECK-NEXT: .cfi_offset lr, 16
154 ; CHECK-NEXT: .cfi_offset r30, -16
155 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
156 ; CHECK-NEXT: std r0, 16(r1)
157 ; CHECK-NEXT: stdu r1, -48(r1)
158 ; CHECK-NEXT: mr r30, r3
159 ; CHECK-NEXT: bl LocalFunction@notoc
160 ; CHECK-NEXT: add r3, r3, r30
161 ; CHECK-NEXT: extsw r3, r3
162 ; CHECK-NEXT: addi r1, r1, 48
163 ; CHECK-NEXT: ld r0, 16(r1)
164 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
165 ; CHECK-NEXT: mtlr r0
168 %call = tail call fastcc signext i32 @LocalFunction()
169 %add = add nsw i32 %call, %a
173 define dso_local signext i32 @TailCallAbs() local_unnamed_addr {
174 ; CHECK-LABEL: TailCallAbs:
175 ; CHECK: # %bb.0: # %entry
176 ; CHECK-NEXT: li r3, 400
177 ; CHECK-NEXT: li r12, 400
178 ; CHECK-NEXT: mtctr r3
180 ; CHECK-NEXT: #TC_RETURNr8 ctr 0
182 %call = tail call signext i32 inttoptr (i64 400 to ptr)()
186 define dso_local signext i32 @NoTailCallAbs(i32 signext %a) local_unnamed_addr {
187 ; CHECK-LABEL: NoTailCallAbs:
188 ; CHECK: # %bb.0: # %entry
189 ; CHECK-NEXT: mflr r0
190 ; CHECK-NEXT: .cfi_def_cfa_offset 48
191 ; CHECK-NEXT: .cfi_offset lr, 16
192 ; CHECK-NEXT: .cfi_offset r30, -16
193 ; CHECK-NEXT: std r30, -16(r1) # 8-byte Folded Spill
194 ; CHECK-NEXT: std r0, 16(r1)
195 ; CHECK-NEXT: stdu r1, -48(r1)
196 ; CHECK-NEXT: mr r30, r3
197 ; CHECK-NEXT: li r3, 400
198 ; CHECK-NEXT: li r12, 400
199 ; CHECK-NEXT: mtctr r3
201 ; CHECK-NEXT: add r3, r3, r30
202 ; CHECK-NEXT: extsw r3, r3
203 ; CHECK-NEXT: addi r1, r1, 48
204 ; CHECK-NEXT: ld r0, 16(r1)
205 ; CHECK-NEXT: ld r30, -16(r1) # 8-byte Folded Reload
206 ; CHECK-NEXT: mtlr r0
209 %call = tail call signext i32 inttoptr (i64 400 to ptr)()
210 %add = add nsw i32 %call, %a
214 ; Function Attrs: noinline
215 ; This function should be tail called and not inlined.
216 define internal fastcc signext i32 @LocalFunction() unnamed_addr #0 {
217 ; CHECK-LABEL: LocalFunction:
218 ; CHECK: # %bb.0: # %entry
220 ; CHECK-NEXT: li r3, 42
221 ; CHECK-NEXT: #NO_APP
222 ; CHECK-NEXT: extsw r3, r3
225 %0 = tail call i32 asm "li $0, 42", "=&r"()
229 attributes #0 = { noinline }