[llvm] Hexagon: Fix early if-conversion crash on an undef PHI operand (PR #216815)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 20 10:27:35 PDT 2026


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/216815

>From 5822426dcba646c66795965428a7841583e05f88 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 17 Aug 2026 19:28:08 +0200
Subject: [PATCH] Hexagon: Fix early if-conversion crash on an undef PHI
 operand

Found by AI while working on something else.

Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
 .../lib/Target/Hexagon/HexagonEarlyIfConv.cpp |  6 +--
 .../CodeGen/Hexagon/early-if-phi-undef.mir    | 42 +++++++++++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/CodeGen/Hexagon/early-if-phi-undef.mir

diff --git a/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp b/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp
index ff3aa61dd0400..7a3d8b64b247e 100644
--- a/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonEarlyIfConv.cpp
@@ -398,10 +398,10 @@ bool HexagonEarlyIfConversion::usesUndefVReg(const MachineInstr *MI) const {
     Register R = MO.getReg();
     if (!R.isVirtual())
       continue;
+    // "Undefined" virtual registers are usually defined via IMPLICIT_DEF, but
+    // an undef use operand may have no reaching def at all.
     const MachineInstr *DefI = MRI->getVRegDef(R);
-    // "Undefined" virtual registers are actually defined via IMPLICIT_DEF.
-    assert(DefI && "Expecting a reaching def in MRI");
-    if (DefI->isImplicitDef())
+    if (!DefI || DefI->isImplicitDef())
       return true;
   }
   return false;
diff --git a/llvm/test/CodeGen/Hexagon/early-if-phi-undef.mir b/llvm/test/CodeGen/Hexagon/early-if-phi-undef.mir
new file mode 100644
index 0000000000000..06c634772cb30
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/early-if-phi-undef.mir
@@ -0,0 +1,42 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=hexagon -run-pass=hexagon-early-if -o - %s | FileCheck %s
+
+# An undef PHI incoming value has no reaching def and must not be
+# dereferenced while checking whether the flow pattern is convertible.
+
+---
+name: undef_phi_operand
+tracksRegLiveness: true
+body: |
+  ; CHECK-LABEL: name: undef_phi_operand
+  ; CHECK: bb.0:
+  ; CHECK-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; CHECK-NEXT:   liveins: $r0, $r1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:intregs = COPY $r0
+  ; CHECK-NEXT:   [[COPY1:%[0-9]+]]:intregs = COPY $r1
+  ; CHECK-NEXT:   [[C2_cmpeq:%[0-9]+]]:predregs = C2_cmpeq [[COPY]], [[COPY1]]
+  ; CHECK-NEXT:   J2_jumpf [[C2_cmpeq]], %bb.2, implicit-def $pc
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1:
+  ; CHECK-NEXT:   successors: %bb.2(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[A2_addi:%[0-9]+]]:intregs = A2_addi [[COPY]], 1
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2:
+  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:intregs = PHI [[COPY]], %bb.0, undef %5:intregs, %bb.1
+  ; CHECK-NEXT:   $r0 = COPY [[PHI]]
+  ; CHECK-NEXT:   J2_jumpr $r31, implicit $r0, implicit-def $pc
+  bb.0:
+    liveins: $r0, $r1
+    %0:intregs = COPY $r0
+    %1:intregs = COPY $r1
+    %3:predregs = C2_cmpeq %0, %1
+    J2_jumpf %3, %bb.2, implicit-def $pc
+  bb.1:
+    %4:intregs = A2_addi %0, 1
+  bb.2:
+    %6:intregs = PHI %0, %bb.0, undef %5:intregs, %bb.1
+    $r0 = COPY %6
+    J2_jumpr $r31, implicit $r0, implicit-def $pc
+...



More information about the llvm-commits mailing list