Index: llvm/trunk/lib/CodeGen/CMakeLists.txt =================================================================== --- llvm/trunk/lib/CodeGen/CMakeLists.txt +++ llvm/trunk/lib/CodeGen/CMakeLists.txt @@ -76,6 +76,7 @@ MachineLoopInfo.cpp MachineModuleInfo.cpp MachineModuleInfoImpls.cpp + MachineOperand.cpp MachineOptimizationRemarkEmitter.cpp MachineOutliner.cpp MachinePassRegistry.cpp Index: llvm/trunk/lib/CodeGen/MachineInstr.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineInstr.cpp +++ llvm/trunk/lib/CodeGen/MachineInstr.cpp @@ -73,707 +73,6 @@ using namespace llvm; -static cl::opt 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); - -//===----------------------------------------------------------------------===// -// MachineOperand Implementation -//===----------------------------------------------------------------------===// - -void MachineOperand::setReg(unsigned Reg) { - if (getReg() == Reg) return; // No change. - - // 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 (MachineInstr *MI = getParent()) - if (MachineBasicBlock *MBB = MI->getParent()) - if (MachineFunction *MF = MBB->getParent()) { - 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(unsigned Reg, unsigned SubIdx, - const TargetRegisterInfo &TRI) { - assert(TargetRegisterInfo::isVirtualRegister(Reg)); - if (SubIdx && getSubReg()) - SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); - setReg(Reg); - if (SubIdx) - setSubReg(SubIdx); -} - -void MachineOperand::substPhysReg(unsigned Reg, const TargetRegisterInfo &TRI) { - assert(TargetRegisterInfo::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); -} - -void MachineOperand::setIsDef(bool Val) { - assert(isReg() && "Wrong MachineOperand accessor"); - assert((!Val || !isDebug()) && "Marking a debug operation as def"); - if (IsDef == Val) - return; - // MRI may keep uses and defs in different list positions. - if (MachineInstr *MI = getParent()) - if (MachineBasicBlock *MBB = MI->getParent()) - if (MachineFunction *MF = MBB->getParent()) { - MachineRegisterInfo &MRI = MF->getRegInfo(); - MRI.removeRegOperandFromUseList(this); - IsDef = Val; - MRI.addRegOperandToUseList(this); - return; - } - IsDef = Val; -} - -void MachineOperand::removeRegFromUses() { - if (!isReg() || !isOnRegUseList()) - return; - - if (MachineInstr *MI = getParent()) { - if (MachineBasicBlock *MBB = MI->getParent()) { - if (MachineFunction *MF = MBB->getParent()) - MF->getRegInfo().removeRegOperandFromUseList(this); - } - } -} - -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 char 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::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 char TargetFlags) { - assert((!isReg() || !isTied()) && - "Cannot change a tied operand into a FrameIndex"); - - removeRegFromUses(); - - OpKind = MO_TargetIndex; - setIndex(Idx); - setOffset(Offset); - setTargetFlags(TargetFlags); -} - -void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, - bool isKill, bool isDead, bool isUndef, - bool isDebug) { - MachineRegisterInfo *RegInfo = nullptr; - if (MachineInstr *MI = getParent()) - if (MachineBasicBlock *MBB = MI->getParent()) - if (MachineFunction *MF = MBB->getParent()) - 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#. - OpKind = MO_Register; - SmallContents.RegNo = Reg; - SubReg_TargetFlags = 0; - IsDef = isDef; - IsImp = isImp; - IsKill = isKill; - IsDead = isDead; - 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); -} - -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; - - // Calculate the size of the RegMask - const MachineFunction *MF = getParent()->getMF(); - 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); - } - case MachineOperand::MO_MCSymbol: - return getMCSymbol() == Other.getMCSymbol(); - case MachineOperand::MO_CFIIndex: - return getCFIIndex() == Other.getCFIIndex(); - case MachineOperand::MO_Metadata: - return getMetadata() == Other.getMetadata(); - case MachineOperand::MO_IntrinsicID: - return getIntrinsicID() == Other.getIntrinsicID(); - case MachineOperand::MO_Predicate: - return getPredicate() == Other.getPredicate(); - } - llvm_unreachable("Invalid machine operand type"); -} - -// Note: this must stay exactly in sync with isIdenticalTo above. -hash_code llvm::hash_value(const MachineOperand &MO) { - switch (MO.getType()) { - case MachineOperand::MO_Register: - // Register operands don't have target flags. - return hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), MO.isDef()); - case MachineOperand::MO_Immediate: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); - case MachineOperand::MO_CImmediate: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm()); - case MachineOperand::MO_FPImmediate: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm()); - case MachineOperand::MO_MachineBasicBlock: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB()); - case MachineOperand::MO_FrameIndex: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); - case MachineOperand::MO_ConstantPoolIndex: - case MachineOperand::MO_TargetIndex: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(), - MO.getOffset()); - case MachineOperand::MO_JumpTableIndex: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); - case MachineOperand::MO_ExternalSymbol: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), - MO.getSymbolName()); - case MachineOperand::MO_GlobalAddress: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(), - MO.getOffset()); - case MachineOperand::MO_BlockAddress: - return hash_combine(MO.getType(), MO.getTargetFlags(), - MO.getBlockAddress(), MO.getOffset()); - case MachineOperand::MO_RegisterMask: - case MachineOperand::MO_RegisterLiveOut: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); - case MachineOperand::MO_Metadata: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); - case MachineOperand::MO_MCSymbol: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); - case MachineOperand::MO_CFIIndex: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); - case MachineOperand::MO_IntrinsicID: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); - case MachineOperand::MO_Predicate: - return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); - } - llvm_unreachable("Invalid machine operand type"); -} - -void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, - const TargetIntrinsicInfo *IntrinsicInfo) const { - ModuleSlotTracker DummyMST(nullptr); - print(OS, DummyMST, TRI, IntrinsicInfo); -} - -void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, - const TargetRegisterInfo *TRI, - const TargetIntrinsicInfo *IntrinsicInfo) const { - switch (getType()) { - case MachineOperand::MO_Register: - OS << printReg(getReg(), TRI, getSubReg()); - - if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || - isInternalRead() || isEarlyClobber() || isTied()) { - OS << '<'; - bool NeedComma = false; - if (isDef()) { - if (NeedComma) OS << ','; - if (isEarlyClobber()) - OS << "earlyclobber,"; - if (isImplicit()) - OS << "imp-"; - OS << "def"; - NeedComma = true; - // only makes sense when getSubReg() is set. - // Don't clutter the output otherwise. - if (isUndef() && getSubReg()) - OS << ",read-undef"; - } else if (isImplicit()) { - OS << "imp-use"; - NeedComma = true; - } - - if (isKill()) { - if (NeedComma) OS << ','; - OS << "kill"; - NeedComma = true; - } - if (isDead()) { - if (NeedComma) OS << ','; - OS << "dead"; - NeedComma = true; - } - if (isUndef() && isUse()) { - if (NeedComma) OS << ','; - OS << "undef"; - NeedComma = true; - } - if (isInternalRead()) { - if (NeedComma) OS << ','; - OS << "internal"; - NeedComma = true; - } - if (isTied()) { - if (NeedComma) OS << ','; - OS << "tied"; - if (TiedTo != 15) - OS << unsigned(TiedTo - 1); - } - OS << '>'; - } - break; - case MachineOperand::MO_Immediate: - OS << getImm(); - break; - case MachineOperand::MO_CImmediate: - getCImm()->getValue().print(OS, false); - break; - case MachineOperand::MO_FPImmediate: - if (getFPImm()->getType()->isFloatTy()) { - OS << getFPImm()->getValueAPF().convertToFloat(); - } else if (getFPImm()->getType()->isHalfTy()) { - APFloat APF = getFPImm()->getValueAPF(); - bool Unused; - APF.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &Unused); - OS << "half " << APF.convertToFloat(); - } else if (getFPImm()->getType()->isFP128Ty()) { - APFloat APF = getFPImm()->getValueAPF(); - SmallString<16> Str; - getFPImm()->getValueAPF().toString(Str); - OS << "quad " << Str; - } else if (getFPImm()->getType()->isX86_FP80Ty()) { - APFloat APF = getFPImm()->getValueAPF(); - OS << "x86_fp80 0xK"; - APInt API = APF.bitcastToAPInt(); - OS << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4, - /*Upper=*/true); - OS << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, - /*Upper=*/true); - } else { - OS << getFPImm()->getValueAPF().convertToDouble(); - } - break; - case MachineOperand::MO_MachineBasicBlock: - OS << "getNumber() << ">"; - break; - case MachineOperand::MO_FrameIndex: - OS << "'; - break; - case MachineOperand::MO_ConstantPoolIndex: - OS << "'; - break; - case MachineOperand::MO_TargetIndex: - OS << "'; - break; - case MachineOperand::MO_JumpTableIndex: - OS << "'; - break; - case MachineOperand::MO_GlobalAddress: - OS << "printAsOperand(OS, /*PrintType=*/false, MST); - if (getOffset()) OS << "+" << getOffset(); - OS << '>'; - break; - case MachineOperand::MO_ExternalSymbol: - OS << "'; - break; - case MachineOperand::MO_BlockAddress: - OS << '<'; - getBlockAddress()->printAsOperand(OS, /*PrintType=*/false, MST); - if (getOffset()) OS << "+" << getOffset(); - OS << '>'; - break; - case MachineOperand::MO_RegisterMask: { - unsigned NumRegsInMask = 0; - unsigned NumRegsEmitted = 0; - OS << "getNumRegs(); ++i) { - unsigned MaskWord = i / 32; - unsigned MaskBit = i % 32; - if (getRegMask()[MaskWord] & (1 << MaskBit)) { - if (PrintRegMaskNumRegs < 0 || - NumRegsEmitted <= static_cast(PrintRegMaskNumRegs)) { - OS << " " << printReg(i, TRI); - NumRegsEmitted++; - } - NumRegsInMask++; - } - } - if (NumRegsEmitted != NumRegsInMask) - OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; - OS << ">"; - break; - } - case MachineOperand::MO_RegisterLiveOut: - OS << ""; - break; - case MachineOperand::MO_Metadata: - OS << '<'; - getMetadata()->printAsOperand(OS, MST); - OS << '>'; - break; - case MachineOperand::MO_MCSymbol: - OS << "'; - break; - case MachineOperand::MO_CFIIndex: - OS << ""; - break; - case MachineOperand::MO_IntrinsicID: { - Intrinsic::ID ID = getIntrinsicID(); - if (ID < Intrinsic::num_intrinsics) - OS << "'; - else if (IntrinsicInfo) - OS << "getName(ID) << '>'; - else - OS << "'; - break; - } - case MachineOperand::MO_Predicate: { - auto Pred = static_cast(getPredicate()); - OS << '<' << (CmpInst::isIntPredicate(Pred) ? "intpred" : "floatpred") - << CmpInst::getPredicateName(Pred) << '>'; - break; - } - } - if (unsigned TF = getTargetFlags()) - OS << "[TF=" << TF << ']'; -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -LLVM_DUMP_METHOD void MachineOperand::dump() const { - dbgs() << *this << '\n'; -} -#endif - -//===----------------------------------------------------------------------===// -// MachineMemOperand Implementation -//===----------------------------------------------------------------------===// - -unsigned MachinePointerInfo::getAddrSpace() const { - if (V.isNull()) return 0; - - if (V.is()) - return V.get()->getAddressSpace(); - - return cast(V.get()->getType())->getAddressSpace(); -} - -bool MachinePointerInfo::isDereferenceable(unsigned Size, LLVMContext &C, - const DataLayout &DL) const { - if (!V.is()) - return false; - - const Value *BasePtr = V.get(); - if (BasePtr == nullptr) - return false; - - return isDereferenceableAndAlignedPointer( - BasePtr, 1, APInt(DL.getPointerSizeInBits(), Offset + Size), DL); -} - -MachinePointerInfo MachinePointerInfo::getConstantPool(MachineFunction &MF) { - return MachinePointerInfo(MF.getPSVManager().getConstantPool()); -} - -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); -} - -MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, - uint64_t s, unsigned int 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() || - isa(PtrInfo.V.get()->getType())) && - "invalid pointer value"); - assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); - assert((isLoad() || isStore()) && "Not a load/store!"); - - AtomicInfo.SSID = static_cast(SSID); - assert(getSyncScopeID() == SSID && "Value truncated"); - AtomicInfo.Ordering = static_cast(Ordering); - assert(getOrdering() == Ordering && "Value truncated"); - AtomicInfo.FailureOrdering = static_cast(FailureOrdering); - assert(getFailureOrdering() == FailureOrdering && "Value truncated"); -} - -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; - } -} - -uint64_t MachineMemOperand::getAlignment() const { - return MinAlign(getBaseAlignment(), getOffset()); -} - -void MachineMemOperand::print(raw_ostream &OS) const { - ModuleSlotTracker DummyMST(nullptr); - print(OS, DummyMST); -} -void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST) const { - assert((isLoad() || isStore()) && - "SV has to be a load, store or both."); - - if (isVolatile()) - OS << "Volatile "; - - if (isLoad()) - OS << "LD"; - if (isStore()) - OS << "ST"; - OS << getSize(); - - // Print the address information. - OS << "["; - if (const Value *V = getValue()) - V->printAsOperand(OS, /*PrintType=*/false, MST); - else if (const PseudoSourceValue *PSV = getPseudoValue()) - PSV->printCustom(OS); - else - OS << ""; - - unsigned AS = getAddrSpace(); - if (AS != 0) - OS << "(addrspace=" << AS << ')'; - - // If the alignment of the memory reference itself differs from the alignment - // of the base pointer, print the base alignment explicitly, next to the base - // pointer. - if (getBaseAlignment() != getAlignment()) - OS << "(align=" << getBaseAlignment() << ")"; - - if (getOffset() != 0) - OS << "+" << getOffset(); - OS << "]"; - - // Print the alignment of the reference. - if (getBaseAlignment() != getAlignment() || getBaseAlignment() != getSize()) - OS << "(align=" << getAlignment() << ")"; - - // Print TBAA info. - if (const MDNode *TBAAInfo = getAAInfo().TBAA) { - OS << "(tbaa="; - if (TBAAInfo->getNumOperands() > 0) - TBAAInfo->getOperand(0)->printAsOperand(OS, MST); - else - OS << ""; - OS << ")"; - } - - // Print AA scope info. - if (const MDNode *ScopeInfo = getAAInfo().Scope) { - OS << "(alias.scope="; - if (ScopeInfo->getNumOperands() > 0) - for (unsigned i = 0, ie = ScopeInfo->getNumOperands(); i != ie; ++i) { - ScopeInfo->getOperand(i)->printAsOperand(OS, MST); - if (i != ie-1) - OS << ","; - } - else - OS << ""; - OS << ")"; - } - - // Print AA noalias scope info. - if (const MDNode *NoAliasInfo = getAAInfo().NoAlias) { - OS << "(noalias="; - if (NoAliasInfo->getNumOperands() > 0) - for (unsigned i = 0, ie = NoAliasInfo->getNumOperands(); i != ie; ++i) { - NoAliasInfo->getOperand(i)->printAsOperand(OS, MST); - if (i != ie-1) - OS << ","; - } - else - OS << ""; - OS << ")"; - } - - if (const MDNode *Ranges = getRanges()) { - unsigned NumRanges = Ranges->getNumOperands(); - if (NumRanges != 0) { - OS << "(ranges="; - - for (unsigned I = 0; I != NumRanges; ++I) { - Ranges->getOperand(I)->printAsOperand(OS, MST); - if (I != NumRanges - 1) - OS << ','; - } - - OS << ')'; - } - } - - if (isNonTemporal()) - OS << "(nontemporal)"; - if (isDereferenceable()) - OS << "(dereferenceable)"; - if (isInvariant()) - OS << "(invariant)"; - if (getFlags() & MOTargetFlag1) - OS << "(flag1)"; - if (getFlags() & MOTargetFlag2) - OS << "(flag2)"; - if (getFlags() & MOTargetFlag3) - OS << "(flag3)"; -} - -//===----------------------------------------------------------------------===// -// MachineInstr Implementation -//===----------------------------------------------------------------------===// - void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) { if (MCID->ImplicitDefs) for (const MCPhysReg *ImpDefs = MCID->getImplicitDefs(); *ImpDefs; Index: llvm/trunk/lib/CodeGen/MachineOperand.cpp =================================================================== --- llvm/trunk/lib/CodeGen/MachineOperand.cpp +++ llvm/trunk/lib/CodeGen/MachineOperand.cpp @@ -0,0 +1,751 @@ +//===- lib/CodeGen/MachineOperand.cpp -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// /// \file +// Methods common to all machine operands. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/Analysis/Loads.h" +#include "llvm/CodeGen/MIRPrinter.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Target/TargetIntrinsicInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/ModuleSlotTracker.h" + +using namespace llvm; + +static cl::opt + 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); + +void MachineOperand::setReg(unsigned Reg) { + if (getReg() == Reg) + return; // No change. + + // 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 (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) { + 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(unsigned Reg, unsigned SubIdx, + const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::isVirtualRegister(Reg)); + if (SubIdx && getSubReg()) + SubIdx = TRI.composeSubRegIndices(SubIdx, getSubReg()); + setReg(Reg); + if (SubIdx) + setSubReg(SubIdx); +} + +void MachineOperand::substPhysReg(unsigned Reg, const TargetRegisterInfo &TRI) { + assert(TargetRegisterInfo::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; + // MRI may keep uses and defs in different list positions. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) { + MachineRegisterInfo &MRI = MF->getRegInfo(); + MRI.removeRegOperandFromUseList(this); + IsDef = Val; + MRI.addRegOperandToUseList(this); + return; + } + IsDef = 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 (MachineInstr *MI = getParent()) { + if (MachineBasicBlock *MBB = MI->getParent()) { + if (MachineFunction *MF = MBB->getParent()) + 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 char 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::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 char 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(unsigned Reg, bool isDef, bool isImp, + bool isKill, bool isDead, bool isUndef, + bool isDebug) { + MachineRegisterInfo *RegInfo = nullptr; + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) + 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#. + OpKind = MO_Register; + SmallContents.RegNo = Reg; + SubReg_TargetFlags = 0; + IsDef = isDef; + IsImp = isImp; + IsKill = isKill; + IsDead = isDead; + 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; + + // Calculate the size of the RegMask + const MachineFunction *MF = getParent()->getMF(); + 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); + } + case MachineOperand::MO_MCSymbol: + return getMCSymbol() == Other.getMCSymbol(); + case MachineOperand::MO_CFIIndex: + return getCFIIndex() == Other.getCFIIndex(); + case MachineOperand::MO_Metadata: + return getMetadata() == Other.getMetadata(); + case MachineOperand::MO_IntrinsicID: + return getIntrinsicID() == Other.getIntrinsicID(); + case MachineOperand::MO_Predicate: + return getPredicate() == Other.getPredicate(); + } + llvm_unreachable("Invalid machine operand type"); +} + +// Note: this must stay exactly in sync with isIdenticalTo above. +hash_code llvm::hash_value(const MachineOperand &MO) { + switch (MO.getType()) { + case MachineOperand::MO_Register: + // Register operands don't have target flags. + return hash_combine(MO.getType(), MO.getReg(), MO.getSubReg(), MO.isDef()); + case MachineOperand::MO_Immediate: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getImm()); + case MachineOperand::MO_CImmediate: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCImm()); + case MachineOperand::MO_FPImmediate: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getFPImm()); + case MachineOperand::MO_MachineBasicBlock: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMBB()); + case MachineOperand::MO_FrameIndex: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); + case MachineOperand::MO_ConstantPoolIndex: + case MachineOperand::MO_TargetIndex: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex(), + MO.getOffset()); + case MachineOperand::MO_JumpTableIndex: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIndex()); + case MachineOperand::MO_ExternalSymbol: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getOffset(), + MO.getSymbolName()); + case MachineOperand::MO_GlobalAddress: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getGlobal(), + MO.getOffset()); + case MachineOperand::MO_BlockAddress: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getBlockAddress(), + MO.getOffset()); + case MachineOperand::MO_RegisterMask: + case MachineOperand::MO_RegisterLiveOut: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask()); + case MachineOperand::MO_Metadata: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMetadata()); + case MachineOperand::MO_MCSymbol: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol()); + case MachineOperand::MO_CFIIndex: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex()); + case MachineOperand::MO_IntrinsicID: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID()); + case MachineOperand::MO_Predicate: + return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getPredicate()); + } + llvm_unreachable("Invalid machine operand type"); +} + +void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI, + const TargetIntrinsicInfo *IntrinsicInfo) const { + ModuleSlotTracker DummyMST(nullptr); + print(OS, DummyMST, TRI, IntrinsicInfo); +} + +void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST, + const TargetRegisterInfo *TRI, + const TargetIntrinsicInfo *IntrinsicInfo) const { + switch (getType()) { + case MachineOperand::MO_Register: + OS << printReg(getReg(), TRI, getSubReg()); + + if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || + isInternalRead() || isEarlyClobber() || isTied()) { + OS << '<'; + bool NeedComma = false; + if (isDef()) { + if (NeedComma) + OS << ','; + if (isEarlyClobber()) + OS << "earlyclobber,"; + if (isImplicit()) + OS << "imp-"; + OS << "def"; + NeedComma = true; + // only makes sense when getSubReg() is set. + // Don't clutter the output otherwise. + if (isUndef() && getSubReg()) + OS << ",read-undef"; + } else if (isImplicit()) { + OS << "imp-use"; + NeedComma = true; + } + + if (isKill()) { + if (NeedComma) + OS << ','; + OS << "kill"; + NeedComma = true; + } + if (isDead()) { + if (NeedComma) + OS << ','; + OS << "dead"; + NeedComma = true; + } + if (isUndef() && isUse()) { + if (NeedComma) + OS << ','; + OS << "undef"; + NeedComma = true; + } + if (isInternalRead()) { + if (NeedComma) + OS << ','; + OS << "internal"; + NeedComma = true; + } + if (isTied()) { + if (NeedComma) + OS << ','; + OS << "tied"; + if (TiedTo != 15) + OS << unsigned(TiedTo - 1); + } + OS << '>'; + } + break; + case MachineOperand::MO_Immediate: + OS << getImm(); + break; + case MachineOperand::MO_CImmediate: + getCImm()->getValue().print(OS, false); + break; + case MachineOperand::MO_FPImmediate: + if (getFPImm()->getType()->isFloatTy()) { + OS << getFPImm()->getValueAPF().convertToFloat(); + } else if (getFPImm()->getType()->isHalfTy()) { + APFloat APF = getFPImm()->getValueAPF(); + bool Unused; + APF.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &Unused); + OS << "half " << APF.convertToFloat(); + } else if (getFPImm()->getType()->isFP128Ty()) { + APFloat APF = getFPImm()->getValueAPF(); + SmallString<16> Str; + getFPImm()->getValueAPF().toString(Str); + OS << "quad " << Str; + } else if (getFPImm()->getType()->isX86_FP80Ty()) { + APFloat APF = getFPImm()->getValueAPF(); + OS << "x86_fp80 0xK"; + APInt API = APF.bitcastToAPInt(); + OS << format_hex_no_prefix(API.getHiBits(16).getZExtValue(), 4, + /*Upper=*/true); + OS << format_hex_no_prefix(API.getLoBits(64).getZExtValue(), 16, + /*Upper=*/true); + } else { + OS << getFPImm()->getValueAPF().convertToDouble(); + } + break; + case MachineOperand::MO_MachineBasicBlock: + OS << "getNumber() << ">"; + break; + case MachineOperand::MO_FrameIndex: + OS << "'; + break; + case MachineOperand::MO_ConstantPoolIndex: + OS << "'; + break; + case MachineOperand::MO_TargetIndex: + OS << "'; + break; + case MachineOperand::MO_JumpTableIndex: + OS << "'; + break; + case MachineOperand::MO_GlobalAddress: + OS << "printAsOperand(OS, /*PrintType=*/false, MST); + if (getOffset()) + OS << "+" << getOffset(); + OS << '>'; + break; + case MachineOperand::MO_ExternalSymbol: + OS << "'; + break; + case MachineOperand::MO_BlockAddress: + OS << '<'; + getBlockAddress()->printAsOperand(OS, /*PrintType=*/false, MST); + if (getOffset()) + OS << "+" << getOffset(); + OS << '>'; + break; + case MachineOperand::MO_RegisterMask: { + unsigned NumRegsInMask = 0; + unsigned NumRegsEmitted = 0; + OS << "getNumRegs(); ++i) { + unsigned MaskWord = i / 32; + unsigned MaskBit = i % 32; + if (getRegMask()[MaskWord] & (1 << MaskBit)) { + if (PrintRegMaskNumRegs < 0 || + NumRegsEmitted <= static_cast(PrintRegMaskNumRegs)) { + OS << " " << printReg(i, TRI); + NumRegsEmitted++; + } + NumRegsInMask++; + } + } + if (NumRegsEmitted != NumRegsInMask) + OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; + OS << ">"; + break; + } + case MachineOperand::MO_RegisterLiveOut: + OS << ""; + break; + case MachineOperand::MO_Metadata: + OS << '<'; + getMetadata()->printAsOperand(OS, MST); + OS << '>'; + break; + case MachineOperand::MO_MCSymbol: + OS << "'; + break; + case MachineOperand::MO_CFIIndex: + OS << ""; + break; + case MachineOperand::MO_IntrinsicID: { + Intrinsic::ID ID = getIntrinsicID(); + if (ID < Intrinsic::num_intrinsics) + OS << "'; + else if (IntrinsicInfo) + OS << "getName(ID) << '>'; + else + OS << "'; + break; + } + case MachineOperand::MO_Predicate: { + auto Pred = static_cast(getPredicate()); + OS << '<' << (CmpInst::isIntPredicate(Pred) ? "intpred" : "floatpred") + << CmpInst::getPredicateName(Pred) << '>'; + break; + } + } + if (unsigned TF = getTargetFlags()) + OS << "[TF=" << TF << ']'; +} + +#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 { + if (V.isNull()) + return 0; + + if (V.is()) + return V.get()->getAddressSpace(); + + return cast(V.get()->getType()) + ->getAddressSpace(); +} + +/// 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()) + return false; + + const Value *BasePtr = V.get(); + if (BasePtr == nullptr) + return false; + + return isDereferenceableAndAlignedPointer( + BasePtr, 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); +} + +MachineMemOperand::MachineMemOperand(MachinePointerInfo ptrinfo, Flags f, + uint64_t s, unsigned int 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() || + isa(PtrInfo.V.get()->getType())) && + "invalid pointer value"); + assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); + assert((isLoad() || isStore()) && "Not a load/store!"); + + AtomicInfo.SSID = static_cast(SSID); + assert(getSyncScopeID() == SSID && "Value truncated"); + AtomicInfo.Ordering = static_cast(Ordering); + assert(getOrdering() == Ordering && "Value truncated"); + AtomicInfo.FailureOrdering = static_cast(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) const { + ModuleSlotTracker DummyMST(nullptr); + print(OS, DummyMST); +} +void MachineMemOperand::print(raw_ostream &OS, ModuleSlotTracker &MST) const { + assert((isLoad() || isStore()) && "SV has to be a load, store or both."); + + if (isVolatile()) + OS << "Volatile "; + + if (isLoad()) + OS << "LD"; + if (isStore()) + OS << "ST"; + OS << getSize(); + + // Print the address information. + OS << "["; + if (const Value *V = getValue()) + V->printAsOperand(OS, /*PrintType=*/false, MST); + else if (const PseudoSourceValue *PSV = getPseudoValue()) + PSV->printCustom(OS); + else + OS << ""; + + unsigned AS = getAddrSpace(); + if (AS != 0) + OS << "(addrspace=" << AS << ')'; + + // If the alignment of the memory reference itself differs from the alignment + // of the base pointer, print the base alignment explicitly, next to the base + // pointer. + if (getBaseAlignment() != getAlignment()) + OS << "(align=" << getBaseAlignment() << ")"; + + if (getOffset() != 0) + OS << "+" << getOffset(); + OS << "]"; + + // Print the alignment of the reference. + if (getBaseAlignment() != getAlignment() || getBaseAlignment() != getSize()) + OS << "(align=" << getAlignment() << ")"; + + // Print TBAA info. + if (const MDNode *TBAAInfo = getAAInfo().TBAA) { + OS << "(tbaa="; + if (TBAAInfo->getNumOperands() > 0) + TBAAInfo->getOperand(0)->printAsOperand(OS, MST); + else + OS << ""; + OS << ")"; + } + + // Print AA scope info. + if (const MDNode *ScopeInfo = getAAInfo().Scope) { + OS << "(alias.scope="; + if (ScopeInfo->getNumOperands() > 0) + for (unsigned i = 0, ie = ScopeInfo->getNumOperands(); i != ie; ++i) { + ScopeInfo->getOperand(i)->printAsOperand(OS, MST); + if (i != ie - 1) + OS << ","; + } + else + OS << ""; + OS << ")"; + } + + // Print AA noalias scope info. + if (const MDNode *NoAliasInfo = getAAInfo().NoAlias) { + OS << "(noalias="; + if (NoAliasInfo->getNumOperands() > 0) + for (unsigned i = 0, ie = NoAliasInfo->getNumOperands(); i != ie; ++i) { + NoAliasInfo->getOperand(i)->printAsOperand(OS, MST); + if (i != ie - 1) + OS << ","; + } + else + OS << ""; + OS << ")"; + } + + if (const MDNode *Ranges = getRanges()) { + unsigned NumRanges = Ranges->getNumOperands(); + if (NumRanges != 0) { + OS << "(ranges="; + + for (unsigned I = 0; I != NumRanges; ++I) { + Ranges->getOperand(I)->printAsOperand(OS, MST); + if (I != NumRanges - 1) + OS << ','; + } + + OS << ')'; + } + } + + if (isNonTemporal()) + OS << "(nontemporal)"; + if (isDereferenceable()) + OS << "(dereferenceable)"; + if (isInvariant()) + OS << "(invariant)"; + if (getFlags() & MOTargetFlag1) + OS << "(flag1)"; + if (getFlags() & MOTargetFlag2) + OS << "(flag2)"; + if (getFlags() & MOTargetFlag3) + OS << "(flag3)"; +}