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 @@ -245,13 +245,17 @@ /// (MachineInstr::hasComplexRegiterTies can determine if it's needed). /// \param TiedOperandIdx - if we need to print register ties this needs to /// provide the index of the tied register. If not, it will be ignored. + /// \param IsOperandSubregIdx - 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. /// \param TRI - provide more target-specific information to the printer. /// Unlike the previous function, this one will not try and get the /// information from it's parent. /// \param IntrinsicInfo - same as \p TRI. void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint, bool PrintDef, bool ShouldPrintRegisterTies, - unsigned TiedOperandIdx, const TargetRegisterInfo *TRI, + unsigned TiedOperandIdx, bool IsOperandSubregIdx, + const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const; void dump() const; Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -854,21 +854,17 @@ 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(); + bool IsOperandSubregIdx = Op.isImm() && MI.isOperandSubregIdx(OpIdx); Op.print(OS, MST, TypeToPrint, PrintDef, ShouldPrintRegisterTies, - TiedOperandIdx, TRI, TII); + TiedOperandIdx, IsOperandSubregIdx, TRI, TII); break; } - case MachineOperand::MO_Immediate: - if (MI.isOperandSubregIdx(OpIdx)) - OS << "%subreg." << TRI->getSubRegIndexName(Op.getImm()); - else - OS << Op.getImm(); - 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 @@ -1259,9 +1259,11 @@ OS << ", "; LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{}; unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + bool IsOperandSubregIdx = + getOperand(StartOp).isImm() && isOperandSubregIdx(StartOp); getOperand(StartOp).print(OS, MST, TypeToPrint, /*PrintDef=*/false, - ShouldPrintRegisterTies, TiedOperandIdx, TRI, - IntrinsicInfo); + ShouldPrintRegisterTies, TiedOperandIdx, + IsOperandSubregIdx, TRI, IntrinsicInfo); unsigned Reg = getOperand(StartOp).getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) VirtRegs.push_back(Reg); @@ -1290,9 +1292,11 @@ const unsigned OpIdx = InlineAsm::MIOp_AsmString; LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{}; unsigned TiedOperandIdx = getTiedOperandIdx(OpIdx); + bool IsOperandSubregIdx = + getOperand(OpIdx).isImm() && isOperandSubregIdx(OpIdx); getOperand(OpIdx).print(OS, MST, TypeToPrint, /*PrintDef=*/true, - ShouldPrintRegisterTies, TiedOperandIdx, TRI, - IntrinsicInfo); + ShouldPrintRegisterTies, TiedOperandIdx, + IsOperandSubregIdx, TRI, IntrinsicInfo); // Print HasSideEffects, MayLoad, MayStore, IsAlignStack unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); @@ -1338,8 +1342,10 @@ else { LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; unsigned TiedOperandIdx = getTiedOperandIdx(i); + bool IsOperandSubregIdx = MO.isImm() && isOperandSubregIdx(i); MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, - ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo); + ShouldPrintRegisterTies, TiedOperandIdx, IsOperandSubregIdx, + TRI, IntrinsicInfo); } } else if (TRI && (isInsertSubreg() || isRegSequence() || (isSubregToReg() && i == 3)) && MO.isImm()) { @@ -1405,8 +1411,9 @@ } else { LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; unsigned TiedOperandIdx = getTiedOperandIdx(i); + bool IsOperandSubregIdx = MO.isImm() && isOperandSubregIdx(i); MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, ShouldPrintRegisterTies, - TiedOperandIdx, TRI, IntrinsicInfo); + TiedOperandIdx, IsOperandSubregIdx, TRI, IntrinsicInfo); } } Index: lib/CodeGen/MachineOperand.cpp =================================================================== --- lib/CodeGen/MachineOperand.cpp +++ lib/CodeGen/MachineOperand.cpp @@ -351,13 +351,14 @@ ModuleSlotTracker DummyMST(nullptr); print(OS, DummyMST, LLT{}, /*PrintDef=*/false, /*ShouldPrintRegisterTies=*/true, - /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); + /*TiedOperandIdx=*/0, /*IsOperandSubregIdx=*/false, TRI, IntrinsicInfo); } void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, LLT TypeToPrint, bool PrintDef, bool ShouldPrintRegisterTies, unsigned TiedOperandIdx, + bool IsOperandSubregIdx, const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const { switch (getType()) { @@ -407,8 +408,16 @@ break; } case MachineOperand::MO_Immediate: - OS << getImm(); + if (IsOperandSubregIdx) { + OS << "%subreg."; + if (TRI) + OS << TRI->getSubRegIndexName(getImm()); + else + OS << getImm(); + } else + OS << getImm(); break; + case MachineOperand::MO_CImmediate: getCImm()->getValue().print(OS, false); break; 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,24 @@ 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); + MO.print(OS, DummyMST, LLT{}, /*PrintDef=*/false, + /*ShouldPrintRegisterTies=*/false, + /*TiedOperandIdx=*/0, /*IsOperandSubregIdx=*/true, nullptr, nullptr); + ASSERT_TRUE(OS.str() == "%subreg.3"); +} + } // end namespace