@@ -230,6 +230,90 @@ define i32 @test_call_omit_extra_moves(ptr %objptr) #0 {
230230 ret i32 42
231231}
232232
233+ ; The second BLRA instruction should not reuse its AddrDisc operand as a scratch register (returned later).
234+ define i64 @test_call_discr_csr_live (ptr %fnptr , i64 %addr.discr ) #0 {
235+ ; ELF-LABEL: test_call_discr_csr_live:
236+ ; ELF-NEXT: str x30, [sp, #-32]!
237+ ; ELF-NEXT: stp x20, x19, [sp, #16]
238+ ; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0
239+ ; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1
240+ ; ELF-NEXT: movk x1, #6503, lsl #48
241+ ; ELF-NEXT: blraa x0, x1
242+ ; ELF-NEXT: movk x[[ADDR_DISC]], #6503, lsl #48
243+ ; ELF-NEXT: blraa x[[FNPTR]], x[[ADDR_DISC]]
244+ ; ELF-NEXT: mov x0, x[[ADDR_DISC]]
245+ ; ELF-NEXT: ldp x20, x19, [sp, #16]
246+ ; ELF-NEXT: ldr x30, [sp], #32
247+ ; ELF-NEXT: ret
248+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
249+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
250+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
251+ ret i64 %addr.discr
252+ }
253+
254+ ; The second BLRA instruction may reuse its AddrDisc operand as a scratch register.
255+ define i64 @test_call_discr_csr_killed (ptr %fnptr , i64 %addr.discr ) #0 {
256+ ; ELF-LABEL: test_call_discr_csr_killed:
257+ ; ELF-NEXT: str x30, [sp, #-32]!
258+ ; ELF-NEXT: stp x20, x19, [sp, #16]
259+ ; ELF-DAG: mov x[[FNPTR:[0-9]+]], x0
260+ ; ELF-DAG: mov x[[ADDR_DISC:[0-9]+]], x1
261+ ; ELF-NEXT: movk x1, #6503, lsl #48
262+ ; ELF-NEXT: blraa x0, x1
263+ ; ELF-NEXT: movk x[[ADDR_DISC]], #6503, lsl #48
264+ ; ELF-NEXT: blraa x[[FNPTR]], x[[ADDR_DISC]]
265+ ; ELF-NEXT: ldp x20, x19, [sp, #16]
266+ ; ELF-NEXT: mov w0, #42
267+ ; ELF-NEXT: ldr x30, [sp], #32
268+ ; ELF-NEXT: ret
269+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
270+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
271+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
272+ ret i64 42
273+ }
274+
275+ ; BLRA instruction should not reuse its AddrDisc operand as a scratch register (function argument).
276+ define i64 @test_call_discr_arg (ptr %fnptr , i64 %addr.discr ) #0 {
277+ ; ELF-LABEL: test_call_discr_arg:
278+ ; ELF-NEXT: str x30, [sp, #-16]!
279+ ; ELF-NEXT: mov x8, x0
280+ ; ELF-NEXT: mov x0, xzr
281+ ; ELF-NEXT: movk x1, #6503, lsl #48
282+ ; ELF-NEXT: blraa x8, x1
283+ ; ELF-NEXT: mov w0, #42
284+ ; ELF-NEXT: ldr x30, [sp], #16
285+ ; ELF-NEXT: ret
286+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
287+ tail call void %fnptr (ptr null , i64 %addr.discr ) [ "ptrauth" (i32 0 , i64 %discr ) ]
288+ ret i64 42
289+ }
290+
291+ ; BLRA instruction may reuse its AddrDisc operand as a scratch register.
292+ define i64 @test_call_discr_non_arg (ptr %fnptr , i64 %addr.discr ) #0 {
293+ ; ELF-LABEL: test_call_discr_non_arg:
294+ ; ELF-NEXT: str x30, [sp, #-16]!
295+ ; ELF-NEXT: movk x1, #6503, lsl #48
296+ ; ELF-NEXT: blraa x0, x1
297+ ; ELF-NEXT: mov w0, #42
298+ ; ELF-NEXT: ldr x30, [sp], #16
299+ ; ELF-NEXT: ret
300+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
301+ tail call void %fnptr () [ "ptrauth" (i32 0 , i64 %discr ) ]
302+ ret i64 42
303+ }
304+
305+ ; AUTH_TCRETURN instruction should not reuse its AddrDisc operand as a scratch register (function argument).
306+ define i64 @test_tailcall_discr_arg (ptr %fnptr , i64 %addr.discr ) #0 {
307+ ; ELF-LABEL: test_tailcall_discr_arg:
308+ ; ELF-NEXT: mov x2, x0
309+ ; ELF-NEXT: mov x0, xzr
310+ ; ELF-NEXT: movk x1, #6503, lsl #48
311+ ; ELF-NEXT: braa x2, x1
312+ %discr = tail call i64 @llvm.ptrauth.blend (i64 %addr.discr , i64 6503 )
313+ %result = tail call i64 %fnptr (ptr null , i64 %addr.discr ) [ "ptrauth" (i32 0 , i64 %discr ) ]
314+ ret i64 %result
315+ }
316+
233317define i32 @test_call_ia_arg (ptr %arg0 , i64 %arg1 ) #0 {
234318; DARWIN-LABEL: test_call_ia_arg:
235319; DARWIN-NEXT: stp x29, x30, [sp, #-16]!
0 commit comments