#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"
case MachineOperand::MO_ExternalSymbol:
return !strcmp(getSymbolName(), Other.getSymbolName()) &&
getOffset() == Other.getOffset();
+ case MachineOperand::MO_BlockAddress:
+ return getBlockAddress() == Other.getBlockAddress();
}
}
isEarlyClobber()) {
OS << '<';
bool NeedComma = false;
- if (isImplicit()) {
- if (NeedComma) OS << ',';
- OS << (isDef() ? "imp-def" : "imp-use");
- NeedComma = true;
- } else if (isDef()) {
+ 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() || isUndef()) {
if (NeedComma) OS << ',';
if (isKill()) OS << "kill";
OS << getImm();
break;
case MachineOperand::MO_FPImmediate:
- if (getFPImm()->getType() == Type::getFloatTy(getFPImm()->getContext()))
+ if (getFPImm()->getType()->isFloatTy())
OS << getFPImm()->getValueAPF().convertToFloat();
else
OS << getFPImm()->getValueAPF().convertToDouble();
if (getOffset()) OS << "+" << getOffset();
OS << '>';
break;
+ case MachineOperand::MO_BlockAddress:
+ OS << "<blockaddress: ";
+ WriteAsOperand(OS, getBlockAddress()->getFunction(), /*PrintType=*/false);
+ OS << ", ";
+ WriteAsOperand(OS, getBlockAddress()->getBasicBlock(), /*PrintType=*/false);
+ OS << '>';
+ break;
default:
llvm_unreachable("Unrecognized operand type");
}
ID.AddInteger(Flags);
}
-raw_ostream &llvm::operator<<(raw_ostream &OS, const MachineMemOperand &MRO) {
- assert((MRO.isLoad() || MRO.isStore()) &&
+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 (MRO.isVolatile())
+ if (MMO.isVolatile())
OS << "Volatile ";
- if (MRO.isLoad())
+ if (MMO.isLoad())
OS << "LD";
- if (MRO.isStore())
+ if (MMO.isStore())
OS << "ST";
- OS << MRO.getSize();
+ OS << MMO.getSize();
// Print the address information.
OS << "[";
- if (!MRO.getValue())
+ if (!MMO.getValue())
OS << "<unknown>";
else
- WriteAsOperand(OS, MRO.getValue(), /*PrintType=*/false);
+ 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 (MRO.getBaseAlignment() != MRO.getAlignment())
- OS << "(align=" << MRO.getBaseAlignment() << ")";
+ if (MMO.getBaseAlignment() != MMO.getAlignment())
+ OS << "(align=" << MMO.getBaseAlignment() << ")";
- if (MRO.getOffset() != 0)
- OS << "+" << MRO.getOffset();
+ if (MMO.getOffset() != 0)
+ OS << "+" << MMO.getOffset();
OS << "]";
// Print the alignment of the reference.
- if (MRO.getBaseAlignment() != MRO.getAlignment() ||
- MRO.getBaseAlignment() != MRO.getSize())
- OS << "(align=" << MRO.getAlignment() << ")";
+ if (MMO.getBaseAlignment() != MMO.getAlignment() ||
+ MMO.getBaseAlignment() != MMO.getSize())
+ OS << "(align=" << MMO.getAlignment() << ")";
return OS;
}
/// 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);
}
/// 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)
/// 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++;
/// 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)
///
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)
/// 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
addOperand(MI.getOperand(i));
NumImplicitOps = MI.NumImplicitOps;
- // Add memory operands.
- for (std::list<MachineMemOperand>::const_iterator i = MI.memoperands_begin(),
- j = MI.memoperands_end(); i != j; ++i)
- addMemOperand(MF, *i);
-
// Set parent to null.
Parent = 0;
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!");
}
}
-/// 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.
/// 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;
// 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 load is volatile, we can't move it.
return !SawStore && !hasVolatileMemoryRef();
/// 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);
return true;
// Check the memory reference information for volatile references.
- for (std::list<MachineMemOperand>::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;
}
+/// 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<PseudoSourceValue>(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::dump() const {
errs() << " " << *this;
}
if (!memoperands_empty()) {
OS << ", Mem:";
- for (std::list<MachineMemOperand>::const_iterator i = memoperands_begin(),
- e = memoperands_end(); i != e; ++i) {
- OS << *i;
+ 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);
- DICompileUnit CU(DLT.CompileUnit);
- std::string Dir, Fn;
- OS << " [dbg: "
- << CU.getDirectory(Dir) << '/' << CU.getFilename(Fn) << ","
- << DLT.Line << ","
- << DLT.Col << "]";
+ DICompileUnit CU(DLT.Scope);
+ if (!CU.isNull())
+ OS << " [dbg: "
+ << CU.getDirectory() << '/' << CU.getFilename() << ","
+ << DLT.Line << ","
+ << DLT.Col << "]";
}
OS << "\n";