Index: include/llvm/CodeGen/MachineInstr.h =================================================================== --- include/llvm/CodeGen/MachineInstr.h +++ include/llvm/CodeGen/MachineInstr.h @@ -44,6 +44,7 @@ class ModuleSlotTracker; class raw_ostream; template class SmallVectorImpl; +class SmallBitVector; class StringRef; class TargetInstrInfo; class TargetRegisterClass; @@ -1220,6 +1221,15 @@ /// Debugging support /// @{ + /// Determine the generic type to be printed (if needed) on uses and defs. + LLT getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes, + const MachineRegisterInfo &MRI) const; + + /// Return true when an instruction has tied register that can't be determined + /// by the instruction's descriptor. This is useful for MIR printing, to + /// determine whether we need to print the ties or not. + bool hasComplexRegisterTies() const; + /// Print this MI to \p OS. /// Only print the defs and the opcode if \p SkipOpers is true. /// Otherwise, also print operands if \p SkipDebugLoc is true. Index: include/llvm/CodeGen/MachineOperand.h =================================================================== --- include/llvm/CodeGen/MachineOperand.h +++ include/llvm/CodeGen/MachineOperand.h @@ -17,6 +17,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/LowLevelTypeImpl.h" #include namespace llvm { @@ -228,8 +229,9 @@ void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr, const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; - void print(raw_ostream &os, ModuleSlotTracker &MST, - const TargetRegisterInfo *TRI = nullptr, + void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint, + bool PrintDef, bool ShouldPrintRegisterTies, + unsigned TiedOperandIdx, const TargetRegisterInfo *TRI = nullptr, const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const; void dump() const; @@ -831,7 +833,7 @@ }; inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand &MO) { - MO.print(OS, nullptr); + MO.print(OS); return OS; } Index: include/llvm/CodeGen/TargetRegisterInfo.h =================================================================== --- include/llvm/CodeGen/TargetRegisterInfo.h +++ include/llvm/CodeGen/TargetRegisterInfo.h @@ -1161,6 +1161,11 @@ /// registers on a \ref raw_ostream. Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI); +/// \brief Create Printable object to print register classes or register banks +/// on a \ref raw_ostream. +Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo, + const TargetRegisterInfo *TRI); + } // end namespace llvm #endif // LLVM_CODEGEN_TARGETREGISTERINFO_H Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -164,7 +164,7 @@ void printTargetFlags(const MachineOperand &Op); void print(const MachineInstr &MI, unsigned OpIdx, const TargetRegisterInfo *TRI, bool ShouldPrintRegisterTies, - LLT TypeToPrint, bool IsDef = false); + LLT TypeToPrint, bool PrintDef = true); void print(const LLVMContext &Context, const TargetInstrInfo &TII, const MachineMemOperand &Op); void printSyncScope(const LLVMContext &Context, SyncScope::ID SSID); @@ -257,25 +257,11 @@ OS << ')'; } -static void printRegClassOrBank(unsigned Reg, raw_ostream &OS, - const MachineRegisterInfo &RegInfo, - const TargetRegisterInfo *TRI) { - if (RegInfo.getRegClassOrNull(Reg)) - OS << StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower(); - else if (RegInfo.getRegBankOrNull(Reg)) - OS << StringRef(RegInfo.getRegBankOrNull(Reg)->getName()).lower(); - else { - OS << "_"; - assert((RegInfo.def_empty(Reg) || RegInfo.getType(Reg).isValid()) && - "Generic registers must have a valid type"); - } -} - static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest, const MachineRegisterInfo &RegInfo, const TargetRegisterInfo *TRI) { raw_string_ostream OS(Dest.Value); - printRegClassOrBank(Reg, OS, RegInfo, TRI); + OS << printRegClassOrBank(Reg, RegInfo, TRI); } @@ -289,7 +275,7 @@ unsigned Reg = TargetRegisterInfo::index2VirtReg(I); yaml::VirtualRegisterDefinition VReg; VReg.ID = I; - printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI); + ::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI); unsigned PreferredReg = RegInfo.getSimpleHint(Reg); if (PreferredReg) printRegMIR(PreferredReg, VReg.PreferredRegister, TRI); @@ -661,44 +647,6 @@ OS.indent(2) << "}\n"; } -/// Return true when an instruction has tied register that can't be determined -/// by the instruction's descriptor. -static bool hasComplexRegisterTies(const MachineInstr &MI) { - const MCInstrDesc &MCID = MI.getDesc(); - for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) { - const auto &Operand = MI.getOperand(I); - if (!Operand.isReg() || Operand.isDef()) - // Ignore the defined registers as MCID marks only the uses as tied. - continue; - int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO); - int TiedIdx = Operand.isTied() ? int(MI.findTiedOperandIdx(I)) : -1; - if (ExpectedTiedIdx != TiedIdx) - return true; - } - return false; -} - -static LLT getTypeToPrint(const MachineInstr &MI, unsigned OpIdx, - SmallBitVector &PrintedTypes, - const MachineRegisterInfo &MRI) { - const MachineOperand &Op = MI.getOperand(OpIdx); - if (!Op.isReg()) - return LLT{}; - - if (MI.isVariadic() || OpIdx >= MI.getNumExplicitOperands()) - return MRI.getType(Op.getReg()); - - auto &OpInfo = MI.getDesc().OpInfo[OpIdx]; - if (!OpInfo.isGenericType()) - return MRI.getType(Op.getReg()); - - if (PrintedTypes[OpInfo.getGenericTypeIndex()]) - return LLT{}; - - PrintedTypes.set(OpInfo.getGenericTypeIndex()); - return MRI.getType(Op.getReg()); -} - void MIPrinter::print(const MachineInstr &MI) { const auto *MF = MI.getMF(); const auto &MRI = MF->getRegInfo(); @@ -711,7 +659,7 @@ assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction"); SmallBitVector PrintedTypes(8); - bool ShouldPrintRegisterTies = hasComplexRegisterTies(MI); + bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies(); unsigned I = 0, E = MI.getNumOperands(); for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() && !MI.getOperand(I).isImplicit(); @@ -719,8 +667,8 @@ if (I) OS << ", "; print(MI, I, TRI, ShouldPrintRegisterTies, - getTypeToPrint(MI, I, PrintedTypes, MRI), - /*IsDef=*/true); + MI.getTypeToPrint(I, PrintedTypes, MRI), + /*PrintDef=*/false); } if (I) @@ -736,7 +684,7 @@ if (NeedComma) OS << ", "; print(MI, I, TRI, ShouldPrintRegisterTies, - getTypeToPrint(MI, I, PrintedTypes, MRI)); + MI.getTypeToPrint(I, PrintedTypes, MRI)); NeedComma = true; } @@ -902,7 +850,7 @@ void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx, const TargetRegisterInfo *TRI, bool ShouldPrintRegisterTies, LLT TypeToPrint, - bool IsDef) { + bool PrintDef) { const MachineOperand &Op = MI.getOperand(OpIdx); printTargetFlags(Op); switch (Op.getType()) { @@ -910,7 +858,7 @@ unsigned Reg = Op.getReg(); if (Op.isImplicit()) OS << (Op.isDef() ? "implicit-def " : "implicit "); - else if (!IsDef && Op.isDef()) + else if (PrintDef && Op.isDef()) // Print the 'def' flag only when the operand is defined after '='. OS << "def "; if (Op.isInternalRead()) @@ -931,9 +879,9 @@ OS << '.' << TRI->getSubRegIndexName(Op.getSubReg()); if (TargetRegisterInfo::isVirtualRegister(Reg)) { const MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo(); - if (IsDef || MRI.def_empty(Reg)) { + if (!PrintDef || MRI.def_empty(Reg)) { OS << ':'; - printRegClassOrBank(Reg, OS, MRI, TRI); + OS << printRegClassOrBank(Reg, MRI, TRI); } } if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef()) Index: lib/CodeGen/MachineInstr.cpp =================================================================== --- lib/CodeGen/MachineInstr.cpp +++ lib/CodeGen/MachineInstr.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -1163,8 +1164,44 @@ } } +bool MachineInstr::hasComplexRegisterTies() const { + const MCInstrDesc &MCID = getDesc(); + for (unsigned I = 0, E = getNumOperands(); I < E; ++I) { + const auto &Operand = getOperand(I); + if (!Operand.isReg() || Operand.isDef()) + // Ignore the defined registers as MCID marks only the uses as tied. + continue; + int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO); + int TiedIdx = Operand.isTied() ? int(findTiedOperandIdx(I)) : -1; + if (ExpectedTiedIdx != TiedIdx) + return true; + } + return false; +} + +LLT MachineInstr::getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes, + const MachineRegisterInfo &MRI) const { + const MachineOperand &Op = getOperand(OpIdx); + if (!Op.isReg()) + return LLT{}; + + if (isVariadic() || OpIdx >= getNumExplicitOperands()) + return MRI.getType(Op.getReg()); + + auto &OpInfo = getDesc().OpInfo[OpIdx]; + if (!OpInfo.isGenericType()) + return MRI.getType(Op.getReg()); + + if (PrintedTypes[OpInfo.getGenericTypeIndex()]) + return LLT{}; + + PrintedTypes.set(OpInfo.getGenericTypeIndex()); + return MRI.getType(Op.getReg()); +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MachineInstr::dump() const { +LLVM_DUMP_METHOD void +MachineInstr::dump() const { dbgs() << " "; print(dbgs()); } @@ -1204,14 +1241,28 @@ // Save a list of virtual registers. SmallVector VirtRegs; + SmallBitVector PrintedTypes(8); + bool ShouldPrintRegisterTies = hasComplexRegisterTies(); + auto getTiedOperandIdx = [&](unsigned OpIdx) { + if (!ShouldPrintRegisterTies) + return 0U; + const MachineOperand &MO = getOperand(OpIdx); + if (MO.isReg() && MO.isTied() && !MO.isDef()) + return findTiedOperandIdx(OpIdx); + return 0U; + }; // Print explicitly defined operands on the left of an assignment syntax. unsigned StartOp = 0, e = getNumOperands(); for (; StartOp < e && getOperand(StartOp).isReg() && - getOperand(StartOp).isDef() && - !getOperand(StartOp).isImplicit(); + getOperand(StartOp).isDef() && !getOperand(StartOp).isImplicit(); ++StartOp) { - if (StartOp != 0) OS << ", "; - getOperand(StartOp).print(OS, MST, TRI, IntrinsicInfo); + if (StartOp != 0) + OS << ", "; + LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + getOperand(StartOp).print(OS, MST, TypeToPrint, /*PrintDef=*/false, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, + IntrinsicInfo); unsigned Reg = getOperand(StartOp).getReg(); if (TargetRegisterInfo::isVirtualRegister(Reg)) { VirtRegs.push_back(Reg); @@ -1241,7 +1292,12 @@ if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) { // Print asm string. OS << " "; - getOperand(InlineAsm::MIOp_AsmString).print(OS, MST, TRI); + const unsigned OpIdx = InlineAsm::MIOp_AsmString; + LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + getOperand(OpIdx).print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, + IntrinsicInfo); // Print HasSideEffects, MayLoad, MayStore, IsAlignStack unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); @@ -1284,8 +1340,12 @@ auto *DIV = dyn_cast(MO.getMetadata()); if (DIV && !DIV->getName().empty()) OS << "!\"" << DIV->getName() << '\"'; - else - MO.print(OS, MST, TRI); + else { + LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo); + } } else if (TRI && (isInsertSubreg() || isRegSequence() || (isSubregToReg() && i == 3)) && MO.isImm()) { OS << TRI->getSubRegIndexName(MO.getImm()); @@ -1347,8 +1407,12 @@ // Compute the index of the next operand descriptor. AsmDescOp += 1 + InlineAsm::getNumOperandRegisters(Flag); - } else - MO.print(OS, MST, TRI); + } else { + LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, ShouldPrintRegisterTies, + TiedOperandIdx, TRI, IntrinsicInfo); + } } bool HaveSemi = false; Index: lib/CodeGen/MachineOperand.cpp =================================================================== --- lib/CodeGen/MachineOperand.cpp +++ lib/CodeGen/MachineOperand.cpp @@ -15,10 +15,11 @@ #include "llvm/Analysis/Loads.h" #include "llvm/CodeGen/MIRPrinter.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/ModuleSlotTracker.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetMachine.h" using namespace llvm; @@ -257,13 +258,21 @@ if (RegMask == OtherRegMask) return true; - // Calculate the size of the RegMask - const MachineFunction *MF = getParent()->getMF(); - const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); - unsigned RegMaskSize = (TRI->getNumRegs() + 31) / 32; + if (const MachineInstr *MI = getParent()) { + if (const MachineBasicBlock *MBB = MI->getParent()) { + if (const MachineFunction *MF = MBB->getParent()) { + // Calculate the size of the RegMask + const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); + unsigned RegMaskSize = (TRI->getNumRegs() + 31) / 32; - // Deep compare of the two RegMasks - return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask); + // Deep compare of the two RegMasks + return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask); + } + } + } + // We don't know the size of the RegMask, so we can't deep compare the two + // reg masks. + return false; } case MachineOperand::MO_MCSymbol: return getMCSymbol() == Other.getMCSymbol(); @@ -327,15 +336,37 @@ llvm_unreachable("Invalid machine operand type"); } +// Try to crawl up to the machine function and get TRI and IntrinsicInfo from +// it. +static void tryToGetTargetInfo(const MachineOperand &MO, + const TargetRegisterInfo *&TRI, + const TargetIntrinsicInfo *&IntrinsicInfo) { + if (const MachineInstr *MI = MO.getParent()) { + if (const MachineBasicBlock *MBB = MI->getParent()) { + if (const MachineFunction *MF = MBB->getParent()) { + TRI = MF->getSubtarget().getRegisterInfo(); + IntrinsicInfo = MF->getTarget().getIntrinsicInfo(); + } + } + } +} + void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const { ModuleSlotTracker DummyMST(nullptr); - print(OS, DummyMST, TRI, IntrinsicInfo); + print(OS, DummyMST, LLT{}, /*PrintDef=*/false, + /*ShouldPrintRegisterTies=*/false, + /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); } void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, + LLT TypeToPrint, bool PrintDef, + bool ShouldPrintRegisterTies, + unsigned TiedOperandIdx, const TargetRegisterInfo *TRI, const TargetIntrinsicInfo *IntrinsicInfo) const { + tryToGetTargetInfo(*this, TRI, IntrinsicInfo); + switch (getType()) { case MachineOperand::MO_Register: OS << printReg(getReg(), TRI, getSubReg()); @@ -469,23 +500,27 @@ OS << '>'; break; case MachineOperand::MO_RegisterMask: { - unsigned NumRegsInMask = 0; - unsigned NumRegsEmitted = 0; OS << "getNumRegs(); ++i) { - unsigned MaskWord = i / 32; - unsigned MaskBit = i % 32; - if (getRegMask()[MaskWord] & (1 << MaskBit)) { - if (PrintRegMaskNumRegs < 0 || - NumRegsEmitted <= static_cast(PrintRegMaskNumRegs)) { - OS << " " << printReg(i, TRI); - NumRegsEmitted++; + if (TRI) { + unsigned NumRegsInMask = 0; + unsigned NumRegsEmitted = 0; + for (unsigned i = 0; i < TRI->getNumRegs(); ++i) { + unsigned MaskWord = i / 32; + unsigned MaskBit = i % 32; + if (getRegMask()[MaskWord] & (1 << MaskBit)) { + if (PrintRegMaskNumRegs < 0 || + NumRegsEmitted <= static_cast(PrintRegMaskNumRegs)) { + OS << " " << printReg(i, TRI); + NumRegsEmitted++; + } + NumRegsInMask++; } - NumRegsInMask++; } + if (NumRegsEmitted != NumRegsInMask) + OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; + } else { + OS << " ..."; } - if (NumRegsEmitted != NumRegsInMask) - OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; OS << ">"; break; } Index: lib/CodeGen/TargetRegisterInfo.cpp =================================================================== --- lib/CodeGen/TargetRegisterInfo.cpp +++ lib/CodeGen/TargetRegisterInfo.cpp @@ -144,6 +144,21 @@ }); } +Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo, + const TargetRegisterInfo *TRI) { + return Printable([Reg, &RegInfo, TRI](raw_ostream &OS) { + if (RegInfo.getRegClassOrNull(Reg)) + OS << StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower(); + else if (RegInfo.getRegBankOrNull(Reg)) + OS << StringRef(RegInfo.getRegBankOrNull(Reg)->getName()).lower(); + else { + OS << "_"; + assert((RegInfo.def_empty(Reg) || RegInfo.getType(Reg).isValid()) && + "Generic registers must have a valid type"); + } + }); +} + } // end namespace llvm /// getAllocatableClass - Return the maximal subclass of the given register 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/Support/raw_ostream.h" #include "gtest/gtest.h" using namespace llvm; @@ -37,4 +38,21 @@ ASSERT_TRUE(MO.getTargetFlags() == 12); } +TEST(MachineOperandTest, PrintRegisterMask) { + uint32_t Dummy; + MachineOperand MO = MachineOperand::CreateRegMask(&Dummy); + + // Checking some preconditions on the newly created + // MachineOperand. + ASSERT_TRUE(MO.isRegMask()); + ASSERT_TRUE(MO.getRegMask() == &Dummy); + + // Print a MachineOperand containing a RegMask. Here we check that without a + // TRI and IntrinsicInfo we still print a less detailed regmask. + std::string str; + raw_string_ostream OS(str); + MO.print(OS, /*TRI=*/nullptr, /*IntrinsicInfo=*/nullptr); + ASSERT_TRUE(OS.str() == ""); +} + } // end namespace