diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 |
commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/CodeGen/MachineInstr.cpp | |
parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) |
Notes
Diffstat (limited to 'lib/CodeGen/MachineInstr.cpp')
-rw-r--r-- | lib/CodeGen/MachineInstr.cpp | 930 |
1 files changed, 170 insertions, 760 deletions
diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 535757ed87c1..14655c6eb700 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/Hashing.h" #include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/AliasAnalysis.h" @@ -33,6 +34,9 @@ #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/CodeGen/TargetRegisterInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DebugLoc.h" @@ -58,11 +62,8 @@ #include "llvm/Support/LowLevelTypeImpl.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetRegisterInfo.h" -#include "llvm/Target/TargetSubtargetInfo.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -73,695 +74,6 @@ using namespace llvm; -static cl::opt<bool> PrintWholeRegMask( - "print-whole-regmask", - cl::desc("Print the full contents of regmask operands in IR dumps"), - cl::init(true), 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); -} - -/// 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); -} - -/// 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()->getParent()->getParent(); - 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; - // <def,read-undef> 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 << "<BB#" << getMBB()->getNumber() << ">"; - break; - case MachineOperand::MO_FrameIndex: - OS << "<fi#" << getIndex() << '>'; - break; - case MachineOperand::MO_ConstantPoolIndex: - OS << "<cp#" << getIndex(); - if (getOffset()) OS << "+" << getOffset(); - OS << '>'; - break; - case MachineOperand::MO_TargetIndex: - OS << "<ti#" << getIndex(); - if (getOffset()) OS << "+" << getOffset(); - OS << '>'; - break; - case MachineOperand::MO_JumpTableIndex: - OS << "<jt#" << getIndex() << '>'; - break; - case MachineOperand::MO_GlobalAddress: - OS << "<ga:"; - getGlobal()->printAsOperand(OS, /*PrintType=*/false, MST); - if (getOffset()) OS << "+" << getOffset(); - OS << '>'; - break; - case MachineOperand::MO_ExternalSymbol: - OS << "<es:" << getSymbolName(); - if (getOffset()) OS << "+" << getOffset(); - 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 << "<regmask"; - for (unsigned i = 0; i < TRI->getNumRegs(); ++i) { - unsigned MaskWord = i / 32; - unsigned MaskBit = i % 32; - if (getRegMask()[MaskWord] & (1 << MaskBit)) { - if (PrintWholeRegMask || NumRegsEmitted <= 10) { - OS << " " << PrintReg(i, TRI); - NumRegsEmitted++; - } - NumRegsInMask++; - } - } - if (NumRegsEmitted != NumRegsInMask) - OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more..."; - OS << ">"; - break; - } - case MachineOperand::MO_RegisterLiveOut: - OS << "<regliveout>"; - break; - case MachineOperand::MO_Metadata: - OS << '<'; - getMetadata()->printAsOperand(OS, MST); - OS << '>'; - break; - case MachineOperand::MO_MCSymbol: - OS << "<MCSym=" << *getMCSymbol() << '>'; - break; - case MachineOperand::MO_CFIIndex: - OS << "<call frame instruction>"; - 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) ? "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() || V.is<const PseudoSourceValue*>()) return 0; - return cast<PointerType>(V.get<const Value*>()->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<const Value*>()) - return false; - - const Value *BasePtr = V.get<const Value*>(); - 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) { - return MachinePointerInfo(MF.getPSVManager().getStack(), Offset); -} - -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<const PseudoSourceValue*>() || - isa<PointerType>(PtrInfo.V.get<const Value*>()->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<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) 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 << "<unknown>"; - - 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 << "<unknown>"; - 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 << "<unknown>"; - 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 << "<unknown>"; - 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; @@ -1034,7 +346,7 @@ MachineInstr::mergeMemRefsWith(const MachineInstr& Other) { if (CombinedNumMemRefs != uint8_t(CombinedNumMemRefs)) return std::make_pair(nullptr, 0); - MachineFunction *MF = getParent()->getParent(); + MachineFunction *MF = getMF(); mmo_iterator MemBegin = MF->allocateMemRefsArray(CombinedNumMemRefs); mmo_iterator MemEnd = std::copy(memoperands_begin(), memoperands_end(), MemBegin); @@ -1108,9 +420,9 @@ bool MachineInstr::isIdenticalTo(const MachineInstr &Other, if (Check == IgnoreDefs) continue; else if (Check == IgnoreVRegDefs) { - if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()) || - TargetRegisterInfo::isPhysicalRegister(OMO.getReg())) - if (MO.getReg() != OMO.getReg()) + if (!TargetRegisterInfo::isVirtualRegister(MO.getReg()) || + !TargetRegisterInfo::isVirtualRegister(OMO.getReg())) + if (!MO.isIdenticalTo(OMO)) return false; } else { if (!MO.isIdenticalTo(OMO)) @@ -1133,6 +445,10 @@ bool MachineInstr::isIdenticalTo(const MachineInstr &Other, return true; } +const MachineFunction *MachineInstr::getMF() const { + return getParent()->getParent(); +} + MachineInstr *MachineInstr::removeFromParent() { assert(getParent() && "Not embedded in a basic block!"); return getParent()->remove(this); @@ -1282,8 +598,8 @@ MachineInstr::getRegClassConstraint(unsigned OpIdx, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const { assert(getParent() && "Can't have an MBB reference here!"); - assert(getParent()->getParent() && "Can't have an MF reference here!"); - const MachineFunction &MF = *getParent()->getParent(); + assert(getMF() && "Can't have an MF reference here!"); + const MachineFunction &MF = *getMF(); // Most opcodes have fixed constraints in their MCInstrDesc. if (!isInlineAsm()) @@ -1427,7 +743,7 @@ MachineInstr::readsWritesVirtualRegister(unsigned Reg, if (MO.isUse()) Use |= !MO.isUndef(); else if (MO.getSubReg() && !MO.isUndef()) - // A partial <def,undef> doesn't count as reading the register. + // A partial def undef doesn't count as reading the register. PartDef = true; else FullDef = true; @@ -1619,7 +935,7 @@ bool MachineInstr::isSafeToMove(AliasAnalysis *AA, bool &SawStore) const { // Treat volatile loads as stores. This is not strictly necessary for // volatiles, but it is required for atomic loads. It is not allowed to move // a load across an atomic load with Ordering > Monotonic. - if (mayStore() || isCall() || + if (mayStore() || isCall() || isPHI() || (mayLoad() && hasOrderedMemoryRef())) { SawStore = true; return false; @@ -1644,8 +960,9 @@ bool MachineInstr::isSafeToMove(AliasAnalysis *AA, bool &SawStore) const { bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other, bool UseTBAA) { - const MachineFunction *MF = getParent()->getParent(); + const MachineFunction *MF = getMF(); const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); + const MachineFrameInfo &MFI = MF->getFrameInfo(); // If neither instruction stores to memory, they can't alias in any // meaningful way, even if they read from the same address. @@ -1656,9 +973,6 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other, if (TII->areMemAccessesTriviallyDisjoint(*this, Other, AA)) return false; - if (!AA) - return true; - // FIXME: Need to handle multiple memory operands to support all targets. if (!hasOneMemOperand() || !Other.hasOneMemOperand()) return true; @@ -1666,9 +980,6 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other, MachineMemOperand *MMOa = *memoperands_begin(); MachineMemOperand *MMOb = *Other.memoperands_begin(); - if (!MMOa->getValue() || !MMOb->getValue()) - return true; - // The following interface to AA is fashioned after DAGCombiner::isAlias // and operates with MachineMemOperand offset with some important // assumptions: @@ -1681,22 +992,53 @@ bool MachineInstr::mayAlias(AliasAnalysis *AA, MachineInstr &Other, // - There should never be any negative offsets here. // // FIXME: Modify API to hide this math from "user" - // FIXME: Even before we go to AA we can reason locally about some + // Even before we go to AA we can reason locally about some // memory objects. It can save compile time, and possibly catch some // corner cases not currently covered. - assert((MMOa->getOffset() >= 0) && "Negative MachineMemOperand offset"); - assert((MMOb->getOffset() >= 0) && "Negative MachineMemOperand offset"); + int64_t OffsetA = MMOa->getOffset(); + int64_t OffsetB = MMOb->getOffset(); + + int64_t MinOffset = std::min(OffsetA, OffsetB); + int64_t WidthA = MMOa->getSize(); + int64_t WidthB = MMOb->getSize(); + const Value *ValA = MMOa->getValue(); + const Value *ValB = MMOb->getValue(); + bool SameVal = (ValA && ValB && (ValA == ValB)); + if (!SameVal) { + const PseudoSourceValue *PSVa = MMOa->getPseudoValue(); + const PseudoSourceValue *PSVb = MMOb->getPseudoValue(); + if (PSVa && ValB && !PSVa->mayAlias(&MFI)) + return false; + if (PSVb && ValA && !PSVb->mayAlias(&MFI)) + return false; + if (PSVa && PSVb && (PSVa == PSVb)) + SameVal = true; + } - int64_t MinOffset = std::min(MMOa->getOffset(), MMOb->getOffset()); - int64_t Overlapa = MMOa->getSize() + MMOa->getOffset() - MinOffset; - int64_t Overlapb = MMOb->getSize() + MMOb->getOffset() - MinOffset; + if (SameVal) { + int64_t MaxOffset = std::max(OffsetA, OffsetB); + int64_t LowWidth = (MinOffset == OffsetA) ? WidthA : WidthB; + return (MinOffset + LowWidth > MaxOffset); + } + + if (!AA) + return true; + + if (!ValA || !ValB) + return true; - AliasResult AAResult = - AA->alias(MemoryLocation(MMOa->getValue(), Overlapa, - UseTBAA ? MMOa->getAAInfo() : AAMDNodes()), - MemoryLocation(MMOb->getValue(), Overlapb, - UseTBAA ? MMOb->getAAInfo() : AAMDNodes())); + assert((OffsetA >= 0) && "Negative MachineMemOperand offset"); + assert((OffsetB >= 0) && "Negative MachineMemOperand offset"); + + int64_t Overlapa = WidthA + OffsetA - MinOffset; + int64_t Overlapb = WidthB + OffsetB - MinOffset; + + AliasResult AAResult = AA->alias( + MemoryLocation(ValA, Overlapa, + UseTBAA ? MMOa->getAAInfo() : AAMDNodes()), + MemoryLocation(ValB, Overlapb, + UseTBAA ? MMOb->getAAInfo() : AAMDNodes())); return (AAResult != NoAlias); } @@ -1822,6 +1164,41 @@ void MachineInstr::copyImplicitOps(MachineFunction &MF, } } +bool MachineInstr::hasComplexRegisterTies() const { + const MCInstrDesc &MCID = getDesc(); + for (unsigned I = 0, E = getNumOperands(); I < E; ++I) { + const auto &Operand = getOperand(I); + if (!Operand.isReg() || Operand.isDef()) + // Ignore the defined registers as MCID marks only the uses as tied. + continue; + int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO); + int TiedIdx = Operand.isTied() ? int(findTiedOperandIdx(I)) : -1; + if (ExpectedTiedIdx != TiedIdx) + return true; + } + return false; +} + +LLT MachineInstr::getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes, + const MachineRegisterInfo &MRI) const { + const MachineOperand &Op = getOperand(OpIdx); + if (!Op.isReg()) + return LLT{}; + + if (isVariadic() || OpIdx >= getNumExplicitOperands()) + return MRI.getType(Op.getReg()); + + auto &OpInfo = getDesc().OpInfo[OpIdx]; + if (!OpInfo.isGenericType()) + return MRI.getType(Op.getReg()); + + if (PrintedTypes[OpInfo.getGenericTypeIndex()]) + return LLT{}; + + PrintedTypes.set(OpInfo.getGenericTypeIndex()); + return MRI.getType(Op.getReg()); +} + #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) LLVM_DUMP_METHOD void MachineInstr::dump() const { dbgs() << " "; @@ -1834,7 +1211,7 @@ void MachineInstr::print(raw_ostream &OS, bool SkipOpers, bool SkipDebugLoc, const Module *M = nullptr; if (const MachineBasicBlock *MBB = getParent()) if (const MachineFunction *MF = MBB->getParent()) - M = MF->getFunction()->getParent(); + M = MF->getFunction().getParent(); ModuleSlotTracker MST(M); print(OS, MST, SkipOpers, SkipDebugLoc, TII); @@ -1863,21 +1240,31 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, // Save a list of virtual registers. SmallVector<unsigned, 8> VirtRegs; + SmallBitVector PrintedTypes(8); + bool ShouldPrintRegisterTies = hasComplexRegisterTies(); + auto getTiedOperandIdx = [&](unsigned OpIdx) { + if (!ShouldPrintRegisterTies) + return 0U; + const MachineOperand &MO = getOperand(OpIdx); + if (MO.isReg() && MO.isTied() && !MO.isDef()) + return findTiedOperandIdx(OpIdx); + return 0U; + }; // Print explicitly defined operands on the left of an assignment syntax. unsigned StartOp = 0, e = getNumOperands(); for (; StartOp < e && getOperand(StartOp).isReg() && - getOperand(StartOp).isDef() && - !getOperand(StartOp).isImplicit(); + getOperand(StartOp).isDef() && !getOperand(StartOp).isImplicit(); ++StartOp) { - if (StartOp != 0) OS << ", "; - getOperand(StartOp).print(OS, MST, TRI, IntrinsicInfo); + if (StartOp != 0) + OS << ", "; + LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(StartOp); + getOperand(StartOp).print(OS, MST, TypeToPrint, /*PrintDef=*/false, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, + IntrinsicInfo); unsigned Reg = getOperand(StartOp).getReg(); - if (TargetRegisterInfo::isVirtualRegister(Reg)) { + if (TargetRegisterInfo::isVirtualRegister(Reg)) VirtRegs.push_back(Reg); - LLT Ty = MRI ? MRI->getType(Reg) : LLT{}; - if (Ty.isValid()) - OS << '(' << Ty << ')'; - } } if (StartOp != 0) @@ -1900,7 +1287,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) { // Print asm string. OS << " "; - getOperand(InlineAsm::MIOp_AsmString).print(OS, MST, TRI); + const unsigned OpIdx = InlineAsm::MIOp_AsmString; + LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(OpIdx); + getOperand(OpIdx).print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, + IntrinsicInfo); // Print HasSideEffects, MayLoad, MayStore, IsAlignStack unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm(); @@ -1943,8 +1335,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata()); if (DIV && !DIV->getName().empty()) OS << "!\"" << DIV->getName() << '\"'; - else - MO.print(OS, MST, TRI); + else { + LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(i); + MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo); + } } else if (TRI && (isInsertSubreg() || isRegSequence() || (isSubregToReg() && i == 3)) && MO.isImm()) { OS << TRI->getSubRegIndexName(MO.getImm()); @@ -2006,8 +1402,15 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, // Compute the index of the next operand descriptor. AsmDescOp += 1 + InlineAsm::getNumOperandRegisters(Flag); - } else - MO.print(OS, MST, TRI); + } else { + LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{}; + unsigned TiedOperandIdx = getTiedOperandIdx(i); + if (MO.isImm() && isOperandSubregIdx(i)) + MachineOperand::printSubregIdx(OS, MO.getImm(), TRI); + else + MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, + ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo); + } } bool HaveSemi = false; @@ -2057,14 +1460,14 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, else OS << " " << TRI->getRegClassName(RC.get<const TargetRegisterClass *>()); - OS << ':' << PrintReg(VirtRegs[i]); + OS << ':' << printReg(VirtRegs[i]); for (unsigned j = i+1; j != VirtRegs.size();) { if (MRI->getRegClassOrRegBank(VirtRegs[j]) != RC) { ++j; continue; } if (VirtRegs[i] != VirtRegs[j]) - OS << "," << PrintReg(VirtRegs[j]); + OS << "," << printReg(VirtRegs[j]); VirtRegs.erase(VirtRegs.begin()+j); } } @@ -2328,8 +1731,8 @@ void MachineInstr::emitError(StringRef Msg) const { MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID, bool IsIndirect, - unsigned Reg, unsigned Offset, - const MDNode *Variable, const MDNode *Expr) { + unsigned Reg, const MDNode *Variable, + const MDNode *Expr) { assert(isa<DILocalVariable>(Variable) && "not a variable"); assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); assert(cast<DILocalVariable>(Variable)->isValidLocationForIntrinsic(DL) && @@ -2337,53 +1740,60 @@ MachineInstrBuilder llvm::BuildMI(MachineFunction &MF, const DebugLoc &DL, if (IsIndirect) return BuildMI(MF, DL, MCID) .addReg(Reg, RegState::Debug) - .addImm(Offset) + .addImm(0U) .addMetadata(Variable) .addMetadata(Expr); - else { - assert(Offset == 0 && "A direct address cannot have an offset."); + else return BuildMI(MF, DL, MCID) .addReg(Reg, RegState::Debug) .addReg(0U, RegState::Debug) .addMetadata(Variable) .addMetadata(Expr); - } } MachineInstrBuilder llvm::BuildMI(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const DebugLoc &DL, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, - unsigned Offset, const MDNode *Variable, - const MDNode *Expr) { + const MDNode *Variable, const MDNode *Expr) { assert(isa<DILocalVariable>(Variable) && "not a variable"); assert(cast<DIExpression>(Expr)->isValid() && "not an expression"); MachineFunction &MF = *BB.getParent(); - MachineInstr *MI = - BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); + MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Variable, Expr); BB.insert(I, MI); return MachineInstrBuilder(MF, MI); } +/// Compute the new DIExpression to use with a DBG_VALUE for a spill slot. +/// This prepends DW_OP_deref when spilling an indirect DBG_VALUE. +static const DIExpression *computeExprForSpill(const MachineInstr &MI) { + assert(MI.getOperand(0).isReg() && "can't spill non-register"); + assert(MI.getDebugVariable()->isValidLocationForIntrinsic(MI.getDebugLoc()) && + "Expected inlined-at fields to agree"); + + const DIExpression *Expr = MI.getDebugExpression(); + if (MI.isIndirectDebugValue()) { + assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset"); + Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); + } + return Expr; +} + MachineInstr *llvm::buildDbgValueForSpill(MachineBasicBlock &BB, MachineBasicBlock::iterator I, const MachineInstr &Orig, int FrameIndex) { - const MDNode *Var = Orig.getDebugVariable(); - const auto *Expr = cast_or_null<DIExpression>(Orig.getDebugExpression()); - bool IsIndirect = Orig.isIndirectDebugValue(); - uint64_t Offset = IsIndirect ? Orig.getOperand(1).getImm() : 0; - DebugLoc DL = Orig.getDebugLoc(); - assert(cast<DILocalVariable>(Var)->isValidLocationForIntrinsic(DL) && - "Expected inlined-at fields to agree"); - // If the DBG_VALUE already was a memory location, add an extra - // DW_OP_deref. Otherwise just turning this from a register into a - // memory/indirect location is sufficient. - if (IsIndirect) - Expr = DIExpression::prepend(Expr, DIExpression::WithDeref); - return BuildMI(BB, I, DL, Orig.getDesc()) + const DIExpression *Expr = computeExprForSpill(Orig); + return BuildMI(BB, I, Orig.getDebugLoc(), Orig.getDesc()) .addFrameIndex(FrameIndex) - .addImm(Offset) - .addMetadata(Var) + .addImm(0U) + .addMetadata(Orig.getDebugVariable()) .addMetadata(Expr); } + +void llvm::updateDbgValueForSpill(MachineInstr &Orig, int FrameIndex) { + const DIExpression *Expr = computeExprForSpill(Orig); + Orig.getOperand(0).ChangeToFrameIndex(FrameIndex); + Orig.getOperand(1).ChangeToImmediate(0U); + Orig.getOperand(3).setMetadata(Expr); +} |