[llvm] [NFC][CodeGen] Refactor register operand parsing in MI parser (PR #181748)

Rahul Joshi via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 16 13:24:40 PST 2026


https://github.com/jurahul created https://github.com/llvm/llvm-project/pull/181748

Refactor register operand parsing to factor out duplicated type parsing code into a lambda. Additionally, fix the MI LangRef to fix the syntax for a register operand to match what the parser supports.

>From 2fd1bacc0809c651aefbf107dec90ae00cb02f29 Mon Sep 17 00:00:00 2001
From: Rahul Joshi <rjoshi at nvidia.com>
Date: Mon, 16 Feb 2026 12:56:59 -0800
Subject: [PATCH] [NFC][CodeGen] Refactor register operand parsing in MI parser

Refactor register operand parsing to factor out duplicated type
parsing code into a lambda. Additionally, fix the MI LangRef to
fix the syntax for a register operand to match what the parser
supports.
---
 llvm/docs/MIRLangRef.rst                |  7 ++-
 llvm/lib/CodeGen/MIRParser/MIParser.cpp | 65 +++++++++++--------------
 2 files changed, 34 insertions(+), 38 deletions(-)

diff --git a/llvm/docs/MIRLangRef.rst b/llvm/docs/MIRLangRef.rst
index f7df57d05baa0..a2ee28151b354 100644
--- a/llvm/docs/MIRLangRef.rst
+++ b/llvm/docs/MIRLangRef.rst
@@ -523,7 +523,7 @@ The full syntax of a register operand is shown below:
 
 .. code-block:: text
 
-    [<flags>] <register> [ :<subregister-idx-name> ] [ (tied-def <tied-op>) ]
+    [<flags>] <register> [ .<subregister-idx-name> ] [ :<register-class> ] [ (tied-def <tied-op>) ] [ (<type>) ]
 
 This example shows an instance of the X86 ``XOR32rr`` instruction that has
 5 register operands with different register flags:
@@ -532,6 +532,9 @@ This example shows an instance of the X86 ``XOR32rr`` instruction that has
 
   dead $eax = XOR32rr undef $eax, undef $eax, implicit-def dead $eflags, implicit-def $al
 
+Note that subregister-index, register-class and type cannot be specified for
+physical registers. Additionally, tied-def can only be specified for a use.
+
 .. _register-flags:
 
 Register Flags
@@ -602,7 +605,7 @@ lower bits from the 32-bit virtual register 0 to the 8-bit virtual register 1:
 
 .. code-block:: text
 
-    %1 = COPY %0:sub_8bit
+    %1 = COPY %0.sub_8bit
 
 The names of the subregister indices are target specific, and are typically
 defined in the target's ``*RegisterInfo.td`` file.
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 9329adcb995b8..563f6c22c40f2 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -1728,9 +1728,7 @@ bool MIParser::parseRegisterTiedDefIndex(unsigned &TiedDefIdx) {
   if (getUnsigned(TiedDefIdx))
     return true;
   lex();
-  if (expectAndConsume(MIToken::rparen))
-    return true;
-  return false;
+  return expectAndConsume(MIToken::rparen);
 }
 
 bool MIParser::assignRegisterTies(MachineInstr &MI,
@@ -1800,49 +1798,44 @@ bool MIParser::parseRegisterOperand(MachineOperand &Dest,
         return true;
   }
   MachineRegisterInfo &MRI = MF.getRegInfo();
-  if (!hasRegState(Flags, RegState::Define)) {
-    if (consumeIfPresent(MIToken::lparen)) {
-      unsigned Idx;
-      if (!parseRegisterTiedDefIndex(Idx))
-        TiedDefIdx = Idx;
-      else {
-        // Try a redundant low-level type.
-        LLT Ty;
-        if (parseLowLevelType(Token.location(), Ty))
-          return error("expected tied-def or low-level type after '('");
-
-        if (expectAndConsume(MIToken::rparen))
-          return true;
-
-        if (MRI.getType(Reg).isValid() && MRI.getType(Reg) != Ty)
-          return error("inconsistent type for generic virtual register");
-
-        MRI.setRegClassOrRegBank(Reg, static_cast<RegisterBank *>(nullptr));
-        MRI.setType(Reg, Ty);
-        MRI.noteNewVirtualRegister(Reg);
-      }
-    }
-  } else if (consumeIfPresent(MIToken::lparen)) {
-    // Virtual registers may have a tpe with GlobalISel.
-    if (!Reg.isVirtual())
-      return error("unexpected type on physical register");
-
+  auto ParseType = [&, this]() -> bool {
     LLT Ty;
-    if (parseLowLevelType(Token.location(), Ty))
-      return true;
+    auto TyLoc = Token.location();
+    // If type parsing fails, forwad the parse error for defs.
+    if (parseLowLevelType(TyLoc, Ty))
+      return IsDef ? true
+                   : error("expected tied-def or low-level type after '('");
 
     if (expectAndConsume(MIToken::rparen))
       return true;
 
+    if (!Reg.isVirtual())
+      return error(TyLoc, "unexpected type on physical register");
+
     if (MRI.getType(Reg).isValid() && MRI.getType(Reg) != Ty)
       return error("inconsistent type for generic virtual register");
 
     MRI.setRegClassOrRegBank(Reg, static_cast<RegisterBank *>(nullptr));
     MRI.setType(Reg, Ty);
-  } else if (Reg.isVirtual()) {
-    // Generic virtual registers must have a type.
-    // If we end up here this means the type hasn't been specified and
-    // this is bad!
+    MRI.noteNewVirtualRegister(Reg);
+    return false;
+  };
+
+  if (consumeIfPresent(MIToken::lparen)) {
+    // For a def, we only expect a type.
+    if (IsDef) {
+      if (ParseType())
+        return true;
+    } else {
+      // For use we expect either a type or a tied-def.
+      unsigned Idx;
+      if (!parseRegisterTiedDefIndex(Idx))
+        TiedDefIdx = Idx;
+      else if (ParseType())
+        return true;
+    }
+  } else if (IsDef && Reg.isVirtual()) {
+    // Generic virtual registers defs must have a type.
     if (RegInfo->Kind == VRegInfo::GENERIC ||
         RegInfo->Kind == VRegInfo::REGBANK)
       return error("generic virtual registers must have a type");



More information about the llvm-commits mailing list