void HexagonPeephole::ChangeOpInto(MachineOperand &Dst, MachineOperand &Src) { assert (&Dst != &Src && "Cannot duplicate into itself"); switch (Dst.getType()) { case MachineOperand::MO_Register: if (Src.isReg()) { Dst.setReg(Src.getReg()); } else if (Src.isImm()) { Dst.ChangeToImmediate(Src.getImm()); } else { llvm_unreachable("Unexpected src operand type"); } break; case MachineOperand::MO_Immediate: if (Src.isImm()) { Dst.setImm(Src.getImm()); } else if (Src.isReg()) { Dst.ChangeToRegister(Src.getReg(), Src.isDef(), Src.isImplicit(), Src.isKill(), Src.isDead(), Src.isUndef(), Src.isDebug()); } else { llvm_unreachable("Unexpected src operand type"); } break; default: llvm_unreachable("Unexpected dst operand type"); break; } }
bool SIInsertWaits::isOpRelevant(MachineOperand &Op) { // Constants are always irrelevant if (!Op.isReg()) return false; // Defines are always relevant if (Op.isDef()) return true; // For exports all registers are relevant MachineInstr &MI = *Op.getParent(); if (MI.getOpcode() == AMDGPU::EXP) return true; // For stores the stored value is also relevant if (!MI.getDesc().mayStore()) return false; for (MachineInstr::mop_iterator I = MI.operands_begin(), E = MI.operands_end(); I != E; ++I) { if (I->isReg() && I->isUse()) return Op.isIdenticalTo(*I); } return false; }
/// isIdenticalTo - Return true if this operand is identical to the specified /// operand. bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { if (getType() != Other.getType()) return false; switch (getType()) { default: assert(0 && "Unrecognized operand type"); case MachineOperand::MO_Register: return getReg() == Other.getReg() && isDef() == Other.isDef() && getSubReg() == Other.getSubReg(); case MachineOperand::MO_Immediate: return getImm() == Other.getImm(); case MachineOperand::MO_FPImmediate: return getFPImm() == Other.getFPImm(); case MachineOperand::MO_MachineBasicBlock: return getMBB() == Other.getMBB(); case MachineOperand::MO_FrameIndex: return getIndex() == Other.getIndex(); case MachineOperand::MO_ConstantPoolIndex: return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); case MachineOperand::MO_JumpTableIndex: return getIndex() == Other.getIndex(); case MachineOperand::MO_GlobalAddress: return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); case MachineOperand::MO_ExternalSymbol: return !strcmp(getSymbolName(), Other.getSymbolName()) && getOffset() == Other.getOffset(); } }
MachineOperand AMDGPUInstructionSelector::getSubOperand64(MachineOperand &MO, unsigned SubIdx) const { MachineInstr *MI = MO.getParent(); MachineBasicBlock *BB = MO.getParent()->getParent(); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &MRI = MF->getRegInfo(); unsigned DstReg = MRI.createVirtualRegister(&AMDGPU::SGPR_32RegClass); if (MO.isReg()) { unsigned ComposedSubIdx = TRI.composeSubRegIndices(MO.getSubReg(), SubIdx); unsigned Reg = MO.getReg(); BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg) .addReg(Reg, 0, ComposedSubIdx); return MachineOperand::CreateReg(DstReg, MO.isDef(), MO.isImplicit(), MO.isKill(), MO.isDead(), MO.isUndef(), MO.isEarlyClobber(), 0, MO.isDebug(), MO.isInternalRead()); } assert(MO.isImm()); APInt Imm(64, MO.getImm()); switch (SubIdx) { default: llvm_unreachable("do not know to split immediate with this sub index."); case AMDGPU::sub0: return MachineOperand::CreateImm(Imm.getLoBits(32).getSExtValue()); case AMDGPU::sub1: return MachineOperand::CreateImm(Imm.getHiBits(32).getSExtValue()); } }
/// Changes operand OpNum in MI the refer the PhysReg, considering subregs. This /// may invalidate any operand pointers. Return true if the operand kills its /// register. bool RegAllocFast::setPhysReg(MachineInstr &MI, MachineOperand &MO, MCPhysReg PhysReg) { bool Dead = MO.isDead(); if (!MO.getSubReg()) { MO.setReg(PhysReg); MO.setIsRenamable(true); return MO.isKill() || Dead; } // Handle subregister index. MO.setReg(PhysReg ? TRI->getSubReg(PhysReg, MO.getSubReg()) : 0); MO.setIsRenamable(true); MO.setSubReg(0); // A kill flag implies killing the full register. Add corresponding super // register kill. if (MO.isKill()) { MI.addRegisterKilled(PhysReg, TRI, true); return true; } // A <def,read-undef> of a sub-register requires an implicit def of the full // register. if (MO.isDef() && MO.isUndef()) MI.addRegisterDefined(PhysReg, TRI); return Dead; }
// Check all machine operands that reference the antidependent register and must // be replaced by NewReg. Return true if any of their parent instructions may // clobber the new register. // // Note: AntiDepReg may be referenced by a two-address instruction such that // it's use operand is tied to a def operand. We guard against the case in which // the two-address instruction also defines NewReg, as may happen with // pre/postincrement loads. In this case, both the use and def operands are in // RegRefs because the def is inserted by PrescanInstruction and not erased // during ScanInstruction. So checking for an instructions with definitions of // both NewReg and AntiDepReg covers it. bool CriticalAntiDepBreaker::isNewRegClobberedByRefs(RegRefIter RegRefBegin, RegRefIter RegRefEnd, unsigned NewReg) { for (RegRefIter I = RegRefBegin; I != RegRefEnd; ++I ) { MachineOperand *RefOper = I->second; // Don't allow the instruction defining AntiDepReg to earlyclobber its // operands, in case they may be assigned to NewReg. In this case antidep // breaking must fail, but it's too rare to bother optimizing. if (RefOper->isDef() && RefOper->isEarlyClobber()) return true; // Handle cases in which this instructions defines NewReg. MachineInstr *MI = RefOper->getParent(); for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { const MachineOperand &CheckOper = MI->getOperand(i); if (CheckOper.isRegMask() && CheckOper.clobbersPhysReg(NewReg)) return true; if (!CheckOper.isReg() || !CheckOper.isDef() || CheckOper.getReg() != NewReg) continue; // Don't allow the instruction to define NewReg and AntiDepReg. // When AntiDepReg is renamed it will be an illegal op. if (RefOper->isDef()) return true; // Don't allow an instruction using AntiDepReg to be earlyclobbered by // NewReg if (CheckOper.isEarlyClobber()) return true; // Don't allow inline asm to define NewReg at all. Who know what it's // doing with it. if (MI->isInlineAsm()) return true; } } return false; }
static inline uint32_t getRegState(const MachineOperand &R) { assert(R.isReg()); return getDefRegState(R.isDef()) | getImplRegState(R.isImplicit()) | getKillRegState(R.isKill()) | getDeadRegState(R.isDead()) | getUndefRegState(R.isUndef()) | getInternalReadRegState(R.isInternalRead()) | (R.isDebug() ? RegState::Debug : 0); }
/// Push this operand's register onto the correct vector. void collect(const MachineOperand &MO) { if (!MO.isReg() || !MO.getReg()) return; if (MO.readsReg()) pushRegUnits(MO.getReg(), Uses); if (MO.isDef()) { if (MO.isDead()) pushRegUnits(MO.getReg(), DeadDefs); else pushRegUnits(MO.getReg(), Defs); } }
static LaneBitmask getDefRegMask(const MachineOperand &MO, const MachineRegisterInfo &MRI) { assert(MO.isDef() && MO.isReg() && TargetRegisterInfo::isVirtualRegister(MO.getReg())); // We don't rely on read-undef flag because in case of tentative schedule // tracking it isn't set correctly yet. This works correctly however since // use mask has been tracked before using LIS. return MO.getSubReg() == 0 ? MRI.getMaxLaneMaskForVReg(MO.getReg()) : MRI.getTargetRegisterInfo()->getSubRegIndexLaneMask(MO.getSubReg()); }
// Copy MachineOperand with all flags except setting it as implicit. static MachineOperand copyRegOperandAsImplicit(const MachineOperand &Orig) { assert(!Orig.isImplicit()); return MachineOperand::CreateReg(Orig.getReg(), Orig.isDef(), true, Orig.isKill(), Orig.isDead(), Orig.isUndef(), Orig.isEarlyClobber(), Orig.getSubReg(), Orig.isDebug(), Orig.isInternalRead()); }
bool SIInsertWaits::isOpRelevant(MachineOperand &Op) { // Constants are always irrelevant if (!Op.isReg()) return false; // Defines are always relevant if (Op.isDef()) return true; // For exports all registers are relevant MachineInstr &MI = *Op.getParent(); if (MI.getOpcode() == AMDGPU::EXP) return true; // For stores the stored value is also relevant if (!MI.getDesc().mayStore()) return false; // Check if this operand is the value being stored. // Special case for DS instructions, since the address // operand comes before the value operand and it may have // multiple data operands. if (TII->isDS(MI.getOpcode())) { MachineOperand *Data = TII->getNamedOperand(MI, AMDGPU::OpName::data); if (Data && Op.isIdenticalTo(*Data)) return true; MachineOperand *Data0 = TII->getNamedOperand(MI, AMDGPU::OpName::data0); if (Data0 && Op.isIdenticalTo(*Data0)) return true; MachineOperand *Data1 = TII->getNamedOperand(MI, AMDGPU::OpName::data1); if (Data1 && Op.isIdenticalTo(*Data1)) return true; return false; } // NOTE: This assumes that the value operand is before the // address operand, and that there is only one value operand. for (MachineInstr::mop_iterator I = MI.operands_begin(), E = MI.operands_end(); I != E; ++I) { if (I->isReg() && I->isUse()) return Op.isIdenticalTo(*I); } return false; }
// Helper function for getting a MachineOperand's register number and adding it // to RegDefs or RegUses. static void insertDefUse(const MachineOperand &MO, SmallSet<unsigned, 32> &RegDefs, SmallSet<unsigned, 32> &RegUses, unsigned ExcludedReg = 0) { unsigned Reg; if (!MO.isReg() || !(Reg = MO.getReg()) || (Reg == ExcludedReg)) return; if (MO.isDef()) RegDefs.insert(Reg); else if (MO.isUse()) RegUses.insert(Reg); }
/// Push this operand's register onto the correct vector. void collect(const MachineOperand &MO, const TargetRegisterInfo *TRI) { if (MO.readsReg()) { if (findReg(MO.getReg(), isVReg, Uses, TRI) == Uses.end()) Uses.push_back(MO.getReg()); } if (MO.isDef()) { if (MO.isDead()) { if (findReg(MO.getReg(), isVReg, DeadDefs, TRI) == DeadDefs.end()) DeadDefs.push_back(MO.getReg()); } else { if (findReg(MO.getReg(), isVReg, Defs, TRI) == Defs.end()) Defs.push_back(MO.getReg()); } } }
/// MO is an operand of SU's instruction that defines a physical register. Add /// data dependencies from SU to any uses of the physical register. void ScheduleDAGInstrs::addPhysRegDataDeps(SUnit *SU, const MachineOperand &MO) { assert(MO.isDef() && "expect physreg def"); // Ask the target if address-backscheduling is desirable, and if so how much. const TargetSubtargetInfo &ST = TM.getSubtarget<TargetSubtargetInfo>(); unsigned SpecialAddressLatency = ST.getSpecialAddressLatency(); unsigned DataLatency = SU->Latency; for (const unsigned *Alias = TRI->getOverlaps(MO.getReg()); *Alias; ++Alias) { if (!Uses.contains(*Alias)) continue; std::vector<SUnit*> &UseList = Uses[*Alias]; for (unsigned i = 0, e = UseList.size(); i != e; ++i) { SUnit *UseSU = UseList[i]; if (UseSU == SU) continue; unsigned LDataLatency = DataLatency; // Optionally add in a special extra latency for nodes that // feed addresses. // TODO: Perhaps we should get rid of // SpecialAddressLatency and just move this into // adjustSchedDependency for the targets that care about it. if (SpecialAddressLatency != 0 && !UnitLatencies && UseSU != &ExitSU) { MachineInstr *UseMI = UseSU->getInstr(); const MCInstrDesc &UseMCID = UseMI->getDesc(); int RegUseIndex = UseMI->findRegisterUseOperandIdx(*Alias); assert(RegUseIndex >= 0 && "UseMI doesn't use register!"); if (RegUseIndex >= 0 && (UseMI->mayLoad() || UseMI->mayStore()) && (unsigned)RegUseIndex < UseMCID.getNumOperands() && UseMCID.OpInfo[RegUseIndex].isLookupPtrRegClass()) LDataLatency += SpecialAddressLatency; } // Adjust the dependence latency using operand def/use // information (if any), and then allow the target to // perform its own adjustments. const SDep& dep = SDep(SU, SDep::Data, LDataLatency, *Alias); if (!UnitLatencies) { ComputeOperandLatency(SU, UseSU, const_cast<SDep &>(dep)); ST.adjustSchedDependency(SU, UseSU, const_cast<SDep &>(dep)); } UseSU->addPred(dep); } } }
// Note: this must stay exactly in sync with isIdenticalTo above. hash_code llvm::hash_value(const MachineOperand &MO) { switch (MO.getType()) { case MachineOperand::MO_Register: // Register operands don't have target flags. return hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), MO.isDef()); case MachineOperand::MO_Immediate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); case MachineOperand::MO_CImmediate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm()); case MachineOperand::MO_FPImmediate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm()); case MachineOperand::MO_MachineBasicBlock: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB()); case MachineOperand::MO_FrameIndex: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_TargetIndex: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(), MO.getOffset()); case MachineOperand::MO_JumpTableIndex: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); case MachineOperand::MO_ExternalSymbol: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), MO.getSymbolName()); case MachineOperand::MO_GlobalAddress: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(), MO.getOffset()); case MachineOperand::MO_BlockAddress: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(), MO.getOffset()); case MachineOperand::MO_RegisterMask: case MachineOperand::MO_RegisterLiveOut: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); case MachineOperand::MO_Metadata: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); case MachineOperand::MO_MCSymbol: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); case MachineOperand::MO_CFIIndex: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); case MachineOperand::MO_IntrinsicID: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); case MachineOperand::MO_Predicate: return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); } llvm_unreachable("Invalid machine operand type"); }
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { switch (Op.getType()) { case MachineOperand::MO_Register: // TODO: Print the other register flags. if (Op.isImplicit()) OS << (Op.isDef() ? "implicit-def " : "implicit "); if (Op.isDead()) OS << "dead "; if (Op.isKill()) OS << "killed "; if (Op.isUndef()) OS << "undef "; printReg(Op.getReg(), OS, TRI); // TODO: Print sub register. break; case MachineOperand::MO_Immediate: OS << Op.getImm(); break; case MachineOperand::MO_MachineBasicBlock: printMBBReference(*Op.getMBB()); break; case MachineOperand::MO_GlobalAddress: Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); // TODO: Print offset and target flags. break; case MachineOperand::MO_RegisterMask: { auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); if (RegMaskInfo != RegisterMaskIds.end()) OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower(); else llvm_unreachable("Can't print this machine register mask yet."); break; } default: // TODO: Print the other machine operands. llvm_unreachable("Can't print this machine operand at the moment"); } }
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI, unsigned I, bool ShouldPrintRegisterTies, bool IsDef) { printTargetFlags(Op); switch (Op.getType()) { case MachineOperand::MO_Register: if (Op.isImplicit()) OS << (Op.isDef() ? "implicit-def " : "implicit "); else if (!IsDef && Op.isDef()) // Print the 'def' flag only when the operand is defined after '='. OS << "def "; if (Op.isInternalRead()) OS << "internal "; if (Op.isDead()) OS << "dead "; if (Op.isKill()) OS << "killed "; if (Op.isUndef()) OS << "undef "; if (Op.isEarlyClobber()) OS << "early-clobber "; if (Op.isDebug()) OS << "debug-use "; printReg(Op.getReg(), OS, TRI); // Print the sub register. if (Op.getSubReg() != 0) OS << ':' << TRI->getSubRegIndexName(Op.getSubReg()); if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef()) OS << "(tied-def " << Op.getParent()->findTiedOperandIdx(I) << ")"; break; case MachineOperand::MO_Immediate: OS << Op.getImm(); break; case MachineOperand::MO_CImmediate: Op.getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_FPImmediate: Op.getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_MachineBasicBlock: printMBBReference(*Op.getMBB()); break; case MachineOperand::MO_FrameIndex: printStackObjectReference(Op.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: OS << "%const." << Op.getIndex(); printOffset(Op.getOffset()); break; case MachineOperand::MO_TargetIndex: { OS << "target-index("; if (const auto *Name = getTargetIndexName( *Op.getParent()->getParent()->getParent(), Op.getIndex())) OS << Name; else OS << "<unknown>"; OS << ')'; printOffset(Op.getOffset()); break; } case MachineOperand::MO_JumpTableIndex: OS << "%jump-table." << Op.getIndex(); break; case MachineOperand::MO_ExternalSymbol: OS << '$'; printLLVMNameWithoutPrefix(OS, Op.getSymbolName()); printOffset(Op.getOffset()); break; case MachineOperand::MO_GlobalAddress: Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); printOffset(Op.getOffset()); break; case MachineOperand::MO_BlockAddress: OS << "blockaddress("; Op.getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, MST); OS << ", "; printIRBlockReference(*Op.getBlockAddress()->getBasicBlock()); OS << ')'; printOffset(Op.getOffset()); break; case MachineOperand::MO_RegisterMask: { auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); if (RegMaskInfo != RegisterMaskIds.end()) OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower(); else llvm_unreachable("Can't print this machine register mask yet."); break; } case MachineOperand::MO_RegisterLiveOut: { const uint32_t *RegMask = Op.getRegLiveOut(); OS << "liveout("; bool IsCommaNeeded = false; for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) { if (RegMask[Reg / 32] & (1U << (Reg % 32))) { if (IsCommaNeeded) OS << ", "; printReg(Reg, OS, TRI); IsCommaNeeded = true; } } OS << ")"; break; } case MachineOperand::MO_Metadata: Op.getMetadata()->printAsOperand(OS, MST); break; case MachineOperand::MO_MCSymbol: OS << "<mcsymbol " << *Op.getMCSymbol() << ">"; break; case MachineOperand::MO_CFIIndex: { const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI(); print(MMI.getFrameInstructions()[Op.getCFIIndex()], TRI); break; } } }
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { printTargetFlags(Op); switch (Op.getType()) { case MachineOperand::MO_Register: // TODO: Print the other register flags. if (Op.isImplicit()) OS << (Op.isDef() ? "implicit-def " : "implicit "); if (Op.isDead()) OS << "dead "; if (Op.isKill()) OS << "killed "; if (Op.isUndef()) OS << "undef "; if (Op.isEarlyClobber()) OS << "early-clobber "; if (Op.isDebug()) OS << "debug-use "; printReg(Op.getReg(), OS, TRI); // Print the sub register. if (Op.getSubReg() != 0) OS << ':' << TRI->getSubRegIndexName(Op.getSubReg()); break; case MachineOperand::MO_Immediate: OS << Op.getImm(); break; case MachineOperand::MO_CImmediate: Op.getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_FPImmediate: Op.getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_MachineBasicBlock: printMBBReference(*Op.getMBB()); break; case MachineOperand::MO_FrameIndex: printStackObjectReference(Op.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: OS << "%const." << Op.getIndex(); printOffset(Op.getOffset()); break; case MachineOperand::MO_TargetIndex: { OS << "target-index("; if (const auto *Name = getTargetIndexName( *Op.getParent()->getParent()->getParent(), Op.getIndex())) OS << Name; else OS << "<unknown>"; OS << ')'; printOffset(Op.getOffset()); break; } case MachineOperand::MO_JumpTableIndex: OS << "%jump-table." << Op.getIndex(); break; case MachineOperand::MO_ExternalSymbol: OS << '$'; printLLVMNameWithoutPrefix(OS, Op.getSymbolName()); printOffset(Op.getOffset()); break; case MachineOperand::MO_GlobalAddress: Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); printOffset(Op.getOffset()); break; case MachineOperand::MO_BlockAddress: OS << "blockaddress("; Op.getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, MST); OS << ", "; printIRBlockReference(*Op.getBlockAddress()->getBasicBlock()); OS << ')'; printOffset(Op.getOffset()); break; case MachineOperand::MO_RegisterMask: { auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); if (RegMaskInfo != RegisterMaskIds.end()) OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower(); else llvm_unreachable("Can't print this machine register mask yet."); break; } case MachineOperand::MO_Metadata: Op.getMetadata()->printAsOperand(OS, MST); break; case MachineOperand::MO_CFIIndex: { const auto &MMI = Op.getParent()->getParent()->getParent()->getMMI(); print(MMI.getFrameInstructions()[Op.getCFIIndex()], TRI); break; } default: // TODO: Print the other machine operands. llvm_unreachable("Can't print this machine operand at the moment"); } }
/// isIdenticalTo - Return true if this operand is identical to the specified /// operand. Note that this should stay in sync with the hash_value overload /// below. bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { if (getType() != Other.getType() || getTargetFlags() != Other.getTargetFlags()) return false; switch (getType()) { case MachineOperand::MO_Register: return getReg() == Other.getReg() && isDef() == Other.isDef() && getSubReg() == Other.getSubReg(); case MachineOperand::MO_Immediate: return getImm() == Other.getImm(); case MachineOperand::MO_CImmediate: return getCImm() == Other.getCImm(); case MachineOperand::MO_FPImmediate: return getFPImm() == Other.getFPImm(); case MachineOperand::MO_MachineBasicBlock: return getMBB() == Other.getMBB(); case MachineOperand::MO_FrameIndex: return getIndex() == Other.getIndex(); case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_TargetIndex: return getIndex() == Other.getIndex() && getOffset() == Other.getOffset(); case MachineOperand::MO_JumpTableIndex: return getIndex() == Other.getIndex(); case MachineOperand::MO_GlobalAddress: return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset(); case MachineOperand::MO_ExternalSymbol: return strcmp(getSymbolName(), Other.getSymbolName()) == 0 && getOffset() == Other.getOffset(); case MachineOperand::MO_BlockAddress: return getBlockAddress() == Other.getBlockAddress() && getOffset() == Other.getOffset(); case MachineOperand::MO_RegisterMask: case MachineOperand::MO_RegisterLiveOut: { // Shallow compare of the two RegMasks const uint32_t *RegMask = getRegMask(); const uint32_t *OtherRegMask = Other.getRegMask(); if (RegMask == OtherRegMask) return true; if (const MachineFunction *MF = getMFIfAvailable(*this)) { // 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); } // 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(); case MachineOperand::MO_CFIIndex: return getCFIIndex() == Other.getCFIIndex(); case MachineOperand::MO_Metadata: return getMetadata() == Other.getMetadata(); case MachineOperand::MO_IntrinsicID: return getIntrinsicID() == Other.getIntrinsicID(); case MachineOperand::MO_Predicate: return getPredicate() == Other.getPredicate(); } llvm_unreachable("Invalid machine operand type"); }
void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI, unsigned I, bool ShouldPrintRegisterTies, LLT TypeToPrint, bool IsDef) { printTargetFlags(Op); switch (Op.getType()) { case MachineOperand::MO_Register: if (Op.isImplicit()) OS << (Op.isDef() ? "implicit-def " : "implicit "); else if (!IsDef && Op.isDef()) // Print the 'def' flag only when the operand is defined after '='. OS << "def "; if (Op.isInternalRead()) OS << "internal "; if (Op.isDead()) OS << "dead "; if (Op.isKill()) OS << "killed "; if (Op.isUndef()) OS << "undef "; if (Op.isEarlyClobber()) OS << "early-clobber "; if (Op.isDebug()) OS << "debug-use "; printReg(Op.getReg(), OS, TRI); // Print the sub register. if (Op.getSubReg() != 0) OS << '.' << TRI->getSubRegIndexName(Op.getSubReg()); if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef()) OS << "(tied-def " << Op.getParent()->findTiedOperandIdx(I) << ")"; if (TypeToPrint.isValid()) OS << '(' << TypeToPrint << ')'; break; case MachineOperand::MO_Immediate: OS << Op.getImm(); break; case MachineOperand::MO_CImmediate: Op.getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_FPImmediate: Op.getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); break; case MachineOperand::MO_MachineBasicBlock: printMBBReference(*Op.getMBB()); break; case MachineOperand::MO_FrameIndex: printStackObjectReference(Op.getIndex()); break; case MachineOperand::MO_ConstantPoolIndex: OS << "%const." << Op.getIndex(); printOffset(Op.getOffset()); break; case MachineOperand::MO_TargetIndex: OS << "target-index("; if (const auto *Name = getTargetIndexName( *Op.getParent()->getParent()->getParent(), Op.getIndex())) OS << Name; else OS << "<unknown>"; OS << ')'; printOffset(Op.getOffset()); break; case MachineOperand::MO_JumpTableIndex: OS << "%jump-table." << Op.getIndex(); break; case MachineOperand::MO_ExternalSymbol: { StringRef Name = Op.getSymbolName(); OS << '$'; if (Name.empty()) { OS << "\"\""; } else { printLLVMNameWithoutPrefix(OS, Name); } printOffset(Op.getOffset()); break; } case MachineOperand::MO_GlobalAddress: Op.getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); printOffset(Op.getOffset()); break; case MachineOperand::MO_BlockAddress: OS << "blockaddress("; Op.getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, MST); OS << ", "; printIRBlockReference(*Op.getBlockAddress()->getBasicBlock()); OS << ')'; printOffset(Op.getOffset()); break; case MachineOperand::MO_RegisterMask: { auto RegMaskInfo = RegisterMaskIds.find(Op.getRegMask()); if (RegMaskInfo != RegisterMaskIds.end()) OS << StringRef(TRI->getRegMaskNames()[RegMaskInfo->second]).lower(); else printCustomRegMask(Op.getRegMask(), OS, TRI); break; } case MachineOperand::MO_RegisterLiveOut: { const uint32_t *RegMask = Op.getRegLiveOut(); OS << "liveout("; bool IsCommaNeeded = false; for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) { if (RegMask[Reg / 32] & (1U << (Reg % 32))) { if (IsCommaNeeded) OS << ", "; printReg(Reg, OS, TRI); IsCommaNeeded = true; } } OS << ")"; break; } case MachineOperand::MO_Metadata: Op.getMetadata()->printAsOperand(OS, MST); break; case MachineOperand::MO_MCSymbol: OS << "<mcsymbol " << *Op.getMCSymbol() << ">"; break; case MachineOperand::MO_CFIIndex: { const MachineFunction &MF = *Op.getParent()->getParent()->getParent(); print(MF.getFrameInstructions()[Op.getCFIIndex()], TRI); break; } case MachineOperand::MO_IntrinsicID: { Intrinsic::ID ID = Op.getIntrinsicID(); if (ID < Intrinsic::num_intrinsics) OS << "intrinsic(@" << Intrinsic::getName(ID, None) << ')'; else { const MachineFunction &MF = *Op.getParent()->getParent()->getParent(); const TargetIntrinsicInfo *TII = MF.getTarget().getIntrinsicInfo(); OS << "intrinsic(@" << TII->getName(ID) << ')'; } break; } case MachineOperand::MO_Predicate: { auto Pred = static_cast<CmpInst::Predicate>(Op.getPredicate()); OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" << CmpInst::getPredicateName(Pred) << ')'; break; } } }