[llvm-branch-commits] [llvm] 1a802d5 - [AArch64][PAC] Mark $Scratch operand of AUTxMxN as earlyclobber (#173999)

Cullen Rhodes via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Feb 23 07:26:49 PST 2026


Author: Anatoly Trosinenko
Date: 2026-02-23T15:26:40Z
New Revision: 1a802d58deacc0d3b8d92a9ace1105e8a45b689b

URL: https://github.com/llvm/llvm-project/commit/1a802d58deacc0d3b8d92a9ace1105e8a45b689b
DIFF: https://github.com/llvm/llvm-project/commit/1a802d58deacc0d3b8d92a9ace1105e8a45b689b.diff

LOG: [AArch64][PAC] Mark $Scratch operand of AUTxMxN as earlyclobber (#173999)

This fixes an assertions when emitting code at `-O0`.

(cherry picked from commit a47f3802bfd7f8f4c56cb11bad89d844398e6662)

Added: 
    

Modified: 
    llvm/lib/Target/AArch64/AArch64InstrInfo.td
    llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
    llvm/test/CodeGen/AArch64/ptrauth-isel.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index cb8f7c3d70afc..279507c8dba22 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -2203,10 +2203,21 @@ let Predicates = [HasPAuth] in {
     let Uses = [X16];
   }
 
+  // AArch64AsmPrinter can clobber the $AddrDisc register as long as it is
+  // marked "killed", otherwise an assertion in emitPtrauthDiscriminator checks
+  // that $Scratch != $AddrDisc. The problem is that it is always correct to
+  // *omit* the "killed" flag, thus an instruction like this is valid:
+  //
+  //     $x8, $x9 = AUTxMxN $x8, 0, 12345, /* is actually killed */ $x9, implicit-def $nzcv
+  //     // $x9 is dead past this point
+  //
+  // While it is possible to allow emitPtrauthDiscriminator to clobber $Scratch
+  // iff ($AddrDisc is killed OR $Scratch == $AddrDisc), it is easier and more
+  // straightforward to mark $Scratch as @earlyclobber.
   def AUTxMxN : Pseudo<(outs GPR64:$AuthVal, GPR64common:$Scratch),
                        (ins GPR64:$Val, i32imm:$Key,
                             i64imm:$Disc, GPR64:$AddrDisc),
-                       [], "$AuthVal = $Val">, Sched<[WriteI, ReadI]> {
+                       [], "$AuthVal = $Val, at earlyclobber $Scratch">, Sched<[WriteI, ReadI]> {
     let isCodeGenOnly = 1;
     let hasSideEffects = 1;
     let mayStore = 0;

diff  --git a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
index e2aea6df78250..a56921d008712 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-intrinsic-auth-resign-with-blend.ll
@@ -29,6 +29,11 @@
 ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -global-isel -global-isel-abort=1 -verify-machineinstrs \
 ; RUN:   -aarch64-ptrauth-auth-checks=trap | FileCheck %s -DL=".L" --check-prefixes=TRAP,TRAP-ELF
 
+; Make sure codegen at -O0 does not crash:
+;
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -O0 -verify-machineinstrs -global-isel=0
+; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -O0 -verify-machineinstrs -global-isel=1 -global-isel-abort=1
+
 target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
 
 define i64 @test_auth_blend(i64 %arg, i64 %arg1) {
@@ -299,6 +304,28 @@ define i64 @test_auth_too_large_discriminator(i64 %arg, i64 %arg1) {
   ret i64 %tmp1
 }
 
+; Without "@earlyclobber $Scratch" constraint on AUTxMxN pseudo, the following
+; instruction was fed to AArch64AsmPrinter at -O0
+;
+;     renamable $x8, dead renamable $x9 = AUTxMxN renamable $x8(tied-def 0), 0, 1, renamable $x9, implicit-def dead $nzcv
+;
+; resulting in an assertion:
+;
+;     Assertion `ScratchReg != AddrDisc && "Forbidden to clobber AddrDisc, but have to"
+;
+define i64 @autxmxn_scratch_is_earlyclobber(i64 %ptr, i64 %arg) {
+entry:
+  %discr = call i64 @llvm.ptrauth.blend(i64 %arg, i64 1)
+  br label %some.bb
+
+some.bb:
+  %authed = call i64 @llvm.ptrauth.auth(i64 %ptr, i32 0, i64 %discr)
+  br label %some.other.bb
+
+some.other.bb:
+  ret i64 %authed
+}
+
 declare i64 @llvm.ptrauth.auth(i64, i32, i64)
 declare i64 @llvm.ptrauth.resign(i64, i32, i64, i32, i64)
 declare i64 @llvm.ptrauth.blend(i64, i64)

diff  --git a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll
index 7011b946aad74..6ecfb5852f790 100644
--- a/llvm/test/CodeGen/AArch64/ptrauth-isel.ll
+++ b/llvm/test/CodeGen/AArch64/ptrauth-isel.ll
@@ -1,12 +1,12 @@
 ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc < %s -mtriple arm64e-apple-darwin             -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \
-; RUN:     | FileCheck %s --check-prefixes=DAGISEL
+; RUN:     | FileCheck %s --check-prefixes=DAGISEL,DAGISEL-DARWIN
 ; RUN: llc < %s -mtriple arm64e-apple-darwin             -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \
-; RUN:     | FileCheck %s --check-prefixes=GISEL
+; RUN:     | FileCheck %s --check-prefixes=GISEL,GISEL-DARWIN
 ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=0 \
-; RUN:     | FileCheck %s --check-prefixes=DAGISEL
+; RUN:     | FileCheck %s --check-prefixes=DAGISEL,DAGISEL-GNU
 ; RUN: llc < %s -mtriple aarch64-linux-gnu -mattr=+pauth -verify-machineinstrs -stop-after=finalize-isel -global-isel=1 -global-isel-abort=1 \
-; RUN:     | FileCheck %s --check-prefixes=GISEL
+; RUN:     | FileCheck %s --check-prefixes=GISEL,GISEL-GNU
 
 ; Check MIR produced by the instruction selector to validate properties that
 ; cannot be reliably tested by only inspecting the final asm output.
@@ -267,3 +267,56 @@ exit:
   %signed = call i64 @llvm.ptrauth.sign(i64 %addr, i32 2, i64 %disc)
   ret i64 %signed
 }
+
+; On non-Darwin platforms, AUTxMxN allows allocating arbitrary scratch registers.
+; To simplify expansion of AUTxMxN in AArch64AsmPrinter, $Scratch operand
+; should be marked as @earlyclobber, which is checked by this test case.
+define i64 @autxmxn_earlyclobbered_scratch(i64 %addr, i64 %disc) {
+  ; DAGISEL-DARWIN-LABEL: name: autxmxn_earlyclobbered_scratch
+  ; DAGISEL-DARWIN: bb.0.entry:
+  ; DAGISEL-DARWIN-NEXT:   liveins: $x0, $x1
+  ; DAGISEL-DARWIN-NEXT: {{  $}}
+  ; DAGISEL-DARWIN-NEXT:   [[COPY:%[0-9]+]]:gpr64noip = COPY $x1
+  ; DAGISEL-DARWIN-NEXT:   [[COPY1:%[0-9]+]]:gpr64 = COPY $x0
+  ; DAGISEL-DARWIN-NEXT:   $x16 = COPY [[COPY1]]
+  ; DAGISEL-DARWIN-NEXT:   AUTx16x17 2, 0, [[COPY]], implicit-def $x16, implicit-def dead $x17, implicit-def dead $nzcv, implicit $x16
+  ; DAGISEL-DARWIN-NEXT:   [[COPY2:%[0-9]+]]:gpr64all = COPY $x16
+  ; DAGISEL-DARWIN-NEXT:   $x0 = COPY [[COPY2]]
+  ; DAGISEL-DARWIN-NEXT:   RET_ReallyLR implicit $x0
+  ;
+  ; GISEL-DARWIN-LABEL: name: autxmxn_earlyclobbered_scratch
+  ; GISEL-DARWIN: bb.1.entry:
+  ; GISEL-DARWIN-NEXT:   liveins: $x0, $x1
+  ; GISEL-DARWIN-NEXT: {{  $}}
+  ; GISEL-DARWIN-NEXT:   [[COPY:%[0-9]+]]:gpr64all = COPY $x0
+  ; GISEL-DARWIN-NEXT:   [[COPY1:%[0-9]+]]:gpr64noip = COPY $x1
+  ; GISEL-DARWIN-NEXT:   $x16 = COPY [[COPY]]
+  ; GISEL-DARWIN-NEXT:   $x17 = IMPLICIT_DEF
+  ; GISEL-DARWIN-NEXT:   AUTx16x17 2, 0, [[COPY1]], implicit-def $x16, implicit-def $x17, implicit-def dead $nzcv, implicit $x16
+  ; GISEL-DARWIN-NEXT:   [[COPY2:%[0-9]+]]:gpr64 = COPY $x16
+  ; GISEL-DARWIN-NEXT:   $x0 = COPY [[COPY2]]
+  ; GISEL-DARWIN-NEXT:   RET_ReallyLR implicit $x0
+  ;
+  ; DAGISEL-GNU-LABEL: name: autxmxn_earlyclobbered_scratch
+  ; DAGISEL-GNU: bb.0.entry:
+  ; DAGISEL-GNU-NEXT:   liveins: $x0, $x1
+  ; DAGISEL-GNU-NEXT: {{  $}}
+  ; DAGISEL-GNU-NEXT:   [[COPY:%[0-9]+]]:gpr64 = COPY $x1
+  ; DAGISEL-GNU-NEXT:   [[COPY1:%[0-9]+]]:gpr64 = COPY $x0
+  ; DAGISEL-GNU-NEXT:   %2:gpr64, early-clobber %3:gpr64common = AUTxMxN [[COPY1]], 2, 0, [[COPY]], implicit-def dead $nzcv
+  ; DAGISEL-GNU-NEXT:   $x0 = COPY %2
+  ; DAGISEL-GNU-NEXT:   RET_ReallyLR implicit $x0
+  ;
+  ; GISEL-GNU-LABEL: name: autxmxn_earlyclobbered_scratch
+  ; GISEL-GNU: bb.1.entry:
+  ; GISEL-GNU-NEXT:   liveins: $x0, $x1
+  ; GISEL-GNU-NEXT: {{  $}}
+  ; GISEL-GNU-NEXT:   [[COPY:%[0-9]+]]:gpr64 = COPY $x0
+  ; GISEL-GNU-NEXT:   [[COPY1:%[0-9]+]]:gpr64 = COPY $x1
+  ; GISEL-GNU-NEXT:   %2:gpr64, early-clobber %3:gpr64common = AUTxMxN [[COPY]], 2, 0, [[COPY1]], implicit-def dead $nzcv
+  ; GISEL-GNU-NEXT:   $x0 = COPY %2
+  ; GISEL-GNU-NEXT:   RET_ReallyLR implicit $x0
+entry:
+  %auted = call i64 @llvm.ptrauth.auth(i64 %addr, i32 2, i64 %disc)
+  ret i64 %auted
+}


        


More information about the llvm-branch-commits mailing list