X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FMachineInstr.cpp;h=c27ecff72d223d30eb464b322b3f9ed195362873;hb=ab918103d284b91105831c6b198ad2ab760b907d;hp=cc85b80a1789add6222cbe2a94936bb448364946;hpb=a24752ff43dc1ad8c18c5d9e78549c45f62b980e;p=oota-llvm.git diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index cc85b80a178..c27ecff72d2 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -11,22 +11,27 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Constants.h" #include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/InlineAsm.h" #include "llvm/Value.h" +#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetInstrDesc.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/DebugInfo.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/LeakDetector.h" #include "llvm/Support/MathExtras.h" -#include "llvm/Support/Streams.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/FoldingSet.h" -#include using namespace llvm; //===----------------------------------------------------------------------===// @@ -67,6 +72,21 @@ void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { *Head = this; } +/// RemoveRegOperandFromRegInfo - Remove this register operand from the +/// MachineRegisterInfo it is linked with. +void MachineOperand::RemoveRegOperandFromRegInfo() { + assert(isOnRegUseList() && "Reg operand is not on a use list"); + // Unlink this from the doubly linked list of operands. + MachineOperand *NextOp = Contents.Reg.Next; + *Contents.Reg.Prev = NextOp; + if (NextOp) { + assert(NextOp->getReg() == getReg() && "Corrupt reg use/def chain!"); + NextOp->Contents.Reg.Prev = Contents.Reg.Prev; + } + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; +} + void MachineOperand::setReg(unsigned Reg) { if (getReg() == Reg) return; // No change. @@ -104,7 +124,7 @@ void MachineOperand::ChangeToImmediate(int64_t ImmVal) { /// 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 isKill, bool isDead, bool isUndef) { // If this operand is already a register operand, use setReg to update the // register's use/def lists. if (isReg()) { @@ -127,6 +147,7 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, IsImp = isImp; IsKill = isKill; IsDead = isDead; + IsUndef = isUndef; IsEarlyClobber = false; SubReg = 0; } @@ -134,10 +155,12 @@ void MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, /// isIdenticalTo - Return true if this operand is identical to the specified /// operand. bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { - if (getType() != Other.getType()) return false; + if (getType() != Other.getType() || + getTargetFlags() != Other.getTargetFlags()) + return false; switch (getType()) { - default: assert(0 && "Unrecognized operand type"); + default: llvm_unreachable("Unrecognized operand type"); case MachineOperand::MO_Register: return getReg() == Other.getReg() && isDef() == Other.isDef() && getSubReg() == Other.getSubReg(); @@ -158,16 +181,13 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { case MachineOperand::MO_ExternalSymbol: return !strcmp(getSymbolName(), Other.getSymbolName()) && getOffset() == Other.getOffset(); + case MachineOperand::MO_BlockAddress: + return getBlockAddress() == Other.getBlockAddress(); } } /// print - Print the specified machine operand. /// -void MachineOperand::print(std::ostream &OS, const TargetMachine *TM) const { - raw_os_ostream RawOS(OS); - print(RawOS, TM); -} - void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { switch (getType()) { case MachineOperand::MO_Register: @@ -188,71 +208,87 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { OS << "%mreg" << getReg(); } - if (getSubReg() != 0) { - OS << ":" << getSubReg(); - } + if (getSubReg() != 0) + OS << ':' << getSubReg(); - if (isDef() || isKill() || isDead() || isImplicit() || isEarlyClobber()) { - OS << "<"; + if (isDef() || isKill() || isDead() || isImplicit() || isUndef() || + isEarlyClobber()) { + OS << '<'; bool NeedComma = false; - if (isImplicit()) { - if (NeedComma) OS << ","; - OS << (isDef() ? "imp-def" : "imp-use"); - NeedComma = true; - } else if (isDef()) { - if (NeedComma) OS << ","; + if (isDef()) { + if (NeedComma) OS << ','; if (isEarlyClobber()) OS << "earlyclobber,"; + if (isImplicit()) + OS << "imp-"; OS << "def"; NeedComma = true; + } else if (isImplicit()) { + OS << "imp-use"; + NeedComma = true; } - if (isKill() || isDead()) { - if (NeedComma) OS << ","; + + if (isKill() || isDead() || isUndef()) { + if (NeedComma) OS << ','; if (isKill()) OS << "kill"; if (isDead()) OS << "dead"; + if (isUndef()) { + if (isKill() || isDead()) + OS << ','; + OS << "undef"; + } } - OS << ">"; + OS << '>'; } break; case MachineOperand::MO_Immediate: OS << getImm(); break; case MachineOperand::MO_FPImmediate: - if (getFPImm()->getType() == Type::FloatTy) { + if (getFPImm()->getType()->isFloatTy()) OS << getFPImm()->getValueAPF().convertToFloat(); - } else { + else OS << getFPImm()->getValueAPF().convertToDouble(); - } break; case MachineOperand::MO_MachineBasicBlock: OS << "mbb<" << ((Value*)getMBB()->getBasicBlock())->getName() - << "," << (void*)getMBB() << ">"; + << "," << (void*)getMBB() << '>'; break; case MachineOperand::MO_FrameIndex: - OS << ""; + OS << "'; break; case MachineOperand::MO_ConstantPoolIndex: OS << ""; + OS << '>'; break; case MachineOperand::MO_JumpTableIndex: - OS << ""; + OS << "'; break; case MachineOperand::MO_GlobalAddress: OS << "getName(); if (getOffset()) OS << "+" << getOffset(); - OS << ">"; + OS << '>'; break; case MachineOperand::MO_ExternalSymbol: OS << ""; + OS << '>'; + break; + case MachineOperand::MO_BlockAddress: + OS << "getFunction(), /*PrintType=*/false); + OS << ", "; + WriteAsOperand(OS, getBlockAddress()->getBasicBlock(), /*PrintType=*/false); + OS << '>'; break; default: - assert(0 && "Unrecognized operand type"); + llvm_unreachable("Unrecognized operand type"); } + + if (unsigned TF = getTargetFlags()) + OS << "[TF=" << TF << ']'; } //===----------------------------------------------------------------------===// @@ -263,7 +299,7 @@ MachineMemOperand::MachineMemOperand(const Value *v, unsigned int f, int64_t o, uint64_t s, unsigned int a) : Offset(o), Size(s), V(v), Flags((f & 7) | ((Log2_32(a) + 1) << 3)) { - assert(isPowerOf2_32(a) && "Alignment is not a power of 2!"); + assert(getBaseAlignment() == a && "Alignment is not a power of 2!"); assert((isLoad() || isStore()) && "Not a load/store!"); } @@ -276,6 +312,66 @@ void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { ID.AddInteger(Flags); } +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. + Flags = (Flags & 7) | ((Log2_32(MMO->getBaseAlignment()) + 1) << 3); + // Also update the base and offset, because the new alignment may + // not be applicable with the old ones. + V = MMO->getValue(); + Offset = MMO->getOffset(); + } +} + +/// getAlignment - Return the minimum known alignment in bytes of the +/// actual memory reference. +uint64_t MachineMemOperand::getAlignment() const { + return MinAlign(getBaseAlignment(), getOffset()); +} + +raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MMO) { + assert((MMO.isLoad() || MMO.isStore()) && + "SV has to be a load, store or both."); + + if (MMO.isVolatile()) + OS << "Volatile "; + + if (MMO.isLoad()) + OS << "LD"; + if (MMO.isStore()) + OS << "ST"; + OS << MMO.getSize(); + + // Print the address information. + OS << "["; + if (!MMO.getValue()) + OS << ""; + else + WriteAsOperand(OS, MMO.getValue(), /*PrintType=*/false); + + // 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 (MMO.getBaseAlignment() != MMO.getAlignment()) + OS << "(align=" << MMO.getBaseAlignment() << ")"; + + if (MMO.getOffset() != 0) + OS << "+" << MMO.getOffset(); + OS << "]"; + + // Print the alignment of the reference. + if (MMO.getBaseAlignment() != MMO.getAlignment() || + MMO.getBaseAlignment() != MMO.getSize()) + OS << "(align=" << MMO.getAlignment() << ")"; + + return OS; +} + //===----------------------------------------------------------------------===// // MachineInstr Implementation //===----------------------------------------------------------------------===// @@ -283,7 +379,8 @@ void MachineMemOperand::Profile(FoldingSetNodeID &ID) const { /// MachineInstr ctor - This constructor creates a dummy MachineInstr with /// TID NULL and no operands. MachineInstr::MachineInstr() - : TID(0), NumImplicitOps(0), Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { + : TID(0), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { // Make sure that we get added to a machine basicblock LeakDetector::addGarbageObject(this); } @@ -302,7 +399,7 @@ void MachineInstr::addImplicitDefUseOperands() { /// TargetInstrDesc or the numOperands if it is not zero. (for /// instructions with variable number of operands). MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) - : TID(&tid), NumImplicitOps(0), Parent(0), + : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { if (!NoImp && TID->getImplicitDefs()) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) @@ -320,7 +417,8 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, bool NoImp) /// MachineInstr ctor - As above, but with a DebugLoc. MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, bool NoImp) - : TID(&tid), NumImplicitOps(0), Parent(0), debugLoc(dl) { + : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(dl) { if (!NoImp && TID->getImplicitDefs()) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) NumImplicitOps++; @@ -339,7 +437,7 @@ MachineInstr::MachineInstr(const TargetInstrDesc &tid, const DebugLoc dl, /// basic block. /// MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), Parent(0), + : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), Parent(0), debugLoc(DebugLoc::getUnknownLoc()) { assert(MBB && "Cannot use inserting ctor with null basic block!"); if (TID->ImplicitDefs) @@ -359,7 +457,8 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid) /// MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, const TargetInstrDesc &tid) - : TID(&tid), NumImplicitOps(0), Parent(0), debugLoc(dl) { + : TID(&tid), NumImplicitOps(0), MemRefs(0), MemRefsEnd(0), + Parent(0), debugLoc(dl) { assert(MBB && "Cannot use inserting ctor with null basic block!"); if (TID->ImplicitDefs) for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs) @@ -377,8 +476,9 @@ MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl, /// MachineInstr ctor - Copies MachineInstr arg exactly /// MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) - : TID(&MI.getDesc()), NumImplicitOps(0), Parent(0), - debugLoc(MI.getDebugLoc()) { + : TID(&MI.getDesc()), NumImplicitOps(0), + MemRefs(MI.MemRefs), MemRefsEnd(MI.MemRefsEnd), + Parent(0), debugLoc(MI.getDebugLoc()) { Operands.reserve(MI.getNumOperands()); // Add operands @@ -386,11 +486,6 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) addOperand(MI.getOperand(i)); NumImplicitOps = MI.NumImplicitOps; - // Add memory operands. - for (std::list::const_iterator i = MI.memoperands_begin(), - j = MI.memoperands_end(); i != j; ++i) - addMemOperand(MF, *i); - // Set parent to null. Parent = 0; @@ -399,8 +494,6 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI) MachineInstr::~MachineInstr() { LeakDetector::removeGarbageObject(this); - assert(MemOperands.empty() && - "MachineInstr being deleted with live memoperands!"); #ifndef NDEBUG for (unsigned i = 0, e = Operands.size(); i != e; ++i) { assert(Operands[i].ParentMI == this && "ParentMI mismatch!"); @@ -561,18 +654,24 @@ void MachineInstr::RemoveOperand(unsigned OpNo) { } } -/// addMemOperand - Add a MachineMemOperand to the machine instruction, -/// referencing arbitrary storage. +/// addMemOperand - Add a MachineMemOperand to the machine instruction. +/// This function should be used only occasionally. The setMemRefs function +/// is the primary method for setting up a MachineInstr's MemRefs list. void MachineInstr::addMemOperand(MachineFunction &MF, - const MachineMemOperand &MO) { - MemOperands.push_back(MO); -} + MachineMemOperand *MO) { + mmo_iterator OldMemRefs = MemRefs; + mmo_iterator OldMemRefsEnd = MemRefsEnd; -/// clearMemOperands - Erase all of this MachineInstr's MachineMemOperands. -void MachineInstr::clearMemOperands(MachineFunction &MF) { - MemOperands.clear(); -} + size_t NewNum = (MemRefsEnd - MemRefs) + 1; + mmo_iterator NewMemRefs = MF.allocateMemRefsArray(NewNum); + mmo_iterator NewMemRefsEnd = NewMemRefs + NewNum; + std::copy(OldMemRefs, OldMemRefsEnd, NewMemRefs); + NewMemRefs[NewNum - 1] = MO; + + MemRefs = NewMemRefs; + MemRefsEnd = NewMemRefsEnd; +} /// removeFromParent - This method unlinks 'this' from the containing basic /// block, and returns it, but does not delete it. @@ -607,8 +706,8 @@ unsigned MachineInstr::getNumExplicitOperands() const { if (!TID->isVariadic()) return NumOperands; - for (unsigned e = getNumOperands(); NumOperands != e; ++NumOperands) { - const MachineOperand &MO = getOperand(NumOperands); + for (unsigned i = NumOperands, e = getNumOperands(); i != e; ++i) { + const MachineOperand &MO = getOperand(i); if (!MO.isReg() || !MO.isImplicit()) NumOperands++; } @@ -631,7 +730,7 @@ bool MachineInstr::isDebugLabel() const { } /// findRegisterUseOperandIdx() - Returns the MachineOperand that is a use of -/// the specific register or -1 if it is not found. It further tightening +/// the specific register or -1 if it is not found. It further tightens /// the search criteria to a use that kills the register if isKill is true. int MachineInstr::findRegisterUseOperandIdx(unsigned Reg, bool isKill, const TargetRegisterInfo *TRI) const { @@ -689,16 +788,62 @@ int MachineInstr::findFirstPredOperandIdx() const { return -1; } -/// isRegReDefinedByTwoAddr - Given the index of a register operand, -/// check if the register def is a re-definition due to two addr elimination. -bool MachineInstr::isRegReDefinedByTwoAddr(unsigned DefIdx) const{ - assert(getOperand(DefIdx).isDef() && "DefIdx is not a def!"); +/// isRegTiedToUseOperand - Given the index of a register def operand, +/// check if the register def is tied to a source operand, due to either +/// two-address elimination or inline assembly constraints. Returns the +/// first tied use operand index by reference is UseOpIdx is not null. +bool MachineInstr:: +isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx) const { + if (getOpcode() == TargetInstrInfo::INLINEASM) { + assert(DefOpIdx >= 2); + const MachineOperand &MO = getOperand(DefOpIdx); + if (!MO.isReg() || !MO.isDef() || MO.getReg() == 0) + return false; + // Determine the actual operand index that corresponds to this index. + unsigned DefNo = 0; + unsigned DefPart = 0; + for (unsigned i = 1, e = getNumOperands(); i < e; ) { + const MachineOperand &FMO = getOperand(i); + // After the normal asm operands there may be additional imp-def regs. + if (!FMO.isImm()) + return false; + // Skip over this def. + unsigned NumOps = InlineAsm::getNumOperandRegisters(FMO.getImm()); + unsigned PrevDef = i + 1; + i = PrevDef + NumOps; + if (i > DefOpIdx) { + DefPart = DefOpIdx - PrevDef; + break; + } + ++DefNo; + } + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + const MachineOperand &FMO = getOperand(i); + if (!FMO.isImm()) + continue; + if (i+1 >= e || !getOperand(i+1).isReg() || !getOperand(i+1).isUse()) + continue; + unsigned Idx; + if (InlineAsm::isUseOperandTiedToDef(FMO.getImm(), Idx) && + Idx == DefNo) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i + 1 + DefPart; + return true; + } + } + return false; + } + + assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!"); const TargetInstrDesc &TID = getDesc(); for (unsigned i = 0, e = TID.getNumOperands(); i != e; ++i) { const MachineOperand &MO = getOperand(i); if (MO.isReg() && MO.isUse() && - TID.getOperandConstraint(i, TOI::TIED_TO) == (int)DefIdx) + TID.getOperandConstraint(i, TOI::TIED_TO) == (int)DefOpIdx) { + if (UseOpIdx) + *UseOpIdx = (unsigned)i; return true; + } } return false; } @@ -706,7 +851,49 @@ bool MachineInstr::isRegReDefinedByTwoAddr(unsigned DefIdx) const{ /// isRegTiedToDefOperand - Return true if the operand of the specified index /// is a register use and it is tied to an def operand. It also returns the def /// operand index by reference. -bool MachineInstr::isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx){ +bool MachineInstr:: +isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx) const { + if (getOpcode() == TargetInstrInfo::INLINEASM) { + const MachineOperand &MO = getOperand(UseOpIdx); + if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0) + return false; + + // Find the flag operand corresponding to UseOpIdx + unsigned FlagIdx, NumOps=0; + for (FlagIdx = 1; FlagIdx < UseOpIdx; FlagIdx += NumOps+1) { + const MachineOperand &UFMO = getOperand(FlagIdx); + // After the normal asm operands there may be additional imp-def regs. + if (!UFMO.isImm()) + return false; + NumOps = InlineAsm::getNumOperandRegisters(UFMO.getImm()); + assert(NumOps < getNumOperands() && "Invalid inline asm flag"); + if (UseOpIdx < FlagIdx+NumOps+1) + break; + } + if (FlagIdx >= UseOpIdx) + return false; + const MachineOperand &UFMO = getOperand(FlagIdx); + unsigned DefNo; + if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) { + if (!DefOpIdx) + return true; + + unsigned DefIdx = 1; + // Remember to adjust the index. First operand is asm string, then there + // is a flag for each. + while (DefNo) { + const MachineOperand &FMO = getOperand(DefIdx); + assert(FMO.isImm()); + // Skip over this def. + DefIdx += InlineAsm::getNumOperandRegisters(FMO.getImm()) + 1; + --DefNo; + } + *DefOpIdx = DefIdx + UseOpIdx - FlagIdx; + return true; + } + return false; + } + const TargetInstrDesc &TID = getDesc(); if (UseOpIdx >= TID.getNumOperands()) return false; @@ -758,7 +945,8 @@ void MachineInstr::copyPredicates(const MachineInstr *MI) { /// SawStore is set to true, it means that there is a store (or call) between /// the instruction's location and its intended destination. bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, - bool &SawStore) const { + bool &SawStore, + AliasAnalysis *AA) const { // Ignore stuff that we obviously can't move. if (TID->mayStore() || TID->isCall()) { SawStore = true; @@ -772,9 +960,9 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, // destination. The check for isInvariantLoad gives the targe the chance to // classify the load as always returning a constant, e.g. a constant pool // load. - if (TID->mayLoad() && !TII->isInvariantLoad(this)) + if (TID->mayLoad() && !isInvariantLoad(AA)) // Otherwise, this is a real load. If there is a store between the load and - // end of block, or if the laod is volatile, we can't move it. + // end of block, or if the load is volatile, we can't move it. return !SawStore && !hasVolatileMemoryRef(); return true; @@ -783,11 +971,11 @@ bool MachineInstr::isSafeToMove(const TargetInstrInfo *TII, /// isSafeToReMat - Return true if it's safe to rematerialize the specified /// instruction which defined the specified register instead of copying it. bool MachineInstr::isSafeToReMat(const TargetInstrInfo *TII, - unsigned DstReg) const { + unsigned DstReg, + AliasAnalysis *AA) const { bool SawStore = false; - if (!getDesc().isRematerializable() || - !TII->isTriviallyReMaterializable(this) || - !isSafeToMove(TII, SawStore)) + if (!TII->isTriviallyReMaterializable(this, AA) || + !isSafeToMove(TII, SawStore, AA)) return false; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { const MachineOperand &MO = getOperand(i); @@ -824,21 +1012,55 @@ bool MachineInstr::hasVolatileMemoryRef() const { return true; // Check the memory reference information for volatile references. - for (std::list::const_iterator I = memoperands_begin(), - E = memoperands_end(); I != E; ++I) - if (I->isVolatile()) + for (mmo_iterator I = memoperands_begin(), E = memoperands_end(); I != E; ++I) + if ((*I)->isVolatile()) return true; return false; } -void MachineInstr::dump() const { - cerr << " " << *this; +/// isInvariantLoad - Return true if this instruction is loading from a +/// location whose value is invariant across the function. For example, +/// loading a value from the constant pool or from from the argument area +/// of a function if it does not change. This should only return true of +/// *all* loads the instruction does are invariant (if it does multiple loads). +bool MachineInstr::isInvariantLoad(AliasAnalysis *AA) const { + // If the instruction doesn't load at all, it isn't an invariant load. + if (!TID->mayLoad()) + return false; + + // If the instruction has lost its memoperands, conservatively assume that + // it may not be an invariant load. + if (memoperands_empty()) + return false; + + const MachineFrameInfo *MFI = getParent()->getParent()->getFrameInfo(); + + for (mmo_iterator I = memoperands_begin(), + E = memoperands_end(); I != E; ++I) { + if ((*I)->isVolatile()) return false; + if ((*I)->isStore()) return false; + + if (const Value *V = (*I)->getValue()) { + // A load from a constant PseudoSourceValue is invariant. + if (const PseudoSourceValue *PSV = dyn_cast(V)) + if (PSV->isConstant(MFI)) + continue; + // If we have an AliasAnalysis, ask it whether the memory is constant. + if (AA && AA->pointsToConstantMemory(V)) + continue; + } + + // Otherwise assume conservatively. + return false; + } + + // Everything checks out. + return true; } -void MachineInstr::print(std::ostream &OS, const TargetMachine *TM) const { - raw_os_ostream RawOS(OS); - print(RawOS, TM); +void MachineInstr::dump() const { + errs() << " " << *this; } void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { @@ -861,44 +1083,23 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const { if (!memoperands_empty()) { OS << ", Mem:"; - for (std::list::const_iterator i = memoperands_begin(), - e = memoperands_end(); i != e; ++i) { - const MachineMemOperand &MRO = *i; - const Value *V = MRO.getValue(); - - assert((MRO.isLoad() || MRO.isStore()) && - "SV has to be a load, store or both."); - - if (MRO.isVolatile()) - OS << "Volatile "; - - if (MRO.isLoad()) - OS << "LD"; - if (MRO.isStore()) - OS << "ST"; - - OS << "(" << MRO.getSize() << "," << MRO.getAlignment() << ") ["; - - if (!V) - OS << ""; - else if (!V->getName().empty()) - OS << V->getName(); - else if (const PseudoSourceValue *PSV = dyn_cast(V)) { - PSV->print(OS); - } else - OS << V; - - OS << " + " << MRO.getOffset() << "]"; + for (mmo_iterator i = memoperands_begin(), e = memoperands_end(); + i != e; ++i) { + OS << **i; + if (next(i) != e) + OS << " "; } } if (!debugLoc.isUnknown()) { const MachineFunction *MF = getParent()->getParent(); DebugLocTuple DLT = MF->getDebugLocTuple(debugLoc); - OS << " [dbg: " - << DLT.Src << "," - << DLT.Line << "," - << DLT.Col << "]"; + DICompileUnit CU(DLT.Scope); + if (!CU.isNull()) + OS << " [dbg: " + << CU.getDirectory() << '/' << CU.getFilename() << "," + << DLT.Line << "," + << DLT.Col << "]"; } OS << "\n"; @@ -913,7 +1114,7 @@ bool MachineInstr::addRegisterKilled(unsigned IncomingReg, SmallVector DeadOps; for (unsigned i = 0, e = getNumOperands(); i != e; ++i) { MachineOperand &MO = getOperand(i); - if (!MO.isReg() || !MO.isUse()) + if (!MO.isReg() || !MO.isUse() || MO.isUndef()) continue; unsigned Reg = MO.getReg(); if (!Reg) @@ -924,6 +1125,9 @@ bool MachineInstr::addRegisterKilled(unsigned IncomingReg, if (MO.isKill()) // The register is already marked kill. return true; + if (isPhysReg && isRegTiedToDefOperand(i)) + // Two-address uses of physregs must not be marked kill. + return true; MO.setIsKill(); Found = true; } @@ -1006,13 +1210,13 @@ bool MachineInstr::addRegisterDead(unsigned IncomingReg, // If not found, this means an alias of one of the operands is dead. Add a // new implicit operand if required. - if (!Found && AddIfNotFound) { - addOperand(MachineOperand::CreateReg(IncomingReg, - true /*IsDef*/, - true /*IsImp*/, - false /*IsKill*/, - true /*IsDead*/)); - return true; - } - return Found; + if (Found || !AddIfNotFound) + return Found; + + addOperand(MachineOperand::CreateReg(IncomingReg, + true /*IsDef*/, + true /*IsImp*/, + false /*IsKill*/, + true /*IsDead*/)); + return true; }