[llvm] c68c176 - [AArch64][PAC] Reset `killed` operand flags in outlined functions (#221041)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 6 04:51:23 PDT 2026


Author: Anatoly Trosinenko
Date: 2026-10-06T11:51:15Z
New Revision: c68c1767aa5f19eedff3024e922f71976669ee25

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

LOG: [AArch64][PAC] Reset `killed` operand flags in outlined functions (#221041)

Presently, MachineOutliner does not take `killed` operand flags into
account when merging instruction sequences. While it sounds perfectly
reasonable not to inhibit merging of the instruction sequences that only
differ in `killed` flags (for N flags there is technically 2^N valid
ways to drop some subset of them), copying these flags from an
arbitrarily chosen representative instruction may result in incorrect
codegen of PAuth-related pseudo instructions on AArch64.

To keep `killed` flags conservatively correct as if `OUTLINED_FUNCTION`s
are virtually re-inserted at every call site, this patch takes the
simplest approach of resetting every `killed` flag inside the outlined
functions.

Added: 
    llvm/test/CodeGen/AArch64/machine-outliner-operand-flags.mir

Modified: 
    llvm/lib/CodeGen/MachineOutliner.cpp
    llvm/test/CodeGen/AArch64/machine-outliner-bundle.mir
    llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp
index 171705f1d68d5..7211059279814 100644
--- a/llvm/lib/CodeGen/MachineOutliner.cpp
+++ b/llvm/lib/CodeGen/MachineOutliner.cpp
@@ -958,11 +958,14 @@ MachineFunction *MachineOutliner::createOutlinedFunction(
       MachineInstr &NewMI = TII.duplicate(MBB, MBB.end(), MI);
       NewMI.dropMemRefs(MF);
       NewMI.setDebugLoc(DL);
-      // Also clear debug locations on any bundled instructions.
+      NewMI.clearKillInfo();
+      // Also clear debug locations and kill info on any bundled instructions.
       if (NewMI.isBundledWithSucc()) {
         auto BundleEnd = getBundleEnd(NewMI.getIterator());
-        for (auto I = std::next(NewMI.getIterator()); I != BundleEnd; ++I)
+        for (auto I = std::next(NewMI.getIterator()); I != BundleEnd; ++I) {
           I->setDebugLoc(DL);
+          I->clearKillInfo();
+        }
       }
     }
   }

diff  --git a/llvm/test/CodeGen/AArch64/machine-outliner-bundle.mir b/llvm/test/CodeGen/AArch64/machine-outliner-bundle.mir
index 1dd5b0811bdfb..50d26557e1947 100644
--- a/llvm/test/CodeGen/AArch64/machine-outliner-bundle.mir
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-bundle.mir
@@ -5,7 +5,7 @@
 # CHECK-NOT: name:
 # CHECK: BUNDLE implicit-def $z3, implicit-def $q3, implicit-def $d3, implicit-def $s3, implicit-def $h3, implicit-def $b3, implicit $z19, implicit $p0, implicit $z16 {
 # CHECK:     $z3 = MOVPRFX_ZZ $z19
-# CHECK:     $z3 = FMUL_ZPmZ_S renamable $p0, killed $z3, renamable $z16
+# CHECK:     $z3 = FMUL_ZPmZ_S renamable $p0, $z3, renamable $z16
 # CHECK: }
 
 ---

diff  --git a/llvm/test/CodeGen/AArch64/machine-outliner-operand-flags.mir b/llvm/test/CodeGen/AArch64/machine-outliner-operand-flags.mir
new file mode 100644
index 0000000000000..b73d60107c834
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/machine-outliner-operand-flags.mir
@@ -0,0 +1,126 @@
+# RUN: llc -mtriple=aarch64 -run-pass=machine-outliner -verify-machineinstrs -o - %s | FileCheck %s
+
+# Make sure `killed` operand flags would be correct if OUTLINED_FUNCTION is
+# virtually re-inserted at its call site. This is important for correct emission
+# of PAuth-related pseudo instructions by AArch64AsmPrinter.
+# Current implementation ensures this property by simply clearing all `killed`
+# flags on the operands of the instructions contained in `OUTLINED_FUNCTION`s.
+
+--- |
+  define void @test_pac_disc(ptr %p) #0 { ret void }
+  define void @test_not_exactly_cloned_flags(i64 %a, i64 %b) #0 { ret void }
+  define void @test_instruction_bundles(i64 %a, i64 %b) #0 { ret void }
+  attributes #0 = { noredzone optsize minsize }
+...
+---
+# Test PAC pseudo that may actually result in incorrect codegen if `killed` flag
+# is passed to AsmPrinter where it should not.
+
+name: test_pac_disc
+tracksRegLiveness: true
+body:             |
+    bb.0:
+        ; CHECK-LABEL: name: test_pac_disc
+        ; CHECK:         $x1 = ORRXrs $xzr, $x0, 0
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_0
+        ; CHECK-NEXT:    $x1 = ORRXrs $xzr, $x0, 0
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_0
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_0
+        ; CHECK-NEXT:    RET undef $lr
+
+        liveins: $x0
+        $x1 = ORRXrs $xzr, $x0, 0
+        $x2 = LDRXui $x1, 0
+        $x2 = PAC $x2, 2, 12345, killed $x1, implicit-def dead $x16, implicit-def dead $x17
+        STRXui $x2, $x0, 0
+        $x1 = ORRXrs $xzr, $x0, 0
+        $x2 = LDRXui $x1, 0
+        $x2 = PAC $x2, 2, 12345, $x1, implicit-def dead $x16, implicit-def dead $x17
+        STRXui $x2, $x0, 0
+        $x2 = LDRXui $x1, 0
+        $x2 = PAC $x2, 2, 12345, killed $x1, implicit-def dead $x16, implicit-def dead $x17
+        STRXui $x2, $x0, 0
+        RET undef $lr
+...
+---
+# Make sure `killed` flags are intentionally reset: in the original function, there
+# is no such ADDXrs instruction that could have been cloned as-is (without clearing
+# the `killed` flags) to OUTLINED_FUNCTION.
+
+name: test_not_exactly_cloned_flags
+tracksRegLiveness: true
+body:             |
+    bb.0:
+        ; CHECK-LABEL: name: test_not_exactly_cloned_flags
+        ; CHECK:         BL @OUTLINED_FUNCTION_2,
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_2,
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_2,
+        ; CHECK-NEXT:    RET undef $lr
+
+        liveins: $x0, $x1
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        $x4 = ADDXrs killed $x2, killed $x3, 0
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        $x4 = ADDXrs killed $x2, $x3, 0
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        $x4 = ADDXrs $x2, killed $x3, 0
+        RET undef $lr
+...
+---
+# Make sure `killed` flags are reset inside instruction bundles.
+
+name: test_instruction_bundles
+tracksRegLiveness: true
+body:             |
+    bb.0:
+        ; CHECK-LABEL: name: test_instruction_bundles
+        ; CHECK:         BL @OUTLINED_FUNCTION_1,
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_1,
+        ; CHECK-NEXT:    BL @OUTLINED_FUNCTION_1,
+        ; CHECK-NEXT:    RET undef $lr
+
+        liveins: $x0, $x1
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        BUNDLE implicit-def $x4, implicit $x2, implicit $x3 {
+          HINT 0
+          $x4 = ADDXrs killed $x2, killed $x3, 0
+        }
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        BUNDLE implicit-def $x4, implicit $x2, implicit $x3 {
+          HINT 0
+          $x4 = ADDXrs killed $x2, $x3, 0
+        }
+        $x2 = ORRXrs $xzr, $x0, 0
+        $x3 = ORRXrs $xzr, $x1, 0
+        BUNDLE implicit-def $x4, implicit $x2, implicit $x3 {
+          HINT 0
+          $x4 = ADDXrs $x2, killed $x3, 0
+        }
+        RET undef $lr
+...
+
+# CHECK-LABEL: name: OUTLINED_FUNCTION_0
+# CHECK:         $x2 = LDRXui $x1, 0
+# CHECK-NEXT:    $x2 = PAC $x2, 2, 12345, $x1, implicit-def dead $x16, implicit-def dead $x17
+# CHECK-NEXT:    STRXui $x2, $x0, 0
+# CHECK-NEXT:    RET $lr
+
+# CHECK-LABEL: name: OUTLINED_FUNCTION_1
+# CHECK:         $x2 = ORRXrs $xzr, $x0, 0
+# CHECK-NEXT:    $x3 = ORRXrs $xzr, $x1, 0
+# CHECK-NEXT:    BUNDLE implicit-def $x4, implicit $x2, implicit $x3 {
+# CHECK-NEXT:      HINT 0
+# CHECK-NEXT:      $x4 = ADDXrs $x2, $x3, 0
+# CHECK-NEXT:    }
+# CHECK-NEXT:    RET $lr
+
+# CHECK-LABEL: name: OUTLINED_FUNCTION_2
+# CHECK:         $x2 = ORRXrs $xzr, $x0, 0
+# CHECK-NEXT:    $x3 = ORRXrs $xzr, $x1, 0
+# CHECK-NEXT:    $x4 = ADDXrs $x2, $x3, 0
+# CHECK-NEXT:    RET $lr

diff  --git a/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir
index a31cf7ea035fe..a64791c942544 100644
--- a/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir
+++ b/llvm/test/CodeGen/ARM/machine-outliner-stack-fixup-thumb.mir
@@ -207,5 +207,5 @@ body:             |
     ;CHECK-NEXT: tBX_RET 14 /* CC::al */, $noreg
 
     ;CHECK: name:           OUTLINED_FUNCTION_[[SHARED]]
-    ;CHECK: $r0 = tMOVr killed $r1, 14 /* CC::al */, $noreg
+    ;CHECK: $r0 = tMOVr $r1, 14 /* CC::al */, $noreg
     ;CHECK-NEXT: tTAILJMPdND @foo, 14 /* CC::al */, $noreg, implicit $sp


        


More information about the llvm-commits mailing list