[llvm] AArch64: Fix MIPeepholeOpt null dereference on undef source operands (PR #218291)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 23 14:35:11 PDT 2026


https://github.com/arsenm created https://github.com/llvm/llvm-project/pull/218291

Fix unchecked getUniqueVRegDef calls. This is also an SSA pass, and has
no reason to use getUniqueVRegDef over getVRegDef, so also make that
change.

Co-Authored-By: Claude <noreply at anthropic.com> (Claude Opus 4.8)

>From dbd185ac2440298e886f6f86f2332989bb24fb42 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Sun, 23 Aug 2026 23:31:13 +0200
Subject: [PATCH] AArch64: Fix MIPeepholeOpt null dereference on undef source
 operands

Fix unchecked getUniqueVRegDef calls. This is also an SSA pass, and has
no reason to use getUniqueVRegDef over getVRegDef, so also make that
change.

Co-Authored-By: Claude <noreply at anthropic.com> (Claude Opus 4.8)
---
 .../Target/AArch64/AArch64MIPeepholeOpt.cpp   | 10 ++--
 .../AArch64/mipeephole-undef-operand.mir      | 57 +++++++++++++++++++
 2 files changed, 63 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/mipeephole-undef-operand.mir

diff --git a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
index a292aee81e615..f6fdc63970408 100644
--- a/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
+++ b/llvm/lib/Target/AArch64/AArch64MIPeepholeOpt.cpp
@@ -512,8 +512,10 @@ bool AArch64MIPeepholeOptImpl::visitADDSSUBS(OpcodePair PosOpcs,
           return std::nullopt;
         // Check conditional uses last since it is expensive for scanning
         // proceeding instructions
-        MachineInstr &SrcMI = *MRI->getUniqueVRegDef(MI.getOperand(1).getReg());
-        std::optional<UsedNZCV> NZCVUsed = examineCFlagsUse(SrcMI, MI, *TRI);
+        MachineInstr *SrcMI = MRI->getVRegDef(MI.getOperand(1).getReg());
+        if (!SrcMI)
+          return std::nullopt;
+        std::optional<UsedNZCV> NZCVUsed = examineCFlagsUse(*SrcMI, MI, *TRI);
         if (!NZCVUsed || NZCVUsed->C || NZCVUsed->V)
           return std::nullopt;
         return OP;
@@ -763,8 +765,8 @@ bool AArch64MIPeepholeOptImpl::visitINSvi64lane(MachineInstr &MI) {
   //  %6:fpr128 = IMPLICIT_DEF
   //  %5:fpr128 = INSERT_SUBREG %6:fpr128(tied-def 0), killed %1:fpr64, %subreg.dsub
   //  %7:fpr128 = INSvi64lane %5:fpr128(tied-def 0), 1, killed %3:fpr128, 0
-  MachineInstr *Low64MI = MRI->getUniqueVRegDef(MI.getOperand(1).getReg());
-  if (Low64MI->getOpcode() != AArch64::INSERT_SUBREG)
+  MachineInstr *Low64MI = MRI->getVRegDef(MI.getOperand(1).getReg());
+  if (!Low64MI || Low64MI->getOpcode() != AArch64::INSERT_SUBREG)
     return false;
   Low64MI = MRI->getUniqueVRegDef(Low64MI->getOperand(2).getReg());
   if (!Low64MI || !is64bitDefwithZeroHigh64bit(Low64MI, MRI, TII))
diff --git a/llvm/test/CodeGen/AArch64/mipeephole-undef-operand.mir b/llvm/test/CodeGen/AArch64/mipeephole-undef-operand.mir
new file mode 100644
index 0000000000000..d68ced796aa1e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/mipeephole-undef-operand.mir
@@ -0,0 +1,57 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=aarch64 -run-pass=aarch64-mi-peephole-opt -o - %s | FileCheck %s
+
+# Make sure AArch64MIPeepholeOpt does not crash on undef operands
+# without a def.
+
+---
+name:            insvi64lane_undef
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $q1
+
+    ; CHECK-LABEL: name: insvi64lane_undef
+    ; CHECK: liveins: $q1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr128 = COPY $q1
+    ; CHECK-NEXT: [[INSvi64lane:%[0-9]+]]:fpr128 = INSvi64lane undef %2:fpr128, 1, [[COPY]], 1
+    ; CHECK-NEXT: $q0 = COPY [[INSvi64lane]]
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %1:fpr128 = COPY $q1
+    %2:fpr128 = INSvi64lane undef %0:fpr128, 1, %1, 1
+    $q0 = COPY %2
+    RET_ReallyLR implicit $q0
+...
+---
+name:            subsxrr_undef
+tracksRegLiveness: true
+body:             |
+  ; CHECK-LABEL: name: subsxrr_undef
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.1(0x40000000), %bb.2(0x40000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOVi64imm:%[0-9]+]]:gpr64 = MOVi64imm 1052673
+  ; CHECK-NEXT:   [[SUBSXrr:%[0-9]+]]:gpr64 = SUBSXrr undef %2:gpr64, killed [[MOVi64imm]], implicit-def $nzcv
+  ; CHECK-NEXT:   Bcc 1, %bb.2, implicit $nzcv
+  ; CHECK-NEXT:   B %bb.1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   RET_ReallyLR
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   RET_ReallyLR
+  bb.0:
+    successors: %bb.1, %bb.2
+
+    %1:gpr64 = MOVi64imm 1052673
+    %2:gpr64 = SUBSXrr undef %0:gpr64, killed %1, implicit-def $nzcv
+    Bcc 1, %bb.2, implicit $nzcv
+    B %bb.1
+
+  bb.1:
+    RET_ReallyLR
+
+  bb.2:
+    RET_ReallyLR
+...



More information about the llvm-commits mailing list