10b57cec5SDimitry Andric //===- lib/CodeGen/MachineOperand.cpp -------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file Methods common to all machine operands.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
150b57cec5SDimitry Andric #include "llvm/Analysis/Loads.h"
16480093f4SDimitry Andric #include "llvm/CodeGen/MIRFormatter.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
20bdd1243dSDimitry Andric #include "llvm/CodeGen/StableHashing.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/TargetInstrInfo.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h"
240b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
250b57cec5SDimitry Andric #include "llvm/IR/IRPrintingPasses.h"
265ffd83dbSDimitry Andric #include "llvm/IR/Instructions.h"
270b57cec5SDimitry Andric #include "llvm/IR/ModuleSlotTracker.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCDwarf.h"
290b57cec5SDimitry Andric #include "llvm/Target/TargetIntrinsicInfo.h"
300b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
31bdd1243dSDimitry Andric #include <optional>
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric static cl::opt<int>
360b57cec5SDimitry Andric     PrintRegMaskNumRegs("print-regmask-num-regs",
370b57cec5SDimitry Andric                         cl::desc("Number of registers to limit to when "
380b57cec5SDimitry Andric                                  "printing regmask operands in IR dumps. "
390b57cec5SDimitry Andric                                  "unlimited = -1"),
400b57cec5SDimitry Andric                         cl::init(32), cl::Hidden);
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric static const MachineFunction *getMFIfAvailable(const MachineOperand &MO) {
430b57cec5SDimitry Andric   if (const MachineInstr *MI = MO.getParent())
440b57cec5SDimitry Andric     if (const MachineBasicBlock *MBB = MI->getParent())
450b57cec5SDimitry Andric       if (const MachineFunction *MF = MBB->getParent())
460b57cec5SDimitry Andric         return MF;
470b57cec5SDimitry Andric   return nullptr;
480b57cec5SDimitry Andric }
49bdd1243dSDimitry Andric 
500b57cec5SDimitry Andric static MachineFunction *getMFIfAvailable(MachineOperand &MO) {
510b57cec5SDimitry Andric   return const_cast<MachineFunction *>(
520b57cec5SDimitry Andric       getMFIfAvailable(const_cast<const MachineOperand &>(MO)));
530b57cec5SDimitry Andric }
540b57cec5SDimitry Andric 
55*fe013be4SDimitry Andric unsigned MachineOperand::getOperandNo() const {
56*fe013be4SDimitry Andric   assert(getParent() && "Operand does not belong to any instruction!");
57*fe013be4SDimitry Andric   return getParent()->getOperandNo(this);
58*fe013be4SDimitry Andric }
59*fe013be4SDimitry Andric 
608bcb0991SDimitry Andric void MachineOperand::setReg(Register Reg) {
610b57cec5SDimitry Andric   if (getReg() == Reg)
620b57cec5SDimitry Andric     return; // No change.
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // Clear the IsRenamable bit to keep it conservatively correct.
650b57cec5SDimitry Andric   IsRenamable = false;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   // Otherwise, we have to change the register.  If this operand is embedded
680b57cec5SDimitry Andric   // into a machine function, we need to update the old and new register's
690b57cec5SDimitry Andric   // use/def lists.
700b57cec5SDimitry Andric   if (MachineFunction *MF = getMFIfAvailable(*this)) {
710b57cec5SDimitry Andric     MachineRegisterInfo &MRI = MF->getRegInfo();
720b57cec5SDimitry Andric     MRI.removeRegOperandFromUseList(this);
730b57cec5SDimitry Andric     SmallContents.RegNo = Reg;
740b57cec5SDimitry Andric     MRI.addRegOperandToUseList(this);
750b57cec5SDimitry Andric     return;
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // Otherwise, just change the register, no problem.  :)
790b57cec5SDimitry Andric   SmallContents.RegNo = Reg;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
828bcb0991SDimitry Andric void MachineOperand::substVirtReg(Register Reg, unsigned SubIdx,
830b57cec5SDimitry Andric                                   const TargetRegisterInfo &TRI) {
848bcb0991SDimitry Andric   assert(Reg.isVirtual());
850b57cec5SDimitry Andric   if (SubIdx && getSubReg())
860b57cec5SDimitry Andric     SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg());
870b57cec5SDimitry Andric   setReg(Reg);
880b57cec5SDimitry Andric   if (SubIdx)
890b57cec5SDimitry Andric     setSubReg(SubIdx);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
928bcb0991SDimitry Andric void MachineOperand::substPhysReg(MCRegister Reg, const TargetRegisterInfo &TRI) {
93e8d8bef9SDimitry Andric   assert(Register::isPhysicalRegister(Reg));
940b57cec5SDimitry Andric   if (getSubReg()) {
950b57cec5SDimitry Andric     Reg = TRI.getSubReg(Reg, getSubReg());
960b57cec5SDimitry Andric     // Note that getSubReg() may return 0 if the sub-register doesn't exist.
970b57cec5SDimitry Andric     // That won't happen in legal code.
980b57cec5SDimitry Andric     setSubReg(0);
990b57cec5SDimitry Andric     if (isDef())
1000b57cec5SDimitry Andric       setIsUndef(false);
1010b57cec5SDimitry Andric   }
1020b57cec5SDimitry Andric   setReg(Reg);
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric /// Change a def to a use, or a use to a def.
1060b57cec5SDimitry Andric void MachineOperand::setIsDef(bool Val) {
1070b57cec5SDimitry Andric   assert(isReg() && "Wrong MachineOperand accessor");
1080b57cec5SDimitry Andric   assert((!Val || !isDebug()) && "Marking a debug operation as def");
1090b57cec5SDimitry Andric   if (IsDef == Val)
1100b57cec5SDimitry Andric     return;
1110b57cec5SDimitry Andric   assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported");
1120b57cec5SDimitry Andric   // MRI may keep uses and defs in different list positions.
1130b57cec5SDimitry Andric   if (MachineFunction *MF = getMFIfAvailable(*this)) {
1140b57cec5SDimitry Andric     MachineRegisterInfo &MRI = MF->getRegInfo();
1150b57cec5SDimitry Andric     MRI.removeRegOperandFromUseList(this);
1160b57cec5SDimitry Andric     IsDef = Val;
1170b57cec5SDimitry Andric     MRI.addRegOperandToUseList(this);
1180b57cec5SDimitry Andric     return;
1190b57cec5SDimitry Andric   }
1200b57cec5SDimitry Andric   IsDef = Val;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric bool MachineOperand::isRenamable() const {
1240b57cec5SDimitry Andric   assert(isReg() && "Wrong MachineOperand accessor");
125bdd1243dSDimitry Andric   assert(getReg().isPhysical() &&
1260b57cec5SDimitry Andric          "isRenamable should only be checked on physical registers");
1270b57cec5SDimitry Andric   if (!IsRenamable)
1280b57cec5SDimitry Andric     return false;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   const MachineInstr *MI = getParent();
1310b57cec5SDimitry Andric   if (!MI)
1320b57cec5SDimitry Andric     return true;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   if (isDef())
1350b57cec5SDimitry Andric     return !MI->hasExtraDefRegAllocReq(MachineInstr::IgnoreBundle);
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   assert(isUse() && "Reg is not def or use");
1380b57cec5SDimitry Andric   return !MI->hasExtraSrcRegAllocReq(MachineInstr::IgnoreBundle);
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric void MachineOperand::setIsRenamable(bool Val) {
1420b57cec5SDimitry Andric   assert(isReg() && "Wrong MachineOperand accessor");
143bdd1243dSDimitry Andric   assert(getReg().isPhysical() &&
1440b57cec5SDimitry Andric          "setIsRenamable should only be called on physical registers");
1450b57cec5SDimitry Andric   IsRenamable = Val;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric // If this operand is currently a register operand, and if this is in a
1490b57cec5SDimitry Andric // function, deregister the operand from the register's use/def list.
1500b57cec5SDimitry Andric void MachineOperand::removeRegFromUses() {
1510b57cec5SDimitry Andric   if (!isReg() || !isOnRegUseList())
1520b57cec5SDimitry Andric     return;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   if (MachineFunction *MF = getMFIfAvailable(*this))
1550b57cec5SDimitry Andric     MF->getRegInfo().removeRegOperandFromUseList(this);
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric /// ChangeToImmediate - Replace this operand with a new immediate operand of
1590b57cec5SDimitry Andric /// the specified value.  If an operand is known to be an immediate already,
1600b57cec5SDimitry Andric /// the setImm method should be used.
161e8d8bef9SDimitry Andric void MachineOperand::ChangeToImmediate(int64_t ImmVal, unsigned TargetFlags) {
1620b57cec5SDimitry Andric   assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm");
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   removeRegFromUses();
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   OpKind = MO_Immediate;
1670b57cec5SDimitry Andric   Contents.ImmVal = ImmVal;
168e8d8bef9SDimitry Andric   setTargetFlags(TargetFlags);
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
171e8d8bef9SDimitry Andric void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm,
172e8d8bef9SDimitry Andric                                          unsigned TargetFlags) {
1730b57cec5SDimitry Andric   assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm");
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   removeRegFromUses();
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   OpKind = MO_FPImmediate;
1780b57cec5SDimitry Andric   Contents.CFP = FPImm;
179e8d8bef9SDimitry Andric   setTargetFlags(TargetFlags);
1800b57cec5SDimitry Andric }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric void MachineOperand::ChangeToES(const char *SymName,
1838bcb0991SDimitry Andric                                 unsigned TargetFlags) {
1840b57cec5SDimitry Andric   assert((!isReg() || !isTied()) &&
1850b57cec5SDimitry Andric          "Cannot change a tied operand into an external symbol");
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   removeRegFromUses();
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   OpKind = MO_ExternalSymbol;
1900b57cec5SDimitry Andric   Contents.OffsetedInfo.Val.SymbolName = SymName;
1910b57cec5SDimitry Andric   setOffset(0); // Offset is always 0.
1920b57cec5SDimitry Andric   setTargetFlags(TargetFlags);
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset,
1968bcb0991SDimitry Andric                                 unsigned TargetFlags) {
1970b57cec5SDimitry Andric   assert((!isReg() || !isTied()) &&
1980b57cec5SDimitry Andric          "Cannot change a tied operand into a global address");
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   removeRegFromUses();
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   OpKind = MO_GlobalAddress;
2030b57cec5SDimitry Andric   Contents.OffsetedInfo.Val.GV = GV;
2040b57cec5SDimitry Andric   setOffset(Offset);
2050b57cec5SDimitry Andric   setTargetFlags(TargetFlags);
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
208e8d8bef9SDimitry Andric void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym, unsigned TargetFlags) {
2090b57cec5SDimitry Andric   assert((!isReg() || !isTied()) &&
2100b57cec5SDimitry Andric          "Cannot change a tied operand into an MCSymbol");
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   removeRegFromUses();
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   OpKind = MO_MCSymbol;
2150b57cec5SDimitry Andric   Contents.Sym = Sym;
216e8d8bef9SDimitry Andric   setTargetFlags(TargetFlags);
2170b57cec5SDimitry Andric }
2180b57cec5SDimitry Andric 
219e8d8bef9SDimitry Andric void MachineOperand::ChangeToFrameIndex(int Idx, unsigned TargetFlags) {
2200b57cec5SDimitry Andric   assert((!isReg() || !isTied()) &&
2210b57cec5SDimitry Andric          "Cannot change a tied operand into a FrameIndex");
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   removeRegFromUses();
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric   OpKind = MO_FrameIndex;
2260b57cec5SDimitry Andric   setIndex(Idx);
227e8d8bef9SDimitry Andric   setTargetFlags(TargetFlags);
2280b57cec5SDimitry Andric }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric void MachineOperand::ChangeToTargetIndex(unsigned Idx, int64_t Offset,
2318bcb0991SDimitry Andric                                          unsigned TargetFlags) {
2320b57cec5SDimitry Andric   assert((!isReg() || !isTied()) &&
2330b57cec5SDimitry Andric          "Cannot change a tied operand into a FrameIndex");
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   removeRegFromUses();
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   OpKind = MO_TargetIndex;
2380b57cec5SDimitry Andric   setIndex(Idx);
2390b57cec5SDimitry Andric   setOffset(Offset);
2400b57cec5SDimitry Andric   setTargetFlags(TargetFlags);
2410b57cec5SDimitry Andric }
2420b57cec5SDimitry Andric 
243bdd1243dSDimitry Andric void MachineOperand::ChangeToDbgInstrRef(unsigned InstrIdx, unsigned OpIdx,
244bdd1243dSDimitry Andric                                          unsigned TargetFlags) {
245bdd1243dSDimitry Andric   assert((!isReg() || !isTied()) &&
246bdd1243dSDimitry Andric          "Cannot change a tied operand into a DbgInstrRef");
247bdd1243dSDimitry Andric 
248bdd1243dSDimitry Andric   removeRegFromUses();
249bdd1243dSDimitry Andric 
250bdd1243dSDimitry Andric   OpKind = MO_DbgInstrRef;
251bdd1243dSDimitry Andric   setInstrRefInstrIndex(InstrIdx);
252bdd1243dSDimitry Andric   setInstrRefOpIndex(OpIdx);
253bdd1243dSDimitry Andric   setTargetFlags(TargetFlags);
254bdd1243dSDimitry Andric }
255bdd1243dSDimitry Andric 
2560b57cec5SDimitry Andric /// ChangeToRegister - Replace this operand with a new register operand of
2570b57cec5SDimitry Andric /// the specified value.  If an operand is known to be an register already,
2580b57cec5SDimitry Andric /// the setReg method should be used.
2598bcb0991SDimitry Andric void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp,
2600b57cec5SDimitry Andric                                       bool isKill, bool isDead, bool isUndef,
2610b57cec5SDimitry Andric                                       bool isDebug) {
2620b57cec5SDimitry Andric   MachineRegisterInfo *RegInfo = nullptr;
2630b57cec5SDimitry Andric   if (MachineFunction *MF = getMFIfAvailable(*this))
2640b57cec5SDimitry Andric     RegInfo = &MF->getRegInfo();
2650b57cec5SDimitry Andric   // If this operand is already a register operand, remove it from the
2660b57cec5SDimitry Andric   // register's use/def lists.
2670b57cec5SDimitry Andric   bool WasReg = isReg();
2680b57cec5SDimitry Andric   if (RegInfo && WasReg)
2690b57cec5SDimitry Andric     RegInfo->removeRegOperandFromUseList(this);
2700b57cec5SDimitry Andric 
271349cc55cSDimitry Andric   // Ensure debug instructions set debug flag on register uses.
272349cc55cSDimitry Andric   const MachineInstr *MI = getParent();
273349cc55cSDimitry Andric   if (!isDef && MI && MI->isDebugInstr())
274349cc55cSDimitry Andric     isDebug = true;
275349cc55cSDimitry Andric 
2760b57cec5SDimitry Andric   // Change this to a register and set the reg#.
2770b57cec5SDimitry Andric   assert(!(isDead && !isDef) && "Dead flag on non-def");
2780b57cec5SDimitry Andric   assert(!(isKill && isDef) && "Kill flag on def");
2790b57cec5SDimitry Andric   OpKind = MO_Register;
2800b57cec5SDimitry Andric   SmallContents.RegNo = Reg;
2810b57cec5SDimitry Andric   SubReg_TargetFlags = 0;
2820b57cec5SDimitry Andric   IsDef = isDef;
2830b57cec5SDimitry Andric   IsImp = isImp;
2840b57cec5SDimitry Andric   IsDeadOrKill = isKill | isDead;
2850b57cec5SDimitry Andric   IsRenamable = false;
2860b57cec5SDimitry Andric   IsUndef = isUndef;
2870b57cec5SDimitry Andric   IsInternalRead = false;
2880b57cec5SDimitry Andric   IsEarlyClobber = false;
2890b57cec5SDimitry Andric   IsDebug = isDebug;
2900b57cec5SDimitry Andric   // Ensure isOnRegUseList() returns false.
2910b57cec5SDimitry Andric   Contents.Reg.Prev = nullptr;
2920b57cec5SDimitry Andric   // Preserve the tie when the operand was already a register.
2930b57cec5SDimitry Andric   if (!WasReg)
2940b57cec5SDimitry Andric     TiedTo = 0;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric   // If this operand is embedded in a function, add the operand to the
2970b57cec5SDimitry Andric   // register's use/def list.
2980b57cec5SDimitry Andric   if (RegInfo)
2990b57cec5SDimitry Andric     RegInfo->addRegOperandToUseList(this);
3000b57cec5SDimitry Andric }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric /// isIdenticalTo - Return true if this operand is identical to the specified
3030b57cec5SDimitry Andric /// operand. Note that this should stay in sync with the hash_value overload
3040b57cec5SDimitry Andric /// below.
3050b57cec5SDimitry Andric bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
3060b57cec5SDimitry Andric   if (getType() != Other.getType() ||
3070b57cec5SDimitry Andric       getTargetFlags() != Other.getTargetFlags())
3080b57cec5SDimitry Andric     return false;
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   switch (getType()) {
3110b57cec5SDimitry Andric   case MachineOperand::MO_Register:
3120b57cec5SDimitry Andric     return getReg() == Other.getReg() && isDef() == Other.isDef() &&
3130b57cec5SDimitry Andric            getSubReg() == Other.getSubReg();
3140b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
3150b57cec5SDimitry Andric     return getImm() == Other.getImm();
3160b57cec5SDimitry Andric   case MachineOperand::MO_CImmediate:
3170b57cec5SDimitry Andric     return getCImm() == Other.getCImm();
3180b57cec5SDimitry Andric   case MachineOperand::MO_FPImmediate:
3190b57cec5SDimitry Andric     return getFPImm() == Other.getFPImm();
3200b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
3210b57cec5SDimitry Andric     return getMBB() == Other.getMBB();
3220b57cec5SDimitry Andric   case MachineOperand::MO_FrameIndex:
3230b57cec5SDimitry Andric     return getIndex() == Other.getIndex();
3240b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
3250b57cec5SDimitry Andric   case MachineOperand::MO_TargetIndex:
3260b57cec5SDimitry Andric     return getIndex() == Other.getIndex() && getOffset() == Other.getOffset();
3270b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
3280b57cec5SDimitry Andric     return getIndex() == Other.getIndex();
3290b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
3300b57cec5SDimitry Andric     return getGlobal() == Other.getGlobal() && getOffset() == Other.getOffset();
3310b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
3320b57cec5SDimitry Andric     return strcmp(getSymbolName(), Other.getSymbolName()) == 0 &&
3330b57cec5SDimitry Andric            getOffset() == Other.getOffset();
3340b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress:
3350b57cec5SDimitry Andric     return getBlockAddress() == Other.getBlockAddress() &&
3360b57cec5SDimitry Andric            getOffset() == Other.getOffset();
3370b57cec5SDimitry Andric   case MachineOperand::MO_RegisterMask:
3380b57cec5SDimitry Andric   case MachineOperand::MO_RegisterLiveOut: {
3390b57cec5SDimitry Andric     // Shallow compare of the two RegMasks
3400b57cec5SDimitry Andric     const uint32_t *RegMask = getRegMask();
3410b57cec5SDimitry Andric     const uint32_t *OtherRegMask = Other.getRegMask();
3420b57cec5SDimitry Andric     if (RegMask == OtherRegMask)
3430b57cec5SDimitry Andric       return true;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(*this)) {
3460b57cec5SDimitry Andric       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
347bdd1243dSDimitry Andric       unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs());
3480b57cec5SDimitry Andric       // Deep compare of the two RegMasks
3490b57cec5SDimitry Andric       return std::equal(RegMask, RegMask + RegMaskSize, OtherRegMask);
3500b57cec5SDimitry Andric     }
3510b57cec5SDimitry Andric     // We don't know the size of the RegMask, so we can't deep compare the two
3520b57cec5SDimitry Andric     // reg masks.
3530b57cec5SDimitry Andric     return false;
3540b57cec5SDimitry Andric   }
3550b57cec5SDimitry Andric   case MachineOperand::MO_MCSymbol:
3560b57cec5SDimitry Andric     return getMCSymbol() == Other.getMCSymbol();
357bdd1243dSDimitry Andric   case MachineOperand::MO_DbgInstrRef:
358bdd1243dSDimitry Andric     return getInstrRefInstrIndex() == Other.getInstrRefInstrIndex() &&
359bdd1243dSDimitry Andric            getInstrRefOpIndex() == Other.getInstrRefOpIndex();
3600b57cec5SDimitry Andric   case MachineOperand::MO_CFIIndex:
3610b57cec5SDimitry Andric     return getCFIIndex() == Other.getCFIIndex();
3620b57cec5SDimitry Andric   case MachineOperand::MO_Metadata:
3630b57cec5SDimitry Andric     return getMetadata() == Other.getMetadata();
3640b57cec5SDimitry Andric   case MachineOperand::MO_IntrinsicID:
3650b57cec5SDimitry Andric     return getIntrinsicID() == Other.getIntrinsicID();
3660b57cec5SDimitry Andric   case MachineOperand::MO_Predicate:
3670b57cec5SDimitry Andric     return getPredicate() == Other.getPredicate();
3688bcb0991SDimitry Andric   case MachineOperand::MO_ShuffleMask:
3698bcb0991SDimitry Andric     return getShuffleMask() == Other.getShuffleMask();
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric   llvm_unreachable("Invalid machine operand type");
3720b57cec5SDimitry Andric }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric // Note: this must stay exactly in sync with isIdenticalTo above.
3750b57cec5SDimitry Andric hash_code llvm::hash_value(const MachineOperand &MO) {
3760b57cec5SDimitry Andric   switch (MO.getType()) {
3770b57cec5SDimitry Andric   case MachineOperand::MO_Register:
3780b57cec5SDimitry Andric     // Register operands don't have target flags.
3790b57cec5SDimitry Andric     return hash_combine(MO.getType(), (unsigned)MO.getReg(), MO.getSubReg(), MO.isDef());
3800b57cec5SDimitry Andric   case MachineOperand::MO_Immediate:
3810b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm());
3820b57cec5SDimitry Andric   case MachineOperand::MO_CImmediate:
3830b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm());
3840b57cec5SDimitry Andric   case MachineOperand::MO_FPImmediate:
3850b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm());
3860b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
3870b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB());
3880b57cec5SDimitry Andric   case MachineOperand::MO_FrameIndex:
3890b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
3900b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
3910b57cec5SDimitry Andric   case MachineOperand::MO_TargetIndex:
3920b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(),
3930b57cec5SDimitry Andric                         MO.getOffset());
3940b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
3950b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex());
3960b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol:
3970b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(),
3980b57cec5SDimitry Andric                         StringRef(MO.getSymbolName()));
3990b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
4000b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(),
4010b57cec5SDimitry Andric                         MO.getOffset());
4020b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress:
4030b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(),
4040b57cec5SDimitry Andric                         MO.getOffset());
4050b57cec5SDimitry Andric   case MachineOperand::MO_RegisterMask:
406bdd1243dSDimitry Andric   case MachineOperand::MO_RegisterLiveOut: {
407bdd1243dSDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(MO)) {
408bdd1243dSDimitry Andric       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
409bdd1243dSDimitry Andric       unsigned RegMaskSize = MachineOperand::getRegMaskSize(TRI->getNumRegs());
410bdd1243dSDimitry Andric       const uint32_t *RegMask = MO.getRegMask();
411bdd1243dSDimitry Andric       std::vector<stable_hash> RegMaskHashes(RegMask, RegMask + RegMaskSize);
412bdd1243dSDimitry Andric       return hash_combine(MO.getType(), MO.getTargetFlags(),
413bdd1243dSDimitry Andric                           stable_hash_combine_array(RegMaskHashes.data(),
414bdd1243dSDimitry Andric                                                     RegMaskHashes.size()));
415bdd1243dSDimitry Andric     }
416bdd1243dSDimitry Andric 
417bdd1243dSDimitry Andric     assert(0 && "MachineOperand not associated with any MachineFunction");
418bdd1243dSDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags());
419bdd1243dSDimitry Andric   }
4200b57cec5SDimitry Andric   case MachineOperand::MO_Metadata:
4210b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata());
4220b57cec5SDimitry Andric   case MachineOperand::MO_MCSymbol:
4230b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol());
424bdd1243dSDimitry Andric   case MachineOperand::MO_DbgInstrRef:
425bdd1243dSDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(),
426bdd1243dSDimitry Andric                         MO.getInstrRefInstrIndex(), MO.getInstrRefOpIndex());
4270b57cec5SDimitry Andric   case MachineOperand::MO_CFIIndex:
4280b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex());
4290b57cec5SDimitry Andric   case MachineOperand::MO_IntrinsicID:
4300b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
4310b57cec5SDimitry Andric   case MachineOperand::MO_Predicate:
4320b57cec5SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate());
4338bcb0991SDimitry Andric   case MachineOperand::MO_ShuffleMask:
4348bcb0991SDimitry Andric     return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask());
4350b57cec5SDimitry Andric   }
4360b57cec5SDimitry Andric   llvm_unreachable("Invalid machine operand type");
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric // Try to crawl up to the machine function and get TRI and IntrinsicInfo from
4400b57cec5SDimitry Andric // it.
4410b57cec5SDimitry Andric static void tryToGetTargetInfo(const MachineOperand &MO,
4420b57cec5SDimitry Andric                                const TargetRegisterInfo *&TRI,
4430b57cec5SDimitry Andric                                const TargetIntrinsicInfo *&IntrinsicInfo) {
4440b57cec5SDimitry Andric   if (const MachineFunction *MF = getMFIfAvailable(MO)) {
4450b57cec5SDimitry Andric     TRI = MF->getSubtarget().getRegisterInfo();
4460b57cec5SDimitry Andric     IntrinsicInfo = MF->getTarget().getIntrinsicInfo();
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric }
4490b57cec5SDimitry Andric 
4500b57cec5SDimitry Andric static const char *getTargetIndexName(const MachineFunction &MF, int Index) {
4510b57cec5SDimitry Andric   const auto *TII = MF.getSubtarget().getInstrInfo();
4520b57cec5SDimitry Andric   assert(TII && "expected instruction info");
4530b57cec5SDimitry Andric   auto Indices = TII->getSerializableTargetIndices();
4540b57cec5SDimitry Andric   auto Found = find_if(Indices, [&](const std::pair<int, const char *> &I) {
4550b57cec5SDimitry Andric     return I.first == Index;
4560b57cec5SDimitry Andric   });
4570b57cec5SDimitry Andric   if (Found != Indices.end())
4580b57cec5SDimitry Andric     return Found->second;
4590b57cec5SDimitry Andric   return nullptr;
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric 
462e8d8bef9SDimitry Andric const char *MachineOperand::getTargetIndexName() const {
463e8d8bef9SDimitry Andric   const MachineFunction *MF = getMFIfAvailable(*this);
464e8d8bef9SDimitry Andric   return MF ? ::getTargetIndexName(*MF, this->getIndex()) : nullptr;
465e8d8bef9SDimitry Andric }
466e8d8bef9SDimitry Andric 
4670b57cec5SDimitry Andric static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) {
4680b57cec5SDimitry Andric   auto Flags = TII->getSerializableDirectMachineOperandTargetFlags();
4690b57cec5SDimitry Andric   for (const auto &I : Flags) {
4700b57cec5SDimitry Andric     if (I.first == TF) {
4710b57cec5SDimitry Andric       return I.second;
4720b57cec5SDimitry Andric     }
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric   return nullptr;
4750b57cec5SDimitry Andric }
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS,
4780b57cec5SDimitry Andric                              const TargetRegisterInfo *TRI) {
4790b57cec5SDimitry Andric   if (!TRI) {
4800b57cec5SDimitry Andric     OS << "%dwarfreg." << DwarfReg;
4810b57cec5SDimitry Andric     return;
4820b57cec5SDimitry Andric   }
4830b57cec5SDimitry Andric 
484bdd1243dSDimitry Andric   if (std::optional<unsigned> Reg = TRI->getLLVMRegNum(DwarfReg, true))
4858bcb0991SDimitry Andric     OS << printReg(*Reg, TRI);
4868bcb0991SDimitry Andric   else
4870b57cec5SDimitry Andric     OS << "<badreg>";
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB,
4910b57cec5SDimitry Andric                                   ModuleSlotTracker &MST) {
4920b57cec5SDimitry Andric   OS << "%ir-block.";
4930b57cec5SDimitry Andric   if (BB.hasName()) {
4940b57cec5SDimitry Andric     printLLVMNameWithoutPrefix(OS, BB.getName());
4950b57cec5SDimitry Andric     return;
4960b57cec5SDimitry Andric   }
497bdd1243dSDimitry Andric   std::optional<int> Slot;
4980b57cec5SDimitry Andric   if (const Function *F = BB.getParent()) {
4990b57cec5SDimitry Andric     if (F == MST.getCurrentFunction()) {
5000b57cec5SDimitry Andric       Slot = MST.getLocalSlot(&BB);
5010b57cec5SDimitry Andric     } else if (const Module *M = F->getParent()) {
5020b57cec5SDimitry Andric       ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false);
5030b57cec5SDimitry Andric       CustomMST.incorporateFunction(*F);
5040b57cec5SDimitry Andric       Slot = CustomMST.getLocalSlot(&BB);
5050b57cec5SDimitry Andric     }
5060b57cec5SDimitry Andric   }
5070b57cec5SDimitry Andric   if (Slot)
5080b57cec5SDimitry Andric     MachineOperand::printIRSlotNumber(OS, *Slot);
5090b57cec5SDimitry Andric   else
5100b57cec5SDimitry Andric     OS << "<unknown>";
5110b57cec5SDimitry Andric }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric static void printSyncScope(raw_ostream &OS, const LLVMContext &Context,
5140b57cec5SDimitry Andric                            SyncScope::ID SSID,
5150b57cec5SDimitry Andric                            SmallVectorImpl<StringRef> &SSNs) {
5160b57cec5SDimitry Andric   switch (SSID) {
5170b57cec5SDimitry Andric   case SyncScope::System:
5180b57cec5SDimitry Andric     break;
5190b57cec5SDimitry Andric   default:
5200b57cec5SDimitry Andric     if (SSNs.empty())
5210b57cec5SDimitry Andric       Context.getSyncScopeNames(SSNs);
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric     OS << "syncscope(\"";
5240b57cec5SDimitry Andric     printEscapedString(SSNs[SSID], OS);
5250b57cec5SDimitry Andric     OS << "\") ";
5260b57cec5SDimitry Andric     break;
5270b57cec5SDimitry Andric   }
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric static const char *getTargetMMOFlagName(const TargetInstrInfo &TII,
5310b57cec5SDimitry Andric                                         unsigned TMMOFlag) {
5320b57cec5SDimitry Andric   auto Flags = TII.getSerializableMachineMemOperandTargetFlags();
5330b57cec5SDimitry Andric   for (const auto &I : Flags) {
5340b57cec5SDimitry Andric     if (I.first == TMMOFlag) {
5350b57cec5SDimitry Andric       return I.second;
5360b57cec5SDimitry Andric     }
5370b57cec5SDimitry Andric   }
5380b57cec5SDimitry Andric   return nullptr;
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric static void printFrameIndex(raw_ostream& OS, int FrameIndex, bool IsFixed,
5420b57cec5SDimitry Andric                             const MachineFrameInfo *MFI) {
5430b57cec5SDimitry Andric   StringRef Name;
5440b57cec5SDimitry Andric   if (MFI) {
5450b57cec5SDimitry Andric     IsFixed = MFI->isFixedObjectIndex(FrameIndex);
5460b57cec5SDimitry Andric     if (const AllocaInst *Alloca = MFI->getObjectAllocation(FrameIndex))
5470b57cec5SDimitry Andric       if (Alloca->hasName())
5480b57cec5SDimitry Andric         Name = Alloca->getName();
5490b57cec5SDimitry Andric     if (IsFixed)
5500b57cec5SDimitry Andric       FrameIndex -= MFI->getObjectIndexBegin();
5510b57cec5SDimitry Andric   }
5520b57cec5SDimitry Andric   MachineOperand::printStackObjectReference(OS, FrameIndex, IsFixed, Name);
5530b57cec5SDimitry Andric }
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric void MachineOperand::printSubRegIdx(raw_ostream &OS, uint64_t Index,
5560b57cec5SDimitry Andric                                     const TargetRegisterInfo *TRI) {
5570b57cec5SDimitry Andric   OS << "%subreg.";
558bdd1243dSDimitry Andric   if (TRI && Index != 0 && Index < TRI->getNumSubRegIndices())
5590b57cec5SDimitry Andric     OS << TRI->getSubRegIndexName(Index);
5600b57cec5SDimitry Andric   else
5610b57cec5SDimitry Andric     OS << Index;
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric void MachineOperand::printTargetFlags(raw_ostream &OS,
5650b57cec5SDimitry Andric                                       const MachineOperand &Op) {
5660b57cec5SDimitry Andric   if (!Op.getTargetFlags())
5670b57cec5SDimitry Andric     return;
5680b57cec5SDimitry Andric   const MachineFunction *MF = getMFIfAvailable(Op);
5690b57cec5SDimitry Andric   if (!MF)
5700b57cec5SDimitry Andric     return;
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric   const auto *TII = MF->getSubtarget().getInstrInfo();
5730b57cec5SDimitry Andric   assert(TII && "expected instruction info");
5740b57cec5SDimitry Andric   auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags());
5750b57cec5SDimitry Andric   OS << "target-flags(";
5760b57cec5SDimitry Andric   const bool HasDirectFlags = Flags.first;
5770b57cec5SDimitry Andric   const bool HasBitmaskFlags = Flags.second;
5780b57cec5SDimitry Andric   if (!HasDirectFlags && !HasBitmaskFlags) {
5790b57cec5SDimitry Andric     OS << "<unknown>) ";
5800b57cec5SDimitry Andric     return;
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric   if (HasDirectFlags) {
5830b57cec5SDimitry Andric     if (const auto *Name = getTargetFlagName(TII, Flags.first))
5840b57cec5SDimitry Andric       OS << Name;
5850b57cec5SDimitry Andric     else
5860b57cec5SDimitry Andric       OS << "<unknown target flag>";
5870b57cec5SDimitry Andric   }
5880b57cec5SDimitry Andric   if (!HasBitmaskFlags) {
5890b57cec5SDimitry Andric     OS << ") ";
5900b57cec5SDimitry Andric     return;
5910b57cec5SDimitry Andric   }
5920b57cec5SDimitry Andric   bool IsCommaNeeded = HasDirectFlags;
5930b57cec5SDimitry Andric   unsigned BitMask = Flags.second;
5940b57cec5SDimitry Andric   auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags();
5950b57cec5SDimitry Andric   for (const auto &Mask : BitMasks) {
5960b57cec5SDimitry Andric     // Check if the flag's bitmask has the bits of the current mask set.
5970b57cec5SDimitry Andric     if ((BitMask & Mask.first) == Mask.first) {
5980b57cec5SDimitry Andric       if (IsCommaNeeded)
5990b57cec5SDimitry Andric         OS << ", ";
6000b57cec5SDimitry Andric       IsCommaNeeded = true;
6010b57cec5SDimitry Andric       OS << Mask.second;
6020b57cec5SDimitry Andric       // Clear the bits which were serialized from the flag's bitmask.
6030b57cec5SDimitry Andric       BitMask &= ~(Mask.first);
6040b57cec5SDimitry Andric     }
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric   if (BitMask) {
6070b57cec5SDimitry Andric     // When the resulting flag's bitmask isn't zero, we know that we didn't
6080b57cec5SDimitry Andric     // serialize all of the bit flags.
6090b57cec5SDimitry Andric     if (IsCommaNeeded)
6100b57cec5SDimitry Andric       OS << ", ";
6110b57cec5SDimitry Andric     OS << "<unknown bitmask target flag>";
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric   OS << ") ";
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric void MachineOperand::printSymbol(raw_ostream &OS, MCSymbol &Sym) {
6170b57cec5SDimitry Andric   OS << "<mcsymbol " << Sym << ">";
6180b57cec5SDimitry Andric }
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric void MachineOperand::printStackObjectReference(raw_ostream &OS,
6210b57cec5SDimitry Andric                                                unsigned FrameIndex,
6220b57cec5SDimitry Andric                                                bool IsFixed, StringRef Name) {
6230b57cec5SDimitry Andric   if (IsFixed) {
6240b57cec5SDimitry Andric     OS << "%fixed-stack." << FrameIndex;
6250b57cec5SDimitry Andric     return;
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   OS << "%stack." << FrameIndex;
6290b57cec5SDimitry Andric   if (!Name.empty())
6300b57cec5SDimitry Andric     OS << '.' << Name;
6310b57cec5SDimitry Andric }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric void MachineOperand::printOperandOffset(raw_ostream &OS, int64_t Offset) {
6340b57cec5SDimitry Andric   if (Offset == 0)
6350b57cec5SDimitry Andric     return;
6360b57cec5SDimitry Andric   if (Offset < 0) {
6370b57cec5SDimitry Andric     OS << " - " << -Offset;
6380b57cec5SDimitry Andric     return;
6390b57cec5SDimitry Andric   }
6400b57cec5SDimitry Andric   OS << " + " << Offset;
6410b57cec5SDimitry Andric }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric void MachineOperand::printIRSlotNumber(raw_ostream &OS, int Slot) {
6440b57cec5SDimitry Andric   if (Slot == -1)
6450b57cec5SDimitry Andric     OS << "<badref>";
6460b57cec5SDimitry Andric   else
6470b57cec5SDimitry Andric     OS << Slot;
6480b57cec5SDimitry Andric }
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI,
6510b57cec5SDimitry Andric                      const TargetRegisterInfo *TRI) {
6520b57cec5SDimitry Andric   switch (CFI.getOperation()) {
6530b57cec5SDimitry Andric   case MCCFIInstruction::OpSameValue:
6540b57cec5SDimitry Andric     OS << "same_value ";
6550b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6560b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6570b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
6580b57cec5SDimitry Andric     break;
6590b57cec5SDimitry Andric   case MCCFIInstruction::OpRememberState:
6600b57cec5SDimitry Andric     OS << "remember_state ";
6610b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6620b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6630b57cec5SDimitry Andric     break;
6640b57cec5SDimitry Andric   case MCCFIInstruction::OpRestoreState:
6650b57cec5SDimitry Andric     OS << "restore_state ";
6660b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6670b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6680b57cec5SDimitry Andric     break;
6690b57cec5SDimitry Andric   case MCCFIInstruction::OpOffset:
6700b57cec5SDimitry Andric     OS << "offset ";
6710b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6720b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6730b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
6740b57cec5SDimitry Andric     OS << ", " << CFI.getOffset();
6750b57cec5SDimitry Andric     break;
6760b57cec5SDimitry Andric   case MCCFIInstruction::OpDefCfaRegister:
6770b57cec5SDimitry Andric     OS << "def_cfa_register ";
6780b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6790b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6800b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
6810b57cec5SDimitry Andric     break;
6820b57cec5SDimitry Andric   case MCCFIInstruction::OpDefCfaOffset:
6830b57cec5SDimitry Andric     OS << "def_cfa_offset ";
6840b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6850b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6860b57cec5SDimitry Andric     OS << CFI.getOffset();
6870b57cec5SDimitry Andric     break;
6880b57cec5SDimitry Andric   case MCCFIInstruction::OpDefCfa:
6890b57cec5SDimitry Andric     OS << "def_cfa ";
6900b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
6910b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
6920b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
6930b57cec5SDimitry Andric     OS << ", " << CFI.getOffset();
6940b57cec5SDimitry Andric     break;
695fe6060f1SDimitry Andric   case MCCFIInstruction::OpLLVMDefAspaceCfa:
696fe6060f1SDimitry Andric     OS << "llvm_def_aspace_cfa ";
697fe6060f1SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
698fe6060f1SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
699fe6060f1SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
700fe6060f1SDimitry Andric     OS << ", " << CFI.getOffset();
701fe6060f1SDimitry Andric     OS << ", " << CFI.getAddressSpace();
702fe6060f1SDimitry Andric     break;
7030b57cec5SDimitry Andric   case MCCFIInstruction::OpRelOffset:
7040b57cec5SDimitry Andric     OS << "rel_offset ";
7050b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7060b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7070b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
7080b57cec5SDimitry Andric     OS << ", " << CFI.getOffset();
7090b57cec5SDimitry Andric     break;
7100b57cec5SDimitry Andric   case MCCFIInstruction::OpAdjustCfaOffset:
7110b57cec5SDimitry Andric     OS << "adjust_cfa_offset ";
7120b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7130b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7140b57cec5SDimitry Andric     OS << CFI.getOffset();
7150b57cec5SDimitry Andric     break;
7160b57cec5SDimitry Andric   case MCCFIInstruction::OpRestore:
7170b57cec5SDimitry Andric     OS << "restore ";
7180b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7190b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7200b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
7210b57cec5SDimitry Andric     break;
7220b57cec5SDimitry Andric   case MCCFIInstruction::OpEscape: {
7230b57cec5SDimitry Andric     OS << "escape ";
7240b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7250b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7260b57cec5SDimitry Andric     if (!CFI.getValues().empty()) {
7270b57cec5SDimitry Andric       size_t e = CFI.getValues().size() - 1;
7280b57cec5SDimitry Andric       for (size_t i = 0; i < e; ++i)
7290b57cec5SDimitry Andric         OS << format("0x%02x", uint8_t(CFI.getValues()[i])) << ", ";
7305ffd83dbSDimitry Andric       OS << format("0x%02x", uint8_t(CFI.getValues()[e]));
7310b57cec5SDimitry Andric     }
7320b57cec5SDimitry Andric     break;
7330b57cec5SDimitry Andric   }
7340b57cec5SDimitry Andric   case MCCFIInstruction::OpUndefined:
7350b57cec5SDimitry Andric     OS << "undefined ";
7360b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7370b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7380b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
7390b57cec5SDimitry Andric     break;
7400b57cec5SDimitry Andric   case MCCFIInstruction::OpRegister:
7410b57cec5SDimitry Andric     OS << "register ";
7420b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7430b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7440b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister(), OS, TRI);
7450b57cec5SDimitry Andric     OS << ", ";
7460b57cec5SDimitry Andric     printCFIRegister(CFI.getRegister2(), OS, TRI);
7470b57cec5SDimitry Andric     break;
7480b57cec5SDimitry Andric   case MCCFIInstruction::OpWindowSave:
7490b57cec5SDimitry Andric     OS << "window_save ";
7500b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7510b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7520b57cec5SDimitry Andric     break;
7530b57cec5SDimitry Andric   case MCCFIInstruction::OpNegateRAState:
7540b57cec5SDimitry Andric     OS << "negate_ra_sign_state ";
7550b57cec5SDimitry Andric     if (MCSymbol *Label = CFI.getLabel())
7560b57cec5SDimitry Andric       MachineOperand::printSymbol(OS, *Label);
7570b57cec5SDimitry Andric     break;
7580b57cec5SDimitry Andric   default:
7590b57cec5SDimitry Andric     // TODO: Print the other CFI Operations.
7600b57cec5SDimitry Andric     OS << "<unserializable cfi directive>";
7610b57cec5SDimitry Andric     break;
7620b57cec5SDimitry Andric   }
7630b57cec5SDimitry Andric }
7640b57cec5SDimitry Andric 
7650b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI,
7660b57cec5SDimitry Andric                            const TargetIntrinsicInfo *IntrinsicInfo) const {
7670b57cec5SDimitry Andric   print(OS, LLT{}, TRI, IntrinsicInfo);
7680b57cec5SDimitry Andric }
7690b57cec5SDimitry Andric 
7700b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, LLT TypeToPrint,
7710b57cec5SDimitry Andric                            const TargetRegisterInfo *TRI,
7720b57cec5SDimitry Andric                            const TargetIntrinsicInfo *IntrinsicInfo) const {
7730b57cec5SDimitry Andric   tryToGetTargetInfo(*this, TRI, IntrinsicInfo);
7740b57cec5SDimitry Andric   ModuleSlotTracker DummyMST(nullptr);
775bdd1243dSDimitry Andric   print(OS, DummyMST, TypeToPrint, std::nullopt, /*PrintDef=*/false,
776480093f4SDimitry Andric         /*IsStandalone=*/true,
7770b57cec5SDimitry Andric         /*ShouldPrintRegisterTies=*/true,
7780b57cec5SDimitry Andric         /*TiedOperandIdx=*/0, TRI, IntrinsicInfo);
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
782bdd1243dSDimitry Andric                            LLT TypeToPrint, std::optional<unsigned> OpIdx,
783bdd1243dSDimitry Andric                            bool PrintDef, bool IsStandalone,
784bdd1243dSDimitry Andric                            bool ShouldPrintRegisterTies,
7850b57cec5SDimitry Andric                            unsigned TiedOperandIdx,
7860b57cec5SDimitry Andric                            const TargetRegisterInfo *TRI,
7870b57cec5SDimitry Andric                            const TargetIntrinsicInfo *IntrinsicInfo) const {
7880b57cec5SDimitry Andric   printTargetFlags(OS, *this);
7890b57cec5SDimitry Andric   switch (getType()) {
7900b57cec5SDimitry Andric   case MachineOperand::MO_Register: {
7918bcb0991SDimitry Andric     Register Reg = getReg();
7920b57cec5SDimitry Andric     if (isImplicit())
7930b57cec5SDimitry Andric       OS << (isDef() ? "implicit-def " : "implicit ");
7940b57cec5SDimitry Andric     else if (PrintDef && isDef())
7950b57cec5SDimitry Andric       // Print the 'def' flag only when the operand is defined after '='.
7960b57cec5SDimitry Andric       OS << "def ";
7970b57cec5SDimitry Andric     if (isInternalRead())
7980b57cec5SDimitry Andric       OS << "internal ";
7990b57cec5SDimitry Andric     if (isDead())
8000b57cec5SDimitry Andric       OS << "dead ";
8010b57cec5SDimitry Andric     if (isKill())
8020b57cec5SDimitry Andric       OS << "killed ";
8030b57cec5SDimitry Andric     if (isUndef())
8040b57cec5SDimitry Andric       OS << "undef ";
8050b57cec5SDimitry Andric     if (isEarlyClobber())
8060b57cec5SDimitry Andric       OS << "early-clobber ";
807bdd1243dSDimitry Andric     if (getReg().isPhysical() && isRenamable())
8080b57cec5SDimitry Andric       OS << "renamable ";
8090b57cec5SDimitry Andric     // isDebug() is exactly true for register operands of a DBG_VALUE. So we
8100b57cec5SDimitry Andric     // simply infer it when parsing and do not need to print it.
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric     const MachineRegisterInfo *MRI = nullptr;
813bdd1243dSDimitry Andric     if (Reg.isVirtual()) {
8140b57cec5SDimitry Andric       if (const MachineFunction *MF = getMFIfAvailable(*this)) {
8150b57cec5SDimitry Andric         MRI = &MF->getRegInfo();
8160b57cec5SDimitry Andric       }
8170b57cec5SDimitry Andric     }
8180b57cec5SDimitry Andric 
8190b57cec5SDimitry Andric     OS << printReg(Reg, TRI, 0, MRI);
8200b57cec5SDimitry Andric     // Print the sub register.
8210b57cec5SDimitry Andric     if (unsigned SubReg = getSubReg()) {
8220b57cec5SDimitry Andric       if (TRI)
8230b57cec5SDimitry Andric         OS << '.' << TRI->getSubRegIndexName(SubReg);
8240b57cec5SDimitry Andric       else
8250b57cec5SDimitry Andric         OS << ".subreg" << SubReg;
8260b57cec5SDimitry Andric     }
8270b57cec5SDimitry Andric     // Print the register class / bank.
828bdd1243dSDimitry Andric     if (Reg.isVirtual()) {
8290b57cec5SDimitry Andric       if (const MachineFunction *MF = getMFIfAvailable(*this)) {
8300b57cec5SDimitry Andric         const MachineRegisterInfo &MRI = MF->getRegInfo();
8310b57cec5SDimitry Andric         if (IsStandalone || !PrintDef || MRI.def_empty(Reg)) {
8320b57cec5SDimitry Andric           OS << ':';
8330b57cec5SDimitry Andric           OS << printRegClassOrBank(Reg, MRI, TRI);
8340b57cec5SDimitry Andric         }
8350b57cec5SDimitry Andric       }
8360b57cec5SDimitry Andric     }
8370b57cec5SDimitry Andric     // Print ties.
8380b57cec5SDimitry Andric     if (ShouldPrintRegisterTies && isTied() && !isDef())
8390b57cec5SDimitry Andric       OS << "(tied-def " << TiedOperandIdx << ")";
8400b57cec5SDimitry Andric     // Print types.
8410b57cec5SDimitry Andric     if (TypeToPrint.isValid())
8420b57cec5SDimitry Andric       OS << '(' << TypeToPrint << ')';
8430b57cec5SDimitry Andric     break;
8440b57cec5SDimitry Andric   }
845480093f4SDimitry Andric   case MachineOperand::MO_Immediate: {
846480093f4SDimitry Andric     const MIRFormatter *Formatter = nullptr;
847480093f4SDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(*this)) {
848480093f4SDimitry Andric       const auto *TII = MF->getSubtarget().getInstrInfo();
849480093f4SDimitry Andric       assert(TII && "expected instruction info");
850480093f4SDimitry Andric       Formatter = TII->getMIRFormatter();
851480093f4SDimitry Andric     }
852480093f4SDimitry Andric     if (Formatter)
853480093f4SDimitry Andric       Formatter->printImm(OS, *getParent(), OpIdx, getImm());
854480093f4SDimitry Andric     else
8550b57cec5SDimitry Andric       OS << getImm();
8560b57cec5SDimitry Andric     break;
857480093f4SDimitry Andric   }
8580b57cec5SDimitry Andric   case MachineOperand::MO_CImmediate:
8590b57cec5SDimitry Andric     getCImm()->printAsOperand(OS, /*PrintType=*/true, MST);
8600b57cec5SDimitry Andric     break;
8610b57cec5SDimitry Andric   case MachineOperand::MO_FPImmediate:
8620b57cec5SDimitry Andric     getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST);
8630b57cec5SDimitry Andric     break;
8640b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
8650b57cec5SDimitry Andric     OS << printMBBReference(*getMBB());
8660b57cec5SDimitry Andric     break;
8670b57cec5SDimitry Andric   case MachineOperand::MO_FrameIndex: {
8680b57cec5SDimitry Andric     int FrameIndex = getIndex();
8690b57cec5SDimitry Andric     bool IsFixed = false;
8700b57cec5SDimitry Andric     const MachineFrameInfo *MFI = nullptr;
8710b57cec5SDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(*this))
8720b57cec5SDimitry Andric       MFI = &MF->getFrameInfo();
8730b57cec5SDimitry Andric     printFrameIndex(OS, FrameIndex, IsFixed, MFI);
8740b57cec5SDimitry Andric     break;
8750b57cec5SDimitry Andric   }
8760b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
8770b57cec5SDimitry Andric     OS << "%const." << getIndex();
8780b57cec5SDimitry Andric     printOperandOffset(OS, getOffset());
8790b57cec5SDimitry Andric     break;
8800b57cec5SDimitry Andric   case MachineOperand::MO_TargetIndex: {
8810b57cec5SDimitry Andric     OS << "target-index(";
8820b57cec5SDimitry Andric     const char *Name = "<unknown>";
8830b57cec5SDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(*this))
884e8d8bef9SDimitry Andric       if (const auto *TargetIndexName = ::getTargetIndexName(*MF, getIndex()))
8850b57cec5SDimitry Andric         Name = TargetIndexName;
8860b57cec5SDimitry Andric     OS << Name << ')';
8870b57cec5SDimitry Andric     printOperandOffset(OS, getOffset());
8880b57cec5SDimitry Andric     break;
8890b57cec5SDimitry Andric   }
8900b57cec5SDimitry Andric   case MachineOperand::MO_JumpTableIndex:
8910b57cec5SDimitry Andric     OS << printJumpTableEntryReference(getIndex());
8920b57cec5SDimitry Andric     break;
8930b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress:
8940b57cec5SDimitry Andric     getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST);
8950b57cec5SDimitry Andric     printOperandOffset(OS, getOffset());
8960b57cec5SDimitry Andric     break;
8970b57cec5SDimitry Andric   case MachineOperand::MO_ExternalSymbol: {
8980b57cec5SDimitry Andric     StringRef Name = getSymbolName();
8990b57cec5SDimitry Andric     OS << '&';
9000b57cec5SDimitry Andric     if (Name.empty()) {
9010b57cec5SDimitry Andric       OS << "\"\"";
9020b57cec5SDimitry Andric     } else {
9030b57cec5SDimitry Andric       printLLVMNameWithoutPrefix(OS, Name);
9040b57cec5SDimitry Andric     }
9050b57cec5SDimitry Andric     printOperandOffset(OS, getOffset());
9060b57cec5SDimitry Andric     break;
9070b57cec5SDimitry Andric   }
9080b57cec5SDimitry Andric   case MachineOperand::MO_BlockAddress: {
9090b57cec5SDimitry Andric     OS << "blockaddress(";
9100b57cec5SDimitry Andric     getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false,
9110b57cec5SDimitry Andric                                                      MST);
9120b57cec5SDimitry Andric     OS << ", ";
9130b57cec5SDimitry Andric     printIRBlockReference(OS, *getBlockAddress()->getBasicBlock(), MST);
9140b57cec5SDimitry Andric     OS << ')';
9150b57cec5SDimitry Andric     MachineOperand::printOperandOffset(OS, getOffset());
9160b57cec5SDimitry Andric     break;
9170b57cec5SDimitry Andric   }
9180b57cec5SDimitry Andric   case MachineOperand::MO_RegisterMask: {
9190b57cec5SDimitry Andric     OS << "<regmask";
9200b57cec5SDimitry Andric     if (TRI) {
9210b57cec5SDimitry Andric       unsigned NumRegsInMask = 0;
9220b57cec5SDimitry Andric       unsigned NumRegsEmitted = 0;
9230b57cec5SDimitry Andric       for (unsigned i = 0; i < TRI->getNumRegs(); ++i) {
9240b57cec5SDimitry Andric         unsigned MaskWord = i / 32;
9250b57cec5SDimitry Andric         unsigned MaskBit = i % 32;
9260b57cec5SDimitry Andric         if (getRegMask()[MaskWord] & (1 << MaskBit)) {
9270b57cec5SDimitry Andric           if (PrintRegMaskNumRegs < 0 ||
9280b57cec5SDimitry Andric               NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) {
9290b57cec5SDimitry Andric             OS << " " << printReg(i, TRI);
9300b57cec5SDimitry Andric             NumRegsEmitted++;
9310b57cec5SDimitry Andric           }
9320b57cec5SDimitry Andric           NumRegsInMask++;
9330b57cec5SDimitry Andric         }
9340b57cec5SDimitry Andric       }
9350b57cec5SDimitry Andric       if (NumRegsEmitted != NumRegsInMask)
9360b57cec5SDimitry Andric         OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more...";
9370b57cec5SDimitry Andric     } else {
9380b57cec5SDimitry Andric       OS << " ...";
9390b57cec5SDimitry Andric     }
9400b57cec5SDimitry Andric     OS << ">";
9410b57cec5SDimitry Andric     break;
9420b57cec5SDimitry Andric   }
9430b57cec5SDimitry Andric   case MachineOperand::MO_RegisterLiveOut: {
9440b57cec5SDimitry Andric     const uint32_t *RegMask = getRegLiveOut();
9450b57cec5SDimitry Andric     OS << "liveout(";
9460b57cec5SDimitry Andric     if (!TRI) {
9470b57cec5SDimitry Andric       OS << "<unknown>";
9480b57cec5SDimitry Andric     } else {
9490b57cec5SDimitry Andric       bool IsCommaNeeded = false;
9500b57cec5SDimitry Andric       for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) {
9510b57cec5SDimitry Andric         if (RegMask[Reg / 32] & (1U << (Reg % 32))) {
9520b57cec5SDimitry Andric           if (IsCommaNeeded)
9530b57cec5SDimitry Andric             OS << ", ";
9540b57cec5SDimitry Andric           OS << printReg(Reg, TRI);
9550b57cec5SDimitry Andric           IsCommaNeeded = true;
9560b57cec5SDimitry Andric         }
9570b57cec5SDimitry Andric       }
9580b57cec5SDimitry Andric     }
9590b57cec5SDimitry Andric     OS << ")";
9600b57cec5SDimitry Andric     break;
9610b57cec5SDimitry Andric   }
9620b57cec5SDimitry Andric   case MachineOperand::MO_Metadata:
9630b57cec5SDimitry Andric     getMetadata()->printAsOperand(OS, MST);
9640b57cec5SDimitry Andric     break;
9650b57cec5SDimitry Andric   case MachineOperand::MO_MCSymbol:
9660b57cec5SDimitry Andric     printSymbol(OS, *getMCSymbol());
9670b57cec5SDimitry Andric     break;
968bdd1243dSDimitry Andric   case MachineOperand::MO_DbgInstrRef: {
969bdd1243dSDimitry Andric     OS << "dbg-instr-ref(" << getInstrRefInstrIndex() << ", "
970bdd1243dSDimitry Andric        << getInstrRefOpIndex() << ')';
971bdd1243dSDimitry Andric     break;
972bdd1243dSDimitry Andric   }
9730b57cec5SDimitry Andric   case MachineOperand::MO_CFIIndex: {
9740b57cec5SDimitry Andric     if (const MachineFunction *MF = getMFIfAvailable(*this))
9750b57cec5SDimitry Andric       printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI);
9760b57cec5SDimitry Andric     else
9770b57cec5SDimitry Andric       OS << "<cfi directive>";
9780b57cec5SDimitry Andric     break;
9790b57cec5SDimitry Andric   }
9800b57cec5SDimitry Andric   case MachineOperand::MO_IntrinsicID: {
9810b57cec5SDimitry Andric     Intrinsic::ID ID = getIntrinsicID();
9820b57cec5SDimitry Andric     if (ID < Intrinsic::num_intrinsics)
983fe6060f1SDimitry Andric       OS << "intrinsic(@" << Intrinsic::getBaseName(ID) << ')';
9840b57cec5SDimitry Andric     else if (IntrinsicInfo)
9850b57cec5SDimitry Andric       OS << "intrinsic(@" << IntrinsicInfo->getName(ID) << ')';
9860b57cec5SDimitry Andric     else
9870b57cec5SDimitry Andric       OS << "intrinsic(" << ID << ')';
9880b57cec5SDimitry Andric     break;
9890b57cec5SDimitry Andric   }
9900b57cec5SDimitry Andric   case MachineOperand::MO_Predicate: {
9910b57cec5SDimitry Andric     auto Pred = static_cast<CmpInst::Predicate>(getPredicate());
9920b57cec5SDimitry Andric     OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred("
993*fe013be4SDimitry Andric        << Pred << ')';
9940b57cec5SDimitry Andric     break;
9950b57cec5SDimitry Andric   }
9968bcb0991SDimitry Andric   case MachineOperand::MO_ShuffleMask:
9978bcb0991SDimitry Andric     OS << "shufflemask(";
998480093f4SDimitry Andric     ArrayRef<int> Mask = getShuffleMask();
9998bcb0991SDimitry Andric     StringRef Separator;
1000480093f4SDimitry Andric     for (int Elt : Mask) {
1001480093f4SDimitry Andric       if (Elt == -1)
1002480093f4SDimitry Andric         OS << Separator << "undef";
1003480093f4SDimitry Andric       else
1004480093f4SDimitry Andric         OS << Separator << Elt;
10058bcb0991SDimitry Andric       Separator = ", ";
10068bcb0991SDimitry Andric     }
10078bcb0991SDimitry Andric 
10088bcb0991SDimitry Andric     OS << ')';
10098bcb0991SDimitry Andric     break;
10100b57cec5SDimitry Andric   }
10110b57cec5SDimitry Andric }
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
10140b57cec5SDimitry Andric LLVM_DUMP_METHOD void MachineOperand::dump() const { dbgs() << *this << '\n'; }
10150b57cec5SDimitry Andric #endif
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10180b57cec5SDimitry Andric // MachineMemOperand Implementation
10190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric /// getAddrSpace - Return the LLVM IR address space number that this pointer
10220b57cec5SDimitry Andric /// points into.
10230b57cec5SDimitry Andric unsigned MachinePointerInfo::getAddrSpace() const { return AddrSpace; }
10240b57cec5SDimitry Andric 
10250b57cec5SDimitry Andric /// isDereferenceable - Return true if V is always dereferenceable for
10260b57cec5SDimitry Andric /// Offset + Size byte.
10270b57cec5SDimitry Andric bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C,
10280b57cec5SDimitry Andric                                            const DataLayout &DL) const {
1029*fe013be4SDimitry Andric   if (!isa<const Value *>(V))
10300b57cec5SDimitry Andric     return false;
10310b57cec5SDimitry Andric 
1032*fe013be4SDimitry Andric   const Value *BasePtr = cast<const Value *>(V);
10330b57cec5SDimitry Andric   if (BasePtr == nullptr)
10340b57cec5SDimitry Andric     return false;
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   return isDereferenceableAndAlignedPointer(
10375ffd83dbSDimitry Andric       BasePtr, Align(1), APInt(DL.getPointerSizeInBits(), Offset + Size), DL);
10380b57cec5SDimitry Andric }
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric /// getConstantPool - Return a MachinePointerInfo record that refers to the
10410b57cec5SDimitry Andric /// constant pool.
10420b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) {
10430b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getConstantPool());
10440b57cec5SDimitry Andric }
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric /// getFixedStack - Return a MachinePointerInfo record that refers to the
10470b57cec5SDimitry Andric /// the specified FrameIndex.
10480b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getFixedStack(MachineFunction &MF,
10490b57cec5SDimitry Andric                                                      int FI, int64_t Offset) {
10500b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getFixedStack(FI), Offset);
10510b57cec5SDimitry Andric }
10520b57cec5SDimitry Andric 
10530b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getJumpTable(MachineFunction &MF) {
10540b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getJumpTable());
10550b57cec5SDimitry Andric }
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getGOT(MachineFunction &MF) {
10580b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getGOT());
10590b57cec5SDimitry Andric }
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getStack(MachineFunction &MF,
10620b57cec5SDimitry Andric                                                 int64_t Offset, uint8_t ID) {
10630b57cec5SDimitry Andric   return MachinePointerInfo(MF.getPSVManager().getStack(), Offset, ID);
10640b57cec5SDimitry Andric }
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric MachinePointerInfo MachinePointerInfo::getUnknownStack(MachineFunction &MF) {
10670b57cec5SDimitry Andric   return MachinePointerInfo(MF.getDataLayout().getAllocaAddrSpace());
10680b57cec5SDimitry Andric }
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f,
1071fe6060f1SDimitry Andric                                      LLT type, Align a, const AAMDNodes &AAInfo,
10720b57cec5SDimitry Andric                                      const MDNode *Ranges, SyncScope::ID SSID,
10730b57cec5SDimitry Andric                                      AtomicOrdering Ordering,
10740b57cec5SDimitry Andric                                      AtomicOrdering FailureOrdering)
1075fe6060f1SDimitry Andric     : PtrInfo(ptrinfo), MemoryType(type), FlagVals(f), BaseAlign(a),
1076fe6060f1SDimitry Andric       AAInfo(AAInfo), Ranges(Ranges) {
1077*fe013be4SDimitry Andric   assert((PtrInfo.V.isNull() || isa<const PseudoSourceValue *>(PtrInfo.V) ||
1078*fe013be4SDimitry Andric           isa<PointerType>(cast<const Value *>(PtrInfo.V)->getType())) &&
10790b57cec5SDimitry Andric          "invalid pointer value");
10800b57cec5SDimitry Andric   assert((isLoad() || isStore()) && "Not a load/store!");
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   AtomicInfo.SSID = static_cast<unsigned>(SSID);
10830b57cec5SDimitry Andric   assert(getSyncScopeID() == SSID && "Value truncated");
10840b57cec5SDimitry Andric   AtomicInfo.Ordering = static_cast<unsigned>(Ordering);
1085fe6060f1SDimitry Andric   assert(getSuccessOrdering() == Ordering && "Value truncated");
10860b57cec5SDimitry Andric   AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering);
10870b57cec5SDimitry Andric   assert(getFailureOrdering() == FailureOrdering && "Value truncated");
10880b57cec5SDimitry Andric }
10890b57cec5SDimitry Andric 
1090fe6060f1SDimitry Andric MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f,
1091fe6060f1SDimitry Andric                                      uint64_t s, Align a,
1092fe6060f1SDimitry Andric                                      const AAMDNodes &AAInfo,
1093fe6060f1SDimitry Andric                                      const MDNode *Ranges, SyncScope::ID SSID,
1094fe6060f1SDimitry Andric                                      AtomicOrdering Ordering,
1095fe6060f1SDimitry Andric                                      AtomicOrdering FailureOrdering)
1096fe6060f1SDimitry Andric     : MachineMemOperand(ptrinfo, f,
1097fe6060f1SDimitry Andric                         s == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * s), a,
1098fe6060f1SDimitry Andric                         AAInfo, Ranges, SSID, Ordering, FailureOrdering) {}
1099fe6060f1SDimitry Andric 
11000b57cec5SDimitry Andric void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) {
11010b57cec5SDimitry Andric   // The Value and Offset may differ due to CSE. But the flags and size
11020b57cec5SDimitry Andric   // should be the same.
11030b57cec5SDimitry Andric   assert(MMO->getFlags() == getFlags() && "Flags mismatch!");
11044824e7fdSDimitry Andric   assert((MMO->getSize() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) ||
11054824e7fdSDimitry Andric           MMO->getSize() == getSize()) &&
11064824e7fdSDimitry Andric          "Size mismatch!");
11070b57cec5SDimitry Andric 
11085ffd83dbSDimitry Andric   if (MMO->getBaseAlign() >= getBaseAlign()) {
11090b57cec5SDimitry Andric     // Update the alignment value.
11105ffd83dbSDimitry Andric     BaseAlign = MMO->getBaseAlign();
11110b57cec5SDimitry Andric     // Also update the base and offset, because the new alignment may
11120b57cec5SDimitry Andric     // not be applicable with the old ones.
11130b57cec5SDimitry Andric     PtrInfo = MMO->PtrInfo;
11140b57cec5SDimitry Andric   }
11150b57cec5SDimitry Andric }
11160b57cec5SDimitry Andric 
11175ffd83dbSDimitry Andric /// getAlign - Return the minimum known alignment in bytes of the
11185ffd83dbSDimitry Andric /// actual memory reference.
11195ffd83dbSDimitry Andric Align MachineMemOperand::getAlign() const {
11205ffd83dbSDimitry Andric   return commonAlignment(getBaseAlign(), getOffset());
11210b57cec5SDimitry Andric }
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
11240b57cec5SDimitry Andric                               SmallVectorImpl<StringRef> &SSNs,
11250b57cec5SDimitry Andric                               const LLVMContext &Context,
11260b57cec5SDimitry Andric                               const MachineFrameInfo *MFI,
11270b57cec5SDimitry Andric                               const TargetInstrInfo *TII) const {
11280b57cec5SDimitry Andric   OS << '(';
11290b57cec5SDimitry Andric   if (isVolatile())
11300b57cec5SDimitry Andric     OS << "volatile ";
11310b57cec5SDimitry Andric   if (isNonTemporal())
11320b57cec5SDimitry Andric     OS << "non-temporal ";
11330b57cec5SDimitry Andric   if (isDereferenceable())
11340b57cec5SDimitry Andric     OS << "dereferenceable ";
11350b57cec5SDimitry Andric   if (isInvariant())
11360b57cec5SDimitry Andric     OS << "invariant ";
1137bdd1243dSDimitry Andric   if (TII) {
11380b57cec5SDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag1)
11390b57cec5SDimitry Andric       OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag1)
11400b57cec5SDimitry Andric          << "\" ";
11410b57cec5SDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag2)
11420b57cec5SDimitry Andric       OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag2)
11430b57cec5SDimitry Andric          << "\" ";
11440b57cec5SDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag3)
11450b57cec5SDimitry Andric       OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag3)
11460b57cec5SDimitry Andric          << "\" ";
1147bdd1243dSDimitry Andric   } else {
1148bdd1243dSDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag1)
1149bdd1243dSDimitry Andric       OS << "\"MOTargetFlag1\" ";
1150bdd1243dSDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag2)
1151bdd1243dSDimitry Andric       OS << "\"MOTargetFlag2\" ";
1152bdd1243dSDimitry Andric     if (getFlags() & MachineMemOperand::MOTargetFlag3)
1153bdd1243dSDimitry Andric       OS << "\"MOTargetFlag3\" ";
1154bdd1243dSDimitry Andric   }
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric   assert((isLoad() || isStore()) &&
11570b57cec5SDimitry Andric          "machine memory operand must be a load or store (or both)");
11580b57cec5SDimitry Andric   if (isLoad())
11590b57cec5SDimitry Andric     OS << "load ";
11600b57cec5SDimitry Andric   if (isStore())
11610b57cec5SDimitry Andric     OS << "store ";
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric   printSyncScope(OS, Context, getSyncScopeID(), SSNs);
11640b57cec5SDimitry Andric 
1165fe6060f1SDimitry Andric   if (getSuccessOrdering() != AtomicOrdering::NotAtomic)
1166fe6060f1SDimitry Andric     OS << toIRString(getSuccessOrdering()) << ' ';
11670b57cec5SDimitry Andric   if (getFailureOrdering() != AtomicOrdering::NotAtomic)
11680b57cec5SDimitry Andric     OS << toIRString(getFailureOrdering()) << ' ';
11690b57cec5SDimitry Andric 
1170fe6060f1SDimitry Andric   if (getMemoryType().isValid())
1171fe6060f1SDimitry Andric     OS << '(' << getMemoryType() << ')';
11720b57cec5SDimitry Andric   else
1173fe6060f1SDimitry Andric     OS << "unknown-size";
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric   if (const Value *Val = getValue()) {
11760b57cec5SDimitry Andric     OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into ");
1177480093f4SDimitry Andric     MIRFormatter::printIRValue(OS, *Val, MST);
11780b57cec5SDimitry Andric   } else if (const PseudoSourceValue *PVal = getPseudoValue()) {
11790b57cec5SDimitry Andric     OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into ");
11800b57cec5SDimitry Andric     assert(PVal && "Expected a pseudo source value");
11810b57cec5SDimitry Andric     switch (PVal->kind()) {
11820b57cec5SDimitry Andric     case PseudoSourceValue::Stack:
11830b57cec5SDimitry Andric       OS << "stack";
11840b57cec5SDimitry Andric       break;
11850b57cec5SDimitry Andric     case PseudoSourceValue::GOT:
11860b57cec5SDimitry Andric       OS << "got";
11870b57cec5SDimitry Andric       break;
11880b57cec5SDimitry Andric     case PseudoSourceValue::JumpTable:
11890b57cec5SDimitry Andric       OS << "jump-table";
11900b57cec5SDimitry Andric       break;
11910b57cec5SDimitry Andric     case PseudoSourceValue::ConstantPool:
11920b57cec5SDimitry Andric       OS << "constant-pool";
11930b57cec5SDimitry Andric       break;
11940b57cec5SDimitry Andric     case PseudoSourceValue::FixedStack: {
11950b57cec5SDimitry Andric       int FrameIndex = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex();
11960b57cec5SDimitry Andric       bool IsFixed = true;
11970b57cec5SDimitry Andric       printFrameIndex(OS, FrameIndex, IsFixed, MFI);
11980b57cec5SDimitry Andric       break;
11990b57cec5SDimitry Andric     }
12000b57cec5SDimitry Andric     case PseudoSourceValue::GlobalValueCallEntry:
12010b57cec5SDimitry Andric       OS << "call-entry ";
12020b57cec5SDimitry Andric       cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand(
12030b57cec5SDimitry Andric           OS, /*PrintType=*/false, MST);
12040b57cec5SDimitry Andric       break;
12050b57cec5SDimitry Andric     case PseudoSourceValue::ExternalSymbolCallEntry:
12060b57cec5SDimitry Andric       OS << "call-entry &";
12070b57cec5SDimitry Andric       printLLVMNameWithoutPrefix(
12080b57cec5SDimitry Andric           OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol());
12090b57cec5SDimitry Andric       break;
1210480093f4SDimitry Andric     default: {
1211480093f4SDimitry Andric       const MIRFormatter *Formatter = TII->getMIRFormatter();
12120b57cec5SDimitry Andric       // FIXME: This is not necessarily the correct MIR serialization format for
12130b57cec5SDimitry Andric       // a custom pseudo source value, but at least it allows
1214e8d8bef9SDimitry Andric       // MIR printing to work on a target with custom pseudo source
12150b57cec5SDimitry Andric       // values.
1216480093f4SDimitry Andric       OS << "custom \"";
1217480093f4SDimitry Andric       Formatter->printCustomPseudoSourceValue(OS, MST, *PVal);
1218480093f4SDimitry Andric       OS << '\"';
12190b57cec5SDimitry Andric       break;
12200b57cec5SDimitry Andric     }
12210b57cec5SDimitry Andric     }
1222fe6060f1SDimitry Andric   } else if (getOpaqueValue() == nullptr && getOffset() != 0) {
1223fe6060f1SDimitry Andric     OS << ((isLoad() && isStore()) ? " on "
1224fe6060f1SDimitry Andric            : isLoad()              ? " from "
1225fe6060f1SDimitry Andric                                    : " into ")
1226fe6060f1SDimitry Andric        << "unknown-address";
1227480093f4SDimitry Andric   }
12280b57cec5SDimitry Andric   MachineOperand::printOperandOffset(OS, getOffset());
1229fe6060f1SDimitry Andric   if (getSize() > 0 && getAlign() != getSize())
1230e8d8bef9SDimitry Andric     OS << ", align " << getAlign().value();
1231e8d8bef9SDimitry Andric   if (getAlign() != getBaseAlign())
1232e8d8bef9SDimitry Andric     OS << ", basealign " << getBaseAlign().value();
12330b57cec5SDimitry Andric   auto AAInfo = getAAInfo();
12340b57cec5SDimitry Andric   if (AAInfo.TBAA) {
12350b57cec5SDimitry Andric     OS << ", !tbaa ";
12360b57cec5SDimitry Andric     AAInfo.TBAA->printAsOperand(OS, MST);
12370b57cec5SDimitry Andric   }
12380b57cec5SDimitry Andric   if (AAInfo.Scope) {
12390b57cec5SDimitry Andric     OS << ", !alias.scope ";
12400b57cec5SDimitry Andric     AAInfo.Scope->printAsOperand(OS, MST);
12410b57cec5SDimitry Andric   }
12420b57cec5SDimitry Andric   if (AAInfo.NoAlias) {
12430b57cec5SDimitry Andric     OS << ", !noalias ";
12440b57cec5SDimitry Andric     AAInfo.NoAlias->printAsOperand(OS, MST);
12450b57cec5SDimitry Andric   }
12460b57cec5SDimitry Andric   if (getRanges()) {
12470b57cec5SDimitry Andric     OS << ", !range ";
12480b57cec5SDimitry Andric     getRanges()->printAsOperand(OS, MST);
12490b57cec5SDimitry Andric   }
12500b57cec5SDimitry Andric   // FIXME: Implement addrspace printing/parsing in MIR.
12510b57cec5SDimitry Andric   // For now, print this even though parsing it is not available in MIR.
12520b57cec5SDimitry Andric   if (unsigned AS = getAddrSpace())
12530b57cec5SDimitry Andric     OS << ", addrspace " << AS;
12540b57cec5SDimitry Andric 
12550b57cec5SDimitry Andric   OS << ')';
12560b57cec5SDimitry Andric }
1257