[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