Index: docs/MIRLangRef.rst =================================================================== --- docs/MIRLangRef.rst +++ docs/MIRLangRef.rst @@ -430,6 +430,35 @@ %eax = MOV32ri -42 +An immediate operand is also used to represent a subregister index when the +machine instruction has one of the following opcodes: + +- ``EXTRACT_SUBREG`` + +- ``INSERT_SUBREG`` + +- ``REG_SEQUENCE`` + +- ``SUBREG_TO_REG`` + +In case this is true, the Machine Operand is printed according to the target. + +For example: + +In AArch64RegisterInfo.td: + +.. code-block:: text + + def sub_32 : SubRegIndex<32>; + +If the third operand is an immediate with the value ``15`` (target-dependent +value), based on the instruction's opcode and the operand's index the operand +will be printed as ``%subreg.sub_32``: + +.. code-block:: text + + %1:gpr64 = SUBREG_TO_REG 0, %0, %subreg.sub_32 + .. TODO: Describe the CIMM (Rare) and FPIMM immediate operands. .. _register-operands: Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -227,6 +227,13 @@ /// void clearParent() { ParentMI = nullptr; } + /// Print a subreg index operand. + /// MO_Immediate operands can also be subreg idices. If it's the case, the + /// subreg index name will be printed. MachineInstr::isOperandSubregIdx can be + /// called to check this. + static void printSubregIdx(raw_ostream &OS, uint64_t Index, + const TargetRegisterInfo *TRI); + /// Print the MachineOperand to \p os. /// Providing a valid \p TRI and \p IntrinsicInfo results in a more /// target-specific printing. If \p TRI and \p IntrinsicInfo are null, the Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -854,21 +854,19 @@ const MachineOperand &Op = MI.getOperand(OpIdx); printTargetFlags(Op); switch (Op.getType()) { - case MachineOperand::MO_Register: { + case MachineOperand::MO_Register: + case MachineOperand::MO_Immediate: { unsigned TiedOperandIdx = 0; - if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef()) + if (ShouldPrintRegisterTies && Op.isReg() && Op.isTied() && !Op.isDef()) TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx); const TargetIntrinsicInfo *TII = MI.getMF()->getTarget().getIntrinsicInfo(); - Op.print(OS, MST, TypeToPrint, PrintDef, ShouldPrintRegisterTies, - TiedOperandIdx, TRI, TII); - break; - } - case MachineOperand::MO_Immediate: - if (MI.isOperandSubregIdx(OpIdx)) - OS << "%subreg." << TRI->getSubRegIndexName(Op.getImm()); + if (Op.isImm() && MI.isOperandSubregIdx(OpIdx)) + MachineOperand::printSubregIdx(OS, Op.getImm(), TRI); else - OS << Op.getImm(); + Op.print(OS, MST, TypeToPrint, PrintDef, ShouldPrintRegisterTies, + TiedOperandIdx, TRI, TII); break; + } case MachineOperand::MO_CImmediate: Op.getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; Index: lib/CodeGen/MachineInstr.cpp =================================================================== --- lib/CodeGen/MachineInstr.cpp +++ lib/CodeGen/MachineInstr.cpp @@ -1405,8 +1405,11 @@ } else { LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; unsigned TiedOperandIdx = getTiedOperandIdx(i); - MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, ShouldPrintRegisterTies, - TiedOperandIdx, TRI, IntrinsicInfo); + if (MO.isImm() && isOperandSubregIdx(i)) + MachineOperand::printSubregIdx(OS, MO.getImm(), TRI); + else + MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo); } } Index: lib/CodeGen/MachineOperand.cpp =================================================================== --- lib/CodeGen/MachineOperand.cpp +++ lib/CodeGen/MachineOperand.cpp @@ -345,6 +345,15 @@ } } +void MachineOperand::printSubregIdx(raw_ostream &OS, uint64_t Index, + const TargetRegisterInfo *TRI) { + OS << "%subreg."; + if (TRI) + OS << TRI->getSubRegIndexName(Index); + else + OS << Index; +} + void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const { tryToGetTargetInfo(*this, TRI, IntrinsicInfo); Index: unittests/CodeGen/MachineOperandTest.cpp =================================================================== --- unittests/CodeGen/MachineOperandTest.cpp +++ unittests/CodeGen/MachineOperandTest.cpp @@ -9,6 +9,7 @@ #include "llvm/ADT/ilist_node.h" #include "llvm/CodeGen/MachineOperand.h" +#include "llvm/IR/ModuleSlotTracker.h" #include "llvm/Support/raw_ostream.h" #include "gtest/gtest.h" @@ -76,4 +77,22 @@ ASSERT_TRUE(OS.str() == "%physreg1.subreg5"); } +TEST(MachineOperandTest, PrintSubRegIndex) { + // Create a MachineOperand with an immediate and print it as a subreg index. + MachineOperand MO = MachineOperand::CreateImm(3); + + // Checking some preconditions on the newly created + // MachineOperand. + ASSERT_TRUE(MO.isImm()); + ASSERT_TRUE(MO.getImm() == 3); + + // Print a MachineOperand containing a SubRegIdx. Here we check that without a + // TRI and IntrinsicInfo we can print the operand as a subreg index. + std::string str; + raw_string_ostream OS(str); + ModuleSlotTracker DummyMST(nullptr); + MachineOperand::printSubregIdx(OS, MO.getImm(), nullptr); + ASSERT_TRUE(OS.str() == "%subreg.3"); +} + } // end namespace