diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/MachineOperand.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/MachineOperand.cpp | 1217 |
1 files changed, 1217 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/MachineOperand.cpp b/contrib/llvm-project/llvm/lib/CodeGen/MachineOperand.cpp new file mode 100644 index 000000000000..680dbe54ffaf --- /dev/null +++ b/contrib/llvm-project/llvm/lib/CodeGen/MachineOperand.cpp @@ -0,0 +1,1217 @@ +//===- 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/FoldingSet.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Analysis/Loads.h" +#include "llvm/Analysis/MemoryLocation.h" +#include "llvm/CodeGen/MIRFormatter.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/Instructions.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(Register::isPhysicalRegister(Reg)); + 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, unsigned TargetFlags) { + assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); + + removeRegFromUses(); + + OpKind = MO_Immediate; + Contents.ImmVal = ImmVal; + setTargetFlags(TargetFlags); +} + +void MachineOperand::ChangeToFPImmediate(const ConstantFP *FPImm, + unsigned TargetFlags) { + assert((!isReg() || !isTied()) && "Cannot change a tied operand into an imm"); + + removeRegFromUses(); + + OpKind = MO_FPImmediate; + Contents.CFP = FPImm; + setTargetFlags(TargetFlags); +} + +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, unsigned TargetFlags) { + assert((!isReg() || !isTied()) && + "Cannot change a tied operand into an MCSymbol"); + + removeRegFromUses(); + + OpKind = MO_MCSymbol; + Contents.Sym = Sym; + setTargetFlags(TargetFlags); +} + +void MachineOperand::ChangeToFrameIndex(int Idx, unsigned TargetFlags) { + assert((!isReg() || !isTied()) && + "Cannot change a tied operand into a FrameIndex"); + + removeRegFromUses(); + + OpKind = MO_FrameIndex; + setIndex(Idx); + setTargetFlags(TargetFlags); +} + +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); + + // Ensure debug instructions set debug flag on register uses. + const MachineInstr *MI = getParent(); + if (!isDef && MI && MI->isDebugInstr()) + isDebug = true; + + // 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; +} + +const char *MachineOperand::getTargetIndexName() const { + const MachineFunction *MF = getMFIfAvailable(*this); + return MF ? ::getTargetIndexName(*MF, this->getIndex()) : 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 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::OpLLVMDefAspaceCfa: + OS << "llvm_def_aspace_cfa "; + if (MCSymbol *Label = CFI.getLabel()) + MachineOperand::printSymbol(OS, *Label); + printCFIRegister(CFI.getRegister(), OS, TRI); + OS << ", " << CFI.getOffset(); + OS << ", " << CFI.getAddressSpace(); + 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, None, /*PrintDef=*/false, + /*IsStandalone=*/true, + /*ShouldPrintRegisterTies=*/true, + /*TiedOperandIdx=*/0, TRI, IntrinsicInfo); +} + +void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, + LLT TypeToPrint, Optional<unsigned> OpIdx, 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: { + const MIRFormatter *Formatter = nullptr; + if (const MachineFunction *MF = getMFIfAvailable(*this)) { + const auto *TII = MF->getSubtarget().getInstrInfo(); + assert(TII && "expected instruction info"); + Formatter = TII->getMIRFormatter(); + } + if (Formatter) + Formatter->printImm(OS, *getParent(), OpIdx, getImm()); + else + 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::getBaseName(ID) << ')'; + 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("; + ArrayRef<int> Mask = getShuffleMask(); + StringRef Separator; + for (int Elt : Mask) { + if (Elt == -1) + OS << Separator << "undef"; + else + OS << Separator << Elt; + 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(1), 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, + LLT type, Align a, const AAMDNodes &AAInfo, + const MDNode *Ranges, SyncScope::ID SSID, + AtomicOrdering Ordering, + AtomicOrdering FailureOrdering) + : PtrInfo(ptrinfo), MemoryType(type), FlagVals(f), BaseAlign(a), + 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((isLoad() || isStore()) && "Not a load/store!"); + + AtomicInfo.SSID = static_cast<unsigned>(SSID); + assert(getSyncScopeID() == SSID && "Value truncated"); + AtomicInfo.Ordering = static_cast<unsigned>(Ordering); + assert(getSuccessOrdering() == Ordering && "Value truncated"); + AtomicInfo.FailureOrdering = static_cast<unsigned>(FailureOrdering); + assert(getFailureOrdering() == FailureOrdering && "Value truncated"); +} + +MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, + uint64_t s, Align a, + const AAMDNodes &AAInfo, + const MDNode *Ranges, SyncScope::ID SSID, + AtomicOrdering Ordering, + AtomicOrdering FailureOrdering) + : MachineMemOperand(ptrinfo, f, + s == ~UINT64_C(0) ? LLT() : LLT::scalar(8 * s), a, + AAInfo, Ranges, SSID, Ordering, FailureOrdering) {} + +/// Profile - Gather unique data for the object. +/// +void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { + ID.AddInteger(getOffset()); + ID.AddInteger(getMemoryType().getUniqueRAWLLTData()); + ID.AddPointer(getOpaqueValue()); + ID.AddInteger(getFlags()); + ID.AddInteger(getBaseAlign().value()); +} + +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() == ~UINT64_C(0) || getSize() == ~UINT64_C(0) || + MMO->getSize() == getSize()) && + "Size mismatch!"); + + if (MMO->getBaseAlign() >= getBaseAlign()) { + // Update the alignment value. + BaseAlign = MMO->getBaseAlign(); + // Also update the base and offset, because the new alignment may + // not be applicable with the old ones. + PtrInfo = MMO->PtrInfo; + } +} + +/// getAlign - Return the minimum known alignment in bytes of the +/// actual memory reference. +Align MachineMemOperand::getAlign() const { + return commonAlignment(getBaseAlign(), 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 (getSuccessOrdering() != AtomicOrdering::NotAtomic) + OS << toIRString(getSuccessOrdering()) << ' '; + if (getFailureOrdering() != AtomicOrdering::NotAtomic) + OS << toIRString(getFailureOrdering()) << ' '; + + if (getMemoryType().isValid()) + OS << '(' << getMemoryType() << ')'; + else + OS << "unknown-size"; + + if (const Value *Val = getValue()) { + OS << ((isLoad() && isStore()) ? " on " : isLoad() ? " from " : " into "); + MIRFormatter::printIRValue(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: { + const MIRFormatter *Formatter = TII->getMIRFormatter(); + // FIXME: This is not necessarily the correct MIR serialization format for + // a custom pseudo source value, but at least it allows + // MIR printing to work on a target with custom pseudo source + // values. + OS << "custom \""; + Formatter->printCustomPseudoSourceValue(OS, MST, *PVal); + OS << '\"'; + break; + } + } + } else if (getOpaqueValue() == nullptr && getOffset() != 0) { + OS << ((isLoad() && isStore()) ? " on " + : isLoad() ? " from " + : " into ") + << "unknown-address"; + } + MachineOperand::printOperandOffset(OS, getOffset()); + if (getSize() > 0 && getAlign() != getSize()) + OS << ", align " << getAlign().value(); + if (getAlign() != getBaseAlign()) + OS << ", basealign " << getBaseAlign().value(); + 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 << ')'; +} |