//
//===----------------------------------------------------------------------===//
-#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/Constants.h"
+#include "llvm/InlineAsm.h"
#include "llvm/Value.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetInstrDesc.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Analysis/DebugInfo.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 <ostream>
using namespace llvm;
//===----------------------------------------------------------------------===//
*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.
/// 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()) {
IsImp = isImp;
IsKill = isKill;
IsDead = isDead;
+ IsUndef = isUndef;
IsEarlyClobber = false;
SubReg = 0;
}
/// 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");
else
OS << "%mreg" << getReg();
}
-
- if (isDef() || isKill() || isDead() || isImplicit() || isEarlyClobber()) {
- OS << "<";
+
+ if (getSubReg() != 0)
+ OS << ':' << getSubReg();
+
+ if (isDef() || isKill() || isDead() || isImplicit() || isUndef() ||
+ isEarlyClobber()) {
+ OS << '<';
bool NeedComma = false;
if (isImplicit()) {
- if (NeedComma) OS << ",";
+ if (NeedComma) OS << ',';
OS << (isDef() ? "imp-def" : "imp-use");
NeedComma = true;
} else if (isDef()) {
- if (NeedComma) OS << ",";
+ if (NeedComma) OS << ',';
if (isEarlyClobber())
OS << "earlyclobber,";
OS << "def";
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() == Type::FloatTy)
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 << "<fi#" << getIndex() << ">";
+ OS << "<fi#" << getIndex() << '>';
break;
case MachineOperand::MO_ConstantPoolIndex:
OS << "<cp#" << getIndex();
if (getOffset()) OS << "+" << getOffset();
- OS << ">";
+ OS << '>';
break;
case MachineOperand::MO_JumpTableIndex:
- OS << "<jt#" << getIndex() << ">";
+ OS << "<jt#" << getIndex() << '>';
break;
case MachineOperand::MO_GlobalAddress:
OS << "<ga:" << ((Value*)getGlobal())->getName();
if (getOffset()) OS << "+" << getOffset();
- OS << ">";
+ OS << '>';
break;
case MachineOperand::MO_ExternalSymbol:
OS << "<es:" << getSymbolName();
if (getOffset()) OS << "+" << getOffset();
- OS << ">";
+ OS << '>';
break;
default:
assert(0 && "Unrecognized operand type");
}
+
+ if (unsigned TF = getTargetFlags())
+ OS << "[TF=" << TF << ']';
}
//===----------------------------------------------------------------------===//
/// MachineInstr ctor - This constructor creates a dummy MachineInstr with
/// TID NULL and no operands.
MachineInstr::MachineInstr()
- : TID(0), NumImplicitOps(0), Parent(0) {
+ : TID(0), NumImplicitOps(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), Parent(0),
+ debugLoc(DebugLoc::getUnknownLoc()) {
+ if (!NoImp && TID->getImplicitDefs())
+ for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
+ NumImplicitOps++;
+ if (!NoImp && TID->getImplicitUses())
+ for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses)
+ NumImplicitOps++;
+ Operands.reserve(NumImplicitOps + TID->getNumOperands());
+ if (!NoImp)
+ addImplicitDefUseOperands();
+ // Make sure that we get added to a machine basicblock
+ LeakDetector::addGarbageObject(this);
+}
+
+/// 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) {
if (!NoImp && TID->getImplicitDefs())
for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
NumImplicitOps++;
LeakDetector::addGarbageObject(this);
}
-/// MachineInstr ctor - Work exactly the same as the ctor above, except that the
-/// MachineInstr is created and added to the end of the specified basic block.
+/// MachineInstr ctor - Work exactly the same as the ctor two above, except
+/// that the MachineInstr is created and added to the end of the specified
+/// basic block.
///
-MachineInstr::MachineInstr(MachineBasicBlock *MBB,
+MachineInstr::MachineInstr(MachineBasicBlock *MBB, const TargetInstrDesc &tid)
+ : TID(&tid), NumImplicitOps(0), Parent(0),
+ debugLoc(DebugLoc::getUnknownLoc()) {
+ assert(MBB && "Cannot use inserting ctor with null basic block!");
+ if (TID->ImplicitDefs)
+ for (const unsigned *ImpDefs = TID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
+ NumImplicitOps++;
+ if (TID->ImplicitUses)
+ for (const unsigned *ImpUses = TID->getImplicitUses(); *ImpUses; ++ImpUses)
+ NumImplicitOps++;
+ Operands.reserve(NumImplicitOps + TID->getNumOperands());
+ addImplicitDefUseOperands();
+ // Make sure that we get added to a machine basicblock
+ LeakDetector::addGarbageObject(this);
+ MBB->push_back(this); // Add instruction to end of basic block!
+}
+
+/// MachineInstr ctor - As above, but with a DebugLoc.
+///
+MachineInstr::MachineInstr(MachineBasicBlock *MBB, const DebugLoc dl,
const TargetInstrDesc &tid)
- : TID(&tid), NumImplicitOps(0), Parent(0) {
+ : TID(&tid), NumImplicitOps(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) {
+ : TID(&MI.getDesc()), NumImplicitOps(0), Parent(0),
+ debugLoc(MI.getDebugLoc()) {
Operands.reserve(MI.getNumOperands());
// Add operands
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++;
}
return -1;
}
-/// isRegReDefinedByTwoAddr - Given the index of a register def 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);
+ assert(FMO.isImm());
+ // 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;
}
+/// 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) const {
+ if (getOpcode() == TargetInstrInfo::INLINEASM) {
+ const MachineOperand &MO = getOperand(UseOpIdx);
+ if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0)
+ return false;
+ int FlagIdx = UseOpIdx - 1;
+ if (FlagIdx < 1)
+ return false;
+ while (!getOperand(FlagIdx).isImm()) {
+ if (--FlagIdx == 0)
+ return false;
+ }
+ const MachineOperand &UFMO = getOperand(FlagIdx);
+ if (FlagIdx + InlineAsm::getNumOperandRegisters(UFMO.getImm()) < UseOpIdx)
+ return false;
+ 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;
+ const MachineOperand &MO = getOperand(UseOpIdx);
+ if (!MO.isReg() || !MO.isUse())
+ return false;
+ int DefIdx = TID.getOperandConstraint(UseOpIdx, TOI::TIED_TO);
+ if (DefIdx == -1)
+ return false;
+ if (DefOpIdx)
+ *DefOpIdx = (unsigned)DefIdx;
+ return true;
+}
+
/// copyKillDeadInfo - Copies kill / dead operand properties from MI.
///
void MachineInstr::copyKillDeadInfo(const MachineInstr *MI) {
SawStore = true;
return false;
}
- if (TID->isReturn() || TID->isBranch() || TID->hasUnmodeledSideEffects())
+ if (TID->isTerminator() || TID->hasUnmodeledSideEffects())
return false;
// See if this instruction does a load. If so, we have to guarantee that the
}
}
+ 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 << "]";
+ }
+
OS << "\n";
}
// 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;
}