diff options
Diffstat (limited to 'llvm/lib/CodeGen/MachineOperand.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/MachineOperand.cpp | 1183 | 
1 files changed, 1183 insertions, 0 deletions
| diff --git a/llvm/lib/CodeGen/MachineOperand.cpp b/llvm/lib/CodeGen/MachineOperand.cpp new file mode 100644 index 000000000000..8b19501ec3cf --- /dev/null +++ b/llvm/lib/CodeGen/MachineOperand.cpp @@ -0,0 +1,1183 @@ +//===- lib/CodeGen/MachineOperand.cpp -------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +/// \file Methods common to all machine operands. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/CodeGen/MIRPrinter.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/Config/llvm-config.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/ModuleSlotTracker.h" +#include "llvm/MC/MCDwarf.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/Target/TargetMachine.h" + +using namespace llvm; + +static cl::opt<int> +    PrintRegMaskNumRegs("print-regmask-num-regs", +                        cl::desc("Number of registers to limit to when " +                                 "printing regmask operands in IR dumps. " +                                 "unlimited = -1"), +                        cl::init(32), cl::Hidden); + +static const MachineFunction *getMFIfAvailable(const MachineOperand &MO) { +  if (const MachineInstr *MI = MO.getParent()) +    if (const MachineBasicBlock *MBB = MI->getParent()) +      if (const MachineFunction *MF = MBB->getParent()) +        return MF; +  return nullptr; +} +static MachineFunction *getMFIfAvailable(MachineOperand &MO) { +  return const_cast<MachineFunction *>( +      getMFIfAvailable(const_cast<const MachineOperand &>(MO))); +} + +void MachineOperand::setReg(Register Reg) { +  if (getReg() == Reg) +    return; // No change. + +  // Clear the IsRenamable bit to keep it conservatively correct. +  IsRenamable = false; + +  // Otherwise, we have to change the register.  If this operand is embedded +  // into a machine function, we need to update the old and new register's +  // use/def lists. +  if (MachineFunction *MF = getMFIfAvailable(*this)) { +    MachineRegisterInfo &MRI = MF->getRegInfo(); +    MRI.removeRegOperandFromUseList(this); +    SmallContents.RegNo = Reg; +    MRI.addRegOperandToUseList(this); +    return; +  } + +  // Otherwise, just change the register, no problem.  :) +  SmallContents.RegNo = Reg; +} + +void MachineOperand::substVirtReg(Register Reg, unsigned SubIdx, +                                  const TargetRegisterInfo &TRI) { +  assert(Reg.isVirtual()); +  if (SubIdx && getSubReg()) +    SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); +  setReg(Reg); +  if (SubIdx) +    setSubReg(SubIdx); +} + +void MachineOperand::substPhysReg(MCRegister Reg, const TargetRegisterInfo &TRI) { +  assert(Reg.isPhysical()); +  if (getSubReg()) { +    Reg = TRI.getSubReg(Reg, getSubReg()); +    // Note that getSubReg() may return 0 if the sub-register doesn't exist. +    // That won't happen in legal code. +    setSubReg(0); +    if (isDef()) +      setIsUndef(false); +  } +  setReg(Reg); +} + +/// Change a def to a use, or a use to a def. +void MachineOperand::setIsDef(bool Val) { +  assert(isReg() && "Wrong MachineOperand accessor"); +  assert((!Val || !isDebug()) && "Marking a debug operation as def"); +  if (IsDef == Val) +    return; +  assert(!IsDeadOrKill && "Changing def/use with dead/kill set not supported"); +  // MRI may keep uses and defs in different list positions. +  if (MachineFunction *MF = getMFIfAvailable(*this)) { +    MachineRegisterInfo &MRI = MF->getRegInfo(); +    MRI.removeRegOperandFromUseList(this); +    IsDef = Val; +    MRI.addRegOperandToUseList(this); +    return; +  } +  IsDef = Val; +} + +bool MachineOperand::isRenamable() const { +  assert(isReg() && "Wrong MachineOperand accessor"); +  assert(Register::isPhysicalRegister(getReg()) && +         "isRenamable should only be checked on physical registers"); +  if (!IsRenamable) +    return false; + +  const MachineInstr *MI = getParent(); +  if (!MI) +    return true; + +  if (isDef()) +    return !MI->hasExtraDefRegAllocReq(MachineInstr::IgnoreBundle); + +  assert(isUse() && "Reg is not def or use"); +  return !MI->hasExtraSrcRegAllocReq(MachineInstr::IgnoreBundle); +} + +void MachineOperand::setIsRenamable(bool Val) { +  assert(isReg() && "Wrong MachineOperand accessor"); +  assert(Register::isPhysicalRegister(getReg()) && +         "setIsRenamable should only be called on physical registers"); +  IsRenamable = Val; +} + +// If this operand is currently a register operand, and if this is in a +// function, deregister the operand from the register's use/def list. +void MachineOperand::removeRegFromUses() { +  if (!isReg() || !isOnRegUseList()) +    return; + +  if (MachineFunction *MF = getMFIfAvailable(*this)) +    MF->getRegInfo().removeRegOperandFromUseList(this); +} + +/// ChangeToImmediate - Replace this operand with a new immediate operand of +/// the specified value.  If an operand is known to be an immediate already, +/// the setImm method should be used. +void MachineOperand::ChangeToImmediate(int64_t ImmVal) { +  assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); + +  removeRegFromUses(); + +  OpKind = MO_Immediate; +  Contents.ImmVal = ImmVal; +} + +void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm) { +  assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); + +  removeRegFromUses(); + +  OpKind = MO_FPImmediate; +  Contents.CFP = FPImm; +} + +void MachineOperand::ChangeToES(const char *SymName, +                                unsigned TargetFlags) { +  assert((!isReg() || !isTied()) && +         "Cannot change a tied operand into an external symbol"); + +  removeRegFromUses(); + +  OpKind = MO_ExternalSymbol; +  Contents.OffsetedInfo.Val.SymbolName = SymName; +  setOffset(0); // Offset is always 0. +  setTargetFlags(TargetFlags); +} + +void MachineOperand::ChangeToGA(const GlobalValue *GV, int64_t Offset, +                                unsigned TargetFlags) { +  assert((!isReg() || !isTied()) && +         "Cannot change a tied operand into a global address"); + +  removeRegFromUses(); + +  OpKind = MO_GlobalAddress; +  Contents.OffsetedInfo.Val.GV = GV; +  setOffset(Offset); +  setTargetFlags(TargetFlags); +} + +void MachineOperand::ChangeToMCSymbol(MCSymbol *Sym) { +  assert((!isReg() || !isTied()) && +         "Cannot change a tied operand into an MCSymbol"); + +  removeRegFromUses(); + +  OpKind = MO_MCSymbol; +  Contents.Sym = Sym; +} + +void MachineOperand::ChangeToFrameIndex(int Idx) { +  assert((!isReg() || !isTied()) && +         "Cannot change a tied operand into a FrameIndex"); + +  removeRegFromUses(); + +  OpKind = MO_FrameIndex; +  setIndex(Idx); +} + +void MachineOperand::ChangeToTargetIndex(unsigned Idx, int64_t Offset, +                                         unsigned TargetFlags) { +  assert((!isReg() || !isTied()) && +         "Cannot change a tied operand into a FrameIndex"); + +  removeRegFromUses(); + +  OpKind = MO_TargetIndex; +  setIndex(Idx); +  setOffset(Offset); +  setTargetFlags(TargetFlags); +} + +/// ChangeToRegister - Replace this operand with a new register operand of +/// the specified value.  If an operand is known to be an register already, +/// the setReg method should be used. +void MachineOperand::ChangeToRegister(Register Reg, bool isDef, bool isImp, +                                      bool isKill, bool isDead, bool isUndef, +                                      bool isDebug) { +  MachineRegisterInfo *RegInfo = nullptr; +  if (MachineFunction *MF = getMFIfAvailable(*this)) +    RegInfo = &MF->getRegInfo(); +  // If this operand is already a register operand, remove it from the +  // register's use/def lists. +  bool WasReg = isReg(); +  if (RegInfo && WasReg) +    RegInfo->removeRegOperandFromUseList(this); + +  // Change this to a register and set the reg#. +  assert(!(isDead && !isDef) && "Dead flag on non-def"); +  assert(!(isKill && isDef) && "Kill flag on def"); +  OpKind = MO_Register; +  SmallContents.RegNo = Reg; +  SubReg_TargetFlags = 0; +  IsDef = isDef; +  IsImp = isImp; +  IsDeadOrKill = isKill | isDead; +  IsRenamable = false; +  IsUndef = isUndef; +  IsInternalRead = false; +  IsEarlyClobber = false; +  IsDebug = isDebug; +  // Ensure isOnRegUseList() returns false. +  Contents.Reg.Prev = nullptr; +  // Preserve the tie when the operand was already a register. +  if (!WasReg) +    TiedTo = 0; + +  // If this operand is embedded in a function, add the operand to the +  // register's use/def list. +  if (RegInfo) +    RegInfo->addRegOperandToUseList(this); +} + +/// 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(); +  case MachineOperand::MO_ShuffleMask: +    return getShuffleMask() == Other.getShuffleMask(); +  } +  llvm_unreachable("Invalid machine operand type"); +} + +// 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(), (unsigned)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(), +                        StringRef(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()); +  case MachineOperand::MO_ShuffleMask: +    return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getShuffleMask()); +  } +  llvm_unreachable("Invalid machine operand type"); +} + +// Try to crawl up to the machine function and get TRI and IntrinsicInfo from +// it. +static void tryToGetTargetInfo(const MachineOperand &MO, +                               const TargetRegisterInfo *&TRI, +                               const TargetIntrinsicInfo *&IntrinsicInfo) { +  if (const MachineFunction *MF = getMFIfAvailable(MO)) { +    TRI = MF->getSubtarget().getRegisterInfo(); +    IntrinsicInfo = MF->getTarget().getIntrinsicInfo(); +  } +} + +static const char *getTargetIndexName(const MachineFunction &MF, int Index) { +  const auto *TII = MF.getSubtarget().getInstrInfo(); +  assert(TII && "expected instruction info"); +  auto Indices = TII->getSerializableTargetIndices(); +  auto Found = find_if(Indices, [&](const std::pair<int, const char *> &I) { +    return I.first == Index; +  }); +  if (Found != Indices.end()) +    return Found->second; +  return nullptr; +} + +static const char *getTargetFlagName(const TargetInstrInfo *TII, unsigned TF) { +  auto Flags = TII->getSerializableDirectMachineOperandTargetFlags(); +  for (const auto &I : Flags) { +    if (I.first == TF) { +      return I.second; +    } +  } +  return nullptr; +} + +static void printCFIRegister(unsigned DwarfReg, raw_ostream &OS, +                             const TargetRegisterInfo *TRI) { +  if (!TRI) { +    OS << "%dwarfreg." << DwarfReg; +    return; +  } + +  if (Optional<unsigned> Reg = TRI->getLLVMRegNum(DwarfReg, true)) +    OS << printReg(*Reg, TRI); +  else +    OS << "<badreg>"; +} + +static void printIRBlockReference(raw_ostream &OS, const BasicBlock &BB, +                                  ModuleSlotTracker &MST) { +  OS << "%ir-block."; +  if (BB.hasName()) { +    printLLVMNameWithoutPrefix(OS, BB.getName()); +    return; +  } +  Optional<int> Slot; +  if (const Function *F = BB.getParent()) { +    if (F == MST.getCurrentFunction()) { +      Slot = MST.getLocalSlot(&BB); +    } else if (const Module *M = F->getParent()) { +      ModuleSlotTracker CustomMST(M, /*ShouldInitializeAllMetadata=*/false); +      CustomMST.incorporateFunction(*F); +      Slot = CustomMST.getLocalSlot(&BB); +    } +  } +  if (Slot) +    MachineOperand::printIRSlotNumber(OS, *Slot); +  else +    OS << "<unknown>"; +} + +static void printIRValueReference(raw_ostream &OS, const Value &V, +                                  ModuleSlotTracker &MST) { +  if (isa<GlobalValue>(V)) { +    V.printAsOperand(OS, /*PrintType=*/false, MST); +    return; +  } +  if (isa<Constant>(V)) { +    // Machine memory operands can load/store to/from constant value pointers. +    OS << '`'; +    V.printAsOperand(OS, /*PrintType=*/true, MST); +    OS << '`'; +    return; +  } +  OS << "%ir."; +  if (V.hasName()) { +    printLLVMNameWithoutPrefix(OS, V.getName()); +    return; +  } +  int Slot = MST.getCurrentFunction() ? MST.getLocalSlot(&V) : -1; +  MachineOperand::printIRSlotNumber(OS, Slot); +} + +static void printSyncScope(raw_ostream &OS, const LLVMContext &Context, +                           SyncScope::ID SSID, +                           SmallVectorImpl<StringRef> &SSNs) { +  switch (SSID) { +  case SyncScope::System: +    break; +  default: +    if (SSNs.empty()) +      Context.getSyncScopeNames(SSNs); + +    OS << "syncscope(\""; +    printEscapedString(SSNs[SSID], OS); +    OS << "\") "; +    break; +  } +} + +static const char *getTargetMMOFlagName(const TargetInstrInfo &TII, +                                        unsigned TMMOFlag) { +  auto Flags = TII.getSerializableMachineMemOperandTargetFlags(); +  for (const auto &I : Flags) { +    if (I.first == TMMOFlag) { +      return I.second; +    } +  } +  return nullptr; +} + +static void printFrameIndex(raw_ostream& OS, int FrameIndex, bool IsFixed, +                            const MachineFrameInfo *MFI) { +  StringRef Name; +  if (MFI) { +    IsFixed = MFI->isFixedObjectIndex(FrameIndex); +    if (const AllocaInst *Alloca = MFI->getObjectAllocation(FrameIndex)) +      if (Alloca->hasName()) +        Name = Alloca->getName(); +    if (IsFixed) +      FrameIndex -= MFI->getObjectIndexBegin(); +  } +  MachineOperand::printStackObjectReference(OS, FrameIndex, IsFixed, Name); +} + +void MachineOperand::printSubRegIdx(raw_ostream &OS, uint64_t Index, +                                    const TargetRegisterInfo *TRI) { +  OS << "%subreg."; +  if (TRI) +    OS << TRI->getSubRegIndexName(Index); +  else +    OS << Index; +} + +void MachineOperand::printTargetFlags(raw_ostream &OS, +                                      const MachineOperand &Op) { +  if (!Op.getTargetFlags()) +    return; +  const MachineFunction *MF = getMFIfAvailable(Op); +  if (!MF) +    return; + +  const auto *TII = MF->getSubtarget().getInstrInfo(); +  assert(TII && "expected instruction info"); +  auto Flags = TII->decomposeMachineOperandsTargetFlags(Op.getTargetFlags()); +  OS << "target-flags("; +  const bool HasDirectFlags = Flags.first; +  const bool HasBitmaskFlags = Flags.second; +  if (!HasDirectFlags && !HasBitmaskFlags) { +    OS << "<unknown>) "; +    return; +  } +  if (HasDirectFlags) { +    if (const auto *Name = getTargetFlagName(TII, Flags.first)) +      OS << Name; +    else +      OS << "<unknown target flag>"; +  } +  if (!HasBitmaskFlags) { +    OS << ") "; +    return; +  } +  bool IsCommaNeeded = HasDirectFlags; +  unsigned BitMask = Flags.second; +  auto BitMasks = TII->getSerializableBitmaskMachineOperandTargetFlags(); +  for (const auto &Mask : BitMasks) { +    // Check if the flag's bitmask has the bits of the current mask set. +    if ((BitMask & Mask.first) == Mask.first) { +      if (IsCommaNeeded) +        OS << ", "; +      IsCommaNeeded = true; +      OS << Mask.second; +      // Clear the bits which were serialized from the flag's bitmask. +      BitMask &= ~(Mask.first); +    } +  } +  if (BitMask) { +    // When the resulting flag's bitmask isn't zero, we know that we didn't +    // serialize all of the bit flags. +    if (IsCommaNeeded) +      OS << ", "; +    OS << "<unknown bitmask target flag>"; +  } +  OS << ") "; +} + +void MachineOperand::printSymbol(raw_ostream &OS, MCSymbol &Sym) { +  OS << "<mcsymbol " << Sym << ">"; +} + +void MachineOperand::printStackObjectReference(raw_ostream &OS, +                                               unsigned FrameIndex, +                                               bool IsFixed, StringRef Name) { +  if (IsFixed) { +    OS << "%fixed-stack." << FrameIndex; +    return; +  } + +  OS << "%stack." << FrameIndex; +  if (!Name.empty()) +    OS << '.' << Name; +} + +void MachineOperand::printOperandOffset(raw_ostream &OS, int64_t Offset) { +  if (Offset == 0) +    return; +  if (Offset < 0) { +    OS << " - " << -Offset; +    return; +  } +  OS << " + " << Offset; +} + +void MachineOperand::printIRSlotNumber(raw_ostream &OS, int Slot) { +  if (Slot == -1) +    OS << "<badref>"; +  else +    OS << Slot; +} + +static void printCFI(raw_ostream &OS, const MCCFIInstruction &CFI, +                     const TargetRegisterInfo *TRI) { +  switch (CFI.getOperation()) { +  case MCCFIInstruction::OpSameValue: +    OS << "same_value "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    break; +  case MCCFIInstruction::OpRememberState: +    OS << "remember_state "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    break; +  case MCCFIInstruction::OpRestoreState: +    OS << "restore_state "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    break; +  case MCCFIInstruction::OpOffset: +    OS << "offset "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    OS << ", " << CFI.getOffset(); +    break; +  case MCCFIInstruction::OpDefCfaRegister: +    OS << "def_cfa_register "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    break; +  case MCCFIInstruction::OpDefCfaOffset: +    OS << "def_cfa_offset "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    OS << CFI.getOffset(); +    break; +  case MCCFIInstruction::OpDefCfa: +    OS << "def_cfa "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    OS << ", " << CFI.getOffset(); +    break; +  case MCCFIInstruction::OpRelOffset: +    OS << "rel_offset "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    OS << ", " << CFI.getOffset(); +    break; +  case MCCFIInstruction::OpAdjustCfaOffset: +    OS << "adjust_cfa_offset "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    OS << CFI.getOffset(); +    break; +  case MCCFIInstruction::OpRestore: +    OS << "restore "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    break; +  case MCCFIInstruction::OpEscape: { +    OS << "escape "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    if (!CFI.getValues().empty()) { +      size_t e = CFI.getValues().size() - 1; +      for (size_t i = 0; i < e; ++i) +        OS << format("0x%02x", uint8_t(CFI.getValues()[i])) << ", "; +      OS << format("0x%02x", uint8_t(CFI.getValues()[e])) << ", "; +    } +    break; +  } +  case MCCFIInstruction::OpUndefined: +    OS << "undefined "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    break; +  case MCCFIInstruction::OpRegister: +    OS << "register "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    printCFIRegister(CFI.getRegister(), OS, TRI); +    OS << ", "; +    printCFIRegister(CFI.getRegister2(), OS, TRI); +    break; +  case MCCFIInstruction::OpWindowSave: +    OS << "window_save "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    break; +  case MCCFIInstruction::OpNegateRAState: +    OS << "negate_ra_sign_state "; +    if (MCSymbol *Label = CFI.getLabel()) +      MachineOperand::printSymbol(OS, *Label); +    break; +  default: +    // TODO: Print the other CFI Operations. +    OS << "<unserializable cfi directive>"; +    break; +  } +} + +void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, +                           const TargetIntrinsicInfo *IntrinsicInfo) const { +  print(OS, LLT{}, TRI, IntrinsicInfo); +} + +void MachineOperand::print(raw_ostream &OS, LLT TypeToPrint, +                           const TargetRegisterInfo *TRI, +                           const TargetIntrinsicInfo *IntrinsicInfo) const { +  tryToGetTargetInfo(*this, TRI, IntrinsicInfo); +  ModuleSlotTracker DummyMST(nullptr); +  print(OS, DummyMST, TypeToPrint, /*PrintDef=*/false, /*IsStandalone=*/true, +        /*ShouldPrintRegisterTies=*/true, +        /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); +} + +void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, +                           LLT TypeToPrint, bool PrintDef, bool IsStandalone, +                           bool ShouldPrintRegisterTies, +                           unsigned TiedOperandIdx, +                           const TargetRegisterInfo *TRI, +                           const TargetIntrinsicInfo *IntrinsicInfo) const { +  printTargetFlags(OS, *this); +  switch (getType()) { +  case MachineOperand::MO_Register: { +    Register Reg = getReg(); +    if (isImplicit()) +      OS << (isDef() ? "implicit-def " : "implicit "); +    else if (PrintDef && isDef()) +      // Print the 'def' flag only when the operand is defined after '='. +      OS << "def "; +    if (isInternalRead()) +      OS << "internal "; +    if (isDead()) +      OS << "dead "; +    if (isKill()) +      OS << "killed "; +    if (isUndef()) +      OS << "undef "; +    if (isEarlyClobber()) +      OS << "early-clobber "; +    if (Register::isPhysicalRegister(getReg()) && isRenamable()) +      OS << "renamable "; +    // isDebug() is exactly true for register operands of a DBG_VALUE. So we +    // simply infer it when parsing and do not need to print it. + +    const MachineRegisterInfo *MRI = nullptr; +    if (Register::isVirtualRegister(Reg)) { +      if (const MachineFunction *MF = getMFIfAvailable(*this)) { +        MRI = &MF->getRegInfo(); +      } +    } + +    OS << printReg(Reg, TRI, 0, MRI); +    // Print the sub register. +    if (unsigned SubReg = getSubReg()) { +      if (TRI) +        OS << '.' << TRI->getSubRegIndexName(SubReg); +      else +        OS << ".subreg" << SubReg; +    } +    // Print the register class / bank. +    if (Register::isVirtualRegister(Reg)) { +      if (const MachineFunction *MF = getMFIfAvailable(*this)) { +        const MachineRegisterInfo &MRI = MF->getRegInfo(); +        if (IsStandalone || !PrintDef || MRI.def_empty(Reg)) { +          OS << ':'; +          OS << printRegClassOrBank(Reg, MRI, TRI); +        } +      } +    } +    // Print ties. +    if (ShouldPrintRegisterTies && isTied() && !isDef()) +      OS << "(tied-def " << TiedOperandIdx << ")"; +    // Print types. +    if (TypeToPrint.isValid()) +      OS << '(' << TypeToPrint << ')'; +    break; +  } +  case MachineOperand::MO_Immediate: +    OS << getImm(); +    break; +  case MachineOperand::MO_CImmediate: +    getCImm()->printAsOperand(OS, /*PrintType=*/true, MST); +    break; +  case MachineOperand::MO_FPImmediate: +    getFPImm()->printAsOperand(OS, /*PrintType=*/true, MST); +    break; +  case MachineOperand::MO_MachineBasicBlock: +    OS << printMBBReference(*getMBB()); +    break; +  case MachineOperand::MO_FrameIndex: { +    int FrameIndex = getIndex(); +    bool IsFixed = false; +    const MachineFrameInfo *MFI = nullptr; +    if (const MachineFunction *MF = getMFIfAvailable(*this)) +      MFI = &MF->getFrameInfo(); +    printFrameIndex(OS, FrameIndex, IsFixed, MFI); +    break; +  } +  case MachineOperand::MO_ConstantPoolIndex: +    OS << "%const." << getIndex(); +    printOperandOffset(OS, getOffset()); +    break; +  case MachineOperand::MO_TargetIndex: { +    OS << "target-index("; +    const char *Name = "<unknown>"; +    if (const MachineFunction *MF = getMFIfAvailable(*this)) +      if (const auto *TargetIndexName = getTargetIndexName(*MF, getIndex())) +        Name = TargetIndexName; +    OS << Name << ')'; +    printOperandOffset(OS, getOffset()); +    break; +  } +  case MachineOperand::MO_JumpTableIndex: +    OS << printJumpTableEntryReference(getIndex()); +    break; +  case MachineOperand::MO_GlobalAddress: +    getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); +    printOperandOffset(OS, getOffset()); +    break; +  case MachineOperand::MO_ExternalSymbol: { +    StringRef Name = getSymbolName(); +    OS << '&'; +    if (Name.empty()) { +      OS << "\"\""; +    } else { +      printLLVMNameWithoutPrefix(OS, Name); +    } +    printOperandOffset(OS, getOffset()); +    break; +  } +  case MachineOperand::MO_BlockAddress: { +    OS << "blockaddress("; +    getBlockAddress()->getFunction()->printAsOperand(OS, /*PrintType=*/false, +                                                     MST); +    OS << ", "; +    printIRBlockReference(OS, *getBlockAddress()->getBasicBlock(), MST); +    OS << ')'; +    MachineOperand::printOperandOffset(OS, getOffset()); +    break; +  } +  case MachineOperand::MO_RegisterMask: { +    OS << "<regmask"; +    if (TRI) { +      unsigned NumRegsInMask = 0; +      unsigned NumRegsEmitted = 0; +      for (unsigned i = 0; i < TRI->getNumRegs(); ++i) { +        unsigned MaskWord = i / 32; +        unsigned MaskBit = i % 32; +        if (getRegMask()[MaskWord] & (1 << MaskBit)) { +          if (PrintRegMaskNumRegs < 0 || +              NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) { +            OS << " " << printReg(i, TRI); +            NumRegsEmitted++; +          } +          NumRegsInMask++; +        } +      } +      if (NumRegsEmitted != NumRegsInMask) +        OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; +    } else { +      OS << " ..."; +    } +    OS << ">"; +    break; +  } +  case MachineOperand::MO_RegisterLiveOut: { +    const uint32_t *RegMask = getRegLiveOut(); +    OS << "liveout("; +    if (!TRI) { +      OS << "<unknown>"; +    } else { +      bool IsCommaNeeded = false; +      for (unsigned Reg = 0, E = TRI->getNumRegs(); Reg < E; ++Reg) { +        if (RegMask[Reg / 32] & (1U << (Reg % 32))) { +          if (IsCommaNeeded) +            OS << ", "; +          OS << printReg(Reg, TRI); +          IsCommaNeeded = true; +        } +      } +    } +    OS << ")"; +    break; +  } +  case MachineOperand::MO_Metadata: +    getMetadata()->printAsOperand(OS, MST); +    break; +  case MachineOperand::MO_MCSymbol: +    printSymbol(OS, *getMCSymbol()); +    break; +  case MachineOperand::MO_CFIIndex: { +    if (const MachineFunction *MF = getMFIfAvailable(*this)) +      printCFI(OS, MF->getFrameInstructions()[getCFIIndex()], TRI); +    else +      OS << "<cfi directive>"; +    break; +  } +  case MachineOperand::MO_IntrinsicID: { +    Intrinsic::ID ID = getIntrinsicID(); +    if (ID < Intrinsic::num_intrinsics) +      OS << "intrinsic(@" << Intrinsic::getName(ID, None) << ')'; +    else if (IntrinsicInfo) +      OS << "intrinsic(@" << IntrinsicInfo->getName(ID) << ')'; +    else +      OS << "intrinsic(" << ID << ')'; +    break; +  } +  case MachineOperand::MO_Predicate: { +    auto Pred = static_cast<CmpInst::Predicate>(getPredicate()); +    OS << (CmpInst::isIntPredicate(Pred) ? "int" : "float") << "pred(" +       << CmpInst::getPredicateName(Pred) << ')'; +    break; +  } +  case MachineOperand::MO_ShuffleMask: +    OS << "shufflemask("; +    const Constant* C = getShuffleMask(); +    const int NumElts = C->getType()->getVectorNumElements(); + +    StringRef Separator; +    for (int I = 0; I != NumElts; ++I) { +      OS << Separator; +      C->getAggregateElement(I)->printAsOperand(OS, false, MST); +      Separator = ", "; +    } + +    OS << ')'; +    break; +  } +} + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +LLVM_DUMP_METHOD void MachineOperand::dump() const { dbgs() << *this << '\n'; } +#endif + +//===----------------------------------------------------------------------===// +// MachineMemOperand Implementation +//===----------------------------------------------------------------------===// + +/// getAddrSpace - Return the LLVM IR address space number that this pointer +/// points into. +unsigned MachinePointerInfo::getAddrSpace() const { return AddrSpace; } + +/// isDereferenceable - Return true if V is always dereferenceable for +/// Offset + Size byte. +bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C, +                                           const DataLayout &DL) const { +  if (!V.is<const Value *>()) +    return false; + +  const Value *BasePtr = V.get<const Value *>(); +  if (BasePtr == nullptr) +    return false; + +  return isDereferenceableAndAlignedPointer( +      BasePtr, Align::None(), APInt(DL.getPointerSizeInBits(), Offset + Size), +      DL); +} + +/// getConstantPool - Return a MachinePointerInfo record that refers to the +/// constant pool. +MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) { +  return MachinePointerInfo(MF.getPSVManager().getConstantPool()); +} + +/// getFixedStack - Return a MachinePointerInfo record that refers to the +/// the specified FrameIndex. +MachinePointerInfo MachinePointerInfo::getFixedStack(MachineFunction &MF, +                                                     int FI, int64_t Offset) { +  return MachinePointerInfo(MF.getPSVManager().getFixedStack(FI), Offset); +} + +MachinePointerInfo MachinePointerInfo::getJumpTable(MachineFunction &MF) { +  return MachinePointerInfo(MF.getPSVManager().getJumpTable()); +} + +MachinePointerInfo MachinePointerInfo::getGOT(MachineFunction &MF) { +  return MachinePointerInfo(MF.getPSVManager().getGOT()); +} + +MachinePointerInfo MachinePointerInfo::getStack(MachineFunction &MF, +                                                int64_t Offset, uint8_t ID) { +  return MachinePointerInfo(MF.getPSVManager().getStack(), Offset, ID); +} + +MachinePointerInfo MachinePointerInfo::getUnknownStack(MachineFunction &MF) { +  return MachinePointerInfo(MF.getDataLayout().getAllocaAddrSpace()); +} + +MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, +                                     uint64_t s, uint64_t a, +                                     const AAMDNodes &AAInfo, +                                     const MDNode *Ranges, SyncScope::ID SSID, +                                     AtomicOrdering Ordering, +                                     AtomicOrdering FailureOrdering) +    : PtrInfo(ptrinfo), Size(s), FlagVals(f), BaseAlignLog2(Log2_32(a) + 1), +      AAInfo(AAInfo), Ranges(Ranges) { +  assert((PtrInfo.V.isNull() || PtrInfo.V.is<const PseudoSourceValue *>() || +          isa<PointerType>(PtrInfo.V.get<const Value *>()->getType())) && +         "invalid pointer value"); +  assert(getBaseAlignment() == a && a != 0 && "Alignment is not a power of 2!"); +  assert((isLoad() || isStore()) && "Not a load/store!"); + +  AtomicInfo.SSID = static_cast<unsigned>(SSID); +  assert(getSyncScopeID() == SSID && "Value truncated"); +  AtomicInfo.Ordering = static_cast<unsigned>(Ordering); +  assert(getOrdering() == Ordering && "Value truncated"); +  AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering); +  assert(getFailureOrdering() == FailureOrdering && "Value truncated"); +} + +/// Profile - Gather unique data for the object. +/// +void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { +  ID.AddInteger(getOffset()); +  ID.AddInteger(Size); +  ID.AddPointer(getOpaqueValue()); +  ID.AddInteger(getFlags()); +  ID.AddInteger(getBaseAlignment()); +} + +void MachineMemOperand::refineAlignment(const MachineMemOperand *MMO) { +  // The Value and Offset may differ due to CSE. But the flags and size +  // should be the same. +  assert(MMO->getFlags() == getFlags() && "Flags mismatch!"); +  assert(MMO->getSize() == getSize() && "Size mismatch!"); + +  if (MMO->getBaseAlignment() >= getBaseAlignment()) { +    // Update the alignment value. +    BaseAlignLog2 = Log2_32(MMO->getBaseAlignment()) + 1; +    // Also update the base and offset, because the new alignment may +    // not be applicable with the old ones. +    PtrInfo = MMO->PtrInfo; +  } +} + +/// getAlignment - Return the minimum known alignment in bytes of the +/// actual memory reference. +uint64_t MachineMemOperand::getAlignment() const { +  return MinAlign(getBaseAlignment(), getOffset()); +} + +void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, +                              SmallVectorImpl<StringRef> &SSNs, +                              const LLVMContext &Context, +                              const MachineFrameInfo *MFI, +                              const TargetInstrInfo *TII) const { +  OS << '('; +  if (isVolatile()) +    OS << "volatile "; +  if (isNonTemporal()) +    OS << "non-temporal "; +  if (isDereferenceable()) +    OS << "dereferenceable "; +  if (isInvariant()) +    OS << "invariant "; +  if (getFlags() & MachineMemOperand::MOTargetFlag1) +    OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag1) +       << "\" "; +  if (getFlags() & MachineMemOperand::MOTargetFlag2) +    OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag2) +       << "\" "; +  if (getFlags() & MachineMemOperand::MOTargetFlag3) +    OS << '"' << getTargetMMOFlagName(*TII, MachineMemOperand::MOTargetFlag3) +       << "\" "; + +  assert((isLoad() || isStore()) && +         "machine memory operand must be a load or store (or both)"); +  if (isLoad()) +    OS << "load "; +  if (isStore()) +    OS << "store "; + +  printSyncScope(OS, Context, getSyncScopeID(), SSNs); + +  if (getOrdering() != AtomicOrdering::NotAtomic) +    OS << toIRString(getOrdering()) << ' '; +  if (getFailureOrdering() != AtomicOrdering::NotAtomic) +    OS << toIRString(getFailureOrdering()) << ' '; + +  if (getSize() == MemoryLocation::UnknownSize) +    OS << "unknown-size"; +  else +    OS << getSize(); + +  if (const Value *Val = getValue()) { +    OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); +    printIRValueReference(OS, *Val, MST); +  } else if (const PseudoSourceValue *PVal = getPseudoValue()) { +    OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); +    assert(PVal && "Expected a pseudo source value"); +    switch (PVal->kind()) { +    case PseudoSourceValue::Stack: +      OS << "stack"; +      break; +    case PseudoSourceValue::GOT: +      OS << "got"; +      break; +    case PseudoSourceValue::JumpTable: +      OS << "jump-table"; +      break; +    case PseudoSourceValue::ConstantPool: +      OS << "constant-pool"; +      break; +    case PseudoSourceValue::FixedStack: { +      int FrameIndex = cast<FixedStackPseudoSourceValue>(PVal)->getFrameIndex(); +      bool IsFixed = true; +      printFrameIndex(OS, FrameIndex, IsFixed, MFI); +      break; +    } +    case PseudoSourceValue::GlobalValueCallEntry: +      OS << "call-entry "; +      cast<GlobalValuePseudoSourceValue>(PVal)->getValue()->printAsOperand( +          OS, /*PrintType=*/false, MST); +      break; +    case PseudoSourceValue::ExternalSymbolCallEntry: +      OS << "call-entry &"; +      printLLVMNameWithoutPrefix( +          OS, cast<ExternalSymbolPseudoSourceValue>(PVal)->getSymbol()); +      break; +    default: +      // FIXME: This is not necessarily the correct MIR serialization format for +      // a custom pseudo source value, but at least it allows +      // -print-machineinstrs to work on a target with custom pseudo source +      // values. +      OS << "custom "; +      PVal->printCustom(OS); +      break; +    } +  } +  MachineOperand::printOperandOffset(OS, getOffset()); +  if (getBaseAlignment() != getSize()) +    OS << ", align " << getBaseAlignment(); +  auto AAInfo = getAAInfo(); +  if (AAInfo.TBAA) { +    OS << ", !tbaa "; +    AAInfo.TBAA->printAsOperand(OS, MST); +  } +  if (AAInfo.Scope) { +    OS << ", !alias.scope "; +    AAInfo.Scope->printAsOperand(OS, MST); +  } +  if (AAInfo.NoAlias) { +    OS << ", !noalias "; +    AAInfo.NoAlias->printAsOperand(OS, MST); +  } +  if (getRanges()) { +    OS << ", !range "; +    getRanges()->printAsOperand(OS, MST); +  } +  // FIXME: Implement addrspace printing/parsing in MIR. +  // For now, print this even though parsing it is not available in MIR. +  if (unsigned AS = getAddrSpace()) +    OS << ", addrspace " << AS; + +  OS << ')'; +} | 
