#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/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");
}
/// 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 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 (!debugLoc.isUnknown()) {
const MachineFunction *MF = getParent()->getParent();
DebugLocTuple DLT = MF->getDebugLocTuple(debugLoc);
- DICompileUnit CU(DLT.CompileUnit);
- OS << " [dbg: "
- << CU.getDirectory() << '/' << CU.getFilename() << ","
- << DLT.Line << ","
- << DLT.Col << "]";
+ DICompileUnit CU(DLT.Scope);
+ if (!CU.isNull())
+ OS << " [dbg: "
+ << CU.getDirectory() << '/' << CU.getFilename() << ","
+ << DLT.Line << ","
+ << DLT.Col << "]";
}
OS << "\n";