@@ -181,8 +181,9 @@ define void @test_tailcall_omit_mov_x16_x16(ptr %objptr) #0 {
181181; ELF-NEXT: movk x8, #6503, lsl #48
182182; ELF-NEXT: autda x1, x8
183183; ELF-NEXT: ldr x2, [x1]
184- ; ELF-NEXT: movk x1, #54167, lsl #48
185- ; ELF-NEXT: braa x2, x1
184+ ; ELF-NEXT: mov x16, x1
185+ ; ELF-NEXT: movk x16, #54167, lsl #48
186+ ; ELF-NEXT: braa x2, x16
186187 %vtable.signed = load ptr , ptr %objptr , align 8
187188 %objptr.int = ptrtoint ptr %objptr to i64
188189 %vtable.discr = tail call i64 @llvm.ptrauth.blend (i64 %objptr.int , i64 6503 )
@@ -213,8 +214,9 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 {
213214; ELF-NEXT: movk x9, #6503, lsl #48
214215; ELF-NEXT: autda x8, x9
215216; ELF-NEXT: ldr x9, [x8]
216- ; ELF-NEXT: movk x8, #34646, lsl #48
217- ; ELF-NEXT: blraa x9, x8
217+ ; ELF-NEXT: mov x17, x8
218+ ; ELF-NEXT: movk x17, #34646, lsl #48
219+ ; ELF-NEXT: blraa x9, x17
218220; ELF-NEXT: mov w0, #42
219221; ELF-NEXT: ldr x30, [sp], #16
220222; CHECK-NEXT: ret
@@ -230,6 +232,97 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 {
230232 ret i32 42
231233}
232234
235+ ; The second BLRA instruction should not reuse its AddrDisc operand as a scratch register (returned later).
236+ define i64 @test_call_discr_csr_live (ptr %fnptr , i64 %addr.discr ) #0 {
237+ ; ELF-LABEL: test_call_discr_csr_live:
238+ ; ELF-NEXT: str x30, [sp, #-32]!
239+ ; ELF-NEXT: stp x20, x19, [sp, #16]
240+ ; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0
241+ ; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1
242+ ; ELF-DAG: mov x17, x1
243+ ; ELF-NEXT: movk x17, #6503, lsl #48
244+ ; ELF-NEXT: blraa x0, x17
245+ ; ELF-NEXT: mov x17, x[[ADDR_DISC]]
246+ ; ELF-NEXT: movk x17, #6503, lsl #48
247+ ; ELF-NEXT: blraa x[[FNPTR]], x17
248+ ; ELF-NEXT: mov x0, x[[ADDR_DISC]]
249+ ; ELF-NEXT: ldp x20, x19, [sp, #16]
250+ ; ELF-NEXT: ldr x30, [sp], #32
251+ ; ELF-NEXT: ret
252+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
253+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
254+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
255+ ret i64 %addr.discr
256+ }
257+
258+ ; The second BLRA instruction may reuse its AddrDisc operand as a scratch register.
259+ define i64 @test_call_discr_csr_killed (ptr %fnptr , i64 %addr.discr ) #0 {
260+ ; ELF-LABEL: test_call_discr_csr_killed:
261+ ; ELF-NEXT: str x30, [sp, #-32]!
262+ ; ELF-NEXT: stp x20, x19, [sp, #16]
263+ ; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0
264+ ; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1
265+ ; ELF-DAG: mov x17, x1
266+ ; ELF-NEXT: movk x17, #6503, lsl #48
267+ ; ELF-NEXT: blraa x0, x17
268+ ; ELF-DAG: mov x17, x[[ADDR_DISC]]
269+ ; ELF-NEXT: movk x17, #6503, lsl #48
270+ ; ELF-NEXT: blraa x[[FNPTR]], x17
271+ ; ELF-NEXT: ldp x20, x19, [sp, #16]
272+ ; ELF-NEXT: mov w0, #42
273+ ; ELF-NEXT: ldr x30, [sp], #32
274+ ; ELF-NEXT: ret
275+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
276+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
277+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
278+ ret i64 42
279+ }
280+
281+ ; BLRA instruction should not reuse its AddrDisc operand as a scratch register (function argument).
282+ define i64 @test_call_discr_arg (ptr %fnptr , i64 %addr.discr ) #0 {
283+ ; ELF-LABEL: test_call_discr_arg:
284+ ; ELF-NEXT: str x30, [sp, #-16]!
285+ ; ELF-NEXT: mov x8, x0
286+ ; ELF-NEXT: mov x0, xzr
287+ ; ELF-NEXT: mov x17, x1
288+ ; ELF-NEXT: movk x17, #6503, lsl #48
289+ ; ELF-NEXT: blraa x8, x17
290+ ; ELF-NEXT: mov w0, #42
291+ ; ELF-NEXT: ldr x30, [sp], #16
292+ ; ELF-NEXT: ret
293+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
294+ tail call void %fnptr (ptr null , i64 %addr.discr ) [ "ptrauth" (i32 0 , i64 %discr ) ]
295+ ret i64 42
296+ }
297+
298+ ; BLRA instruction may reuse its AddrDisc operand as a scratch register.
299+ define i64 @test_call_discr_non_arg (ptr %fnptr , i64 %addr.discr ) #0 {
300+ ; ELF-LABEL: test_call_discr_non_arg:
301+ ; ELF-NEXT: str x30, [sp, #-16]!
302+ ; ELF-NEXT: mov x17, x1
303+ ; ELF-NEXT: movk x17, #6503, lsl #48
304+ ; ELF-NEXT: blraa x0, x17
305+ ; ELF-NEXT: mov w0, #42
306+ ; ELF-NEXT: ldr x30, [sp], #16
307+ ; ELF-NEXT: ret
308+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
309+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
310+ ret i64 42
311+ }
312+
313+ ; AUTH_TCRETURN instruction should not reuse its AddrDisc operand as a scratch register (function argument).
314+ define i64 @test_tailcall_discr_arg (ptr %fnptr , i64 %addr.discr ) #0 {
315+ ; ELF-LABEL: test_tailcall_discr_arg:
316+ ; ELF-NEXT: mov x2, x0
317+ ; ELF-NEXT: mov x0, xzr
318+ ; ELF-NEXT: mov x16, x1
319+ ; ELF-NEXT: movk x16, #6503, lsl #48
320+ ; ELF-NEXT: braa x2, x16
321+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
322+ %result = tail call i64 %fnptr (ptr null , i64 %addr.discr ) [ "ptrauth" (i32 0 , i64 %discr ) ]
323+ ret i64 %result
324+ }
325+
233326define i32 @test_call_ia_arg (ptr %arg0 , i64 %arg1 ) #0 {
234327; DARWIN-LABEL: test_call_ia_arg:
235328; DARWIN-NEXT: stp x29, x30, [sp, #-16]!
0 commit comments