[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