//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/Constants.h"
-#include "llvm/DebugInfo.h"
-#include "llvm/Function.h"
-#include "llvm/InlineAsm.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Metadata.h"
-#include "llvm/Module.h"
-#include "llvm/Type.h"
-#include "llvm/Value.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/Constants.h"
+#include "llvm/DebugInfo.h"
+#include "llvm/Function.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/LLVMContext.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Target/TargetMachine.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetRegisterInfo.h"
-#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Metadata.h"
+#include "llvm/Module.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/Hashing.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Type.h"
+#include "llvm/Value.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
IsDebug = isDebug;
// Ensure isOnRegUseList() returns false.
Contents.Reg.Prev = 0;
- // Preserve the tie bit when the operand was already a register.
+ // Preserve the tie when the operand was already a register.
if (!WasReg)
- IsTied = false;
+ TiedTo = 0;
// If this operand is embedded in a function, add the operand to the
// register's use/def list.
return !strcmp(getSymbolName(), Other.getSymbolName()) &&
getOffset() == Other.getOffset();
case MachineOperand::MO_BlockAddress:
- return getBlockAddress() == Other.getBlockAddress();
+ return getBlockAddress() == Other.getBlockAddress() &&
+ getOffset() == Other.getOffset();
case MO_RegisterMask:
return getRegMask() == Other.getRegMask();
case MachineOperand::MO_MCSymbol:
MO.getOffset());
case MachineOperand::MO_BlockAddress:
return hash_combine(MO.getType(), MO.getTargetFlags(),
- MO.getBlockAddress());
+ MO.getBlockAddress(), MO.getOffset());
case MachineOperand::MO_RegisterMask:
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getRegMask());
case MachineOperand::MO_Metadata:
if (isTied()) {
if (NeedComma) OS << ',';
OS << "tied";
+ if (TiedTo != 15)
+ OS << unsigned(TiedTo - 1);
NeedComma = true;
}
OS << '>';
case MachineOperand::MO_BlockAddress:
OS << '<';
WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false);
+ if (getOffset()) OS << "+" << getOffset();
OS << '>';
break;
case MachineOperand::MO_RegisterMask:
// MachineInstr Implementation
//===----------------------------------------------------------------------===//
-/// MachineInstr ctor - This constructor creates a dummy MachineInstr with
-/// MCID NULL and no operands.
-MachineInstr::MachineInstr()
- : MCID(0), Flags(0), AsmPrinterFlags(0),
- NumMemRefs(0), MemRefs(0),
- Parent(0) {
- // Make sure that we get added to a machine basicblock
- LeakDetector::addGarbageObject(this);
-}
-
void MachineInstr::addImplicitDefUseOperands() {
if (MCID->ImplicitDefs)
for (const uint16_t *ImpDefs = MCID->getImplicitDefs(); *ImpDefs; ++ImpDefs)
/// MachineInstr ctor - This constructor creates a MachineInstr and adds the
/// implicit operands. It reserves space for the number of operands specified by
/// the MCInstrDesc.
-MachineInstr::MachineInstr(const MCInstrDesc &tid, bool NoImp)
- : MCID(&tid), Flags(0), AsmPrinterFlags(0),
- NumMemRefs(0), MemRefs(0), Parent(0) {
- unsigned NumImplicitOps = 0;
- if (!NoImp)
- NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses();
- Operands.reserve(NumImplicitOps + MCID->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 MCInstrDesc &tid, const DebugLoc dl,
bool NoImp)
: MCID(&tid), Flags(0), AsmPrinterFlags(0),
LeakDetector::addGarbageObject(this);
}
-/// 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, const MCInstrDesc &tid)
- : MCID(&tid), Flags(0), AsmPrinterFlags(0),
- NumMemRefs(0), MemRefs(0), Parent(0) {
- assert(MBB && "Cannot use inserting ctor with null basic block!");
- unsigned NumImplicitOps =
- MCID->getNumImplicitDefs() + MCID->getNumImplicitUses();
- Operands.reserve(NumImplicitOps + MCID->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 MCInstrDesc &tid)
- : MCID(&tid), Flags(0), AsmPrinterFlags(0),
- NumMemRefs(0), MemRefs(0), Parent(0), debugLoc(dl) {
- assert(MBB && "Cannot use inserting ctor with null basic block!");
- unsigned NumImplicitOps =
- MCID->getNumImplicitDefs() + MCID->getNumImplicitUses();
- Operands.reserve(NumImplicitOps + MCID->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 - Copies MachineInstr arg exactly
///
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
if (!isImpReg && !isInlineAsm()) {
while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
--OpNo;
+ assert(!Operands[OpNo].isTied() && "Cannot move tied operands");
if (RegInfo)
RegInfo->removeRegOperandFromUseList(&Operands[OpNo]);
}
if (Operands[OpNo].isReg()) {
// Ensure isOnRegUseList() returns false, regardless of Op's status.
Operands[OpNo].Contents.Reg.Prev = 0;
- // Ignore existing IsTied bit. This is not a property that can be copied.
- Operands[OpNo].IsTied = false;
+ // Ignore existing ties. This is not a property that can be copied.
+ Operands[OpNo].TiedTo = 0;
// Add the new operand to RegInfo.
if (RegInfo)
RegInfo->addRegOperandToUseList(&Operands[OpNo]);
// explicit operands. The implicit operands are added first, then the
// explicits are inserted before them.
if (!isImpReg) {
- // Set the IsTied bit if MC indicates this use is tied to a def.
+ // Tie uses to defs as indicated in MCInstrDesc.
if (Operands[OpNo].isUse()) {
int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
- if (DefIdx != -1) {
- MachineOperand &DefMO = getOperand(DefIdx);
- assert(DefMO.isDef() && "Use tied to operand that isn't a def");
- DefMO.IsTied = true;
- Operands[OpNo].IsTied = true;
- }
+ if (DefIdx != -1)
+ tieOperands(DefIdx, OpNo);
}
// If the register operand is flagged as early, mark the operand as such.
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
}
}
+#ifndef NDEBUG
+ // Moving tied operands would break the ties.
+ for (unsigned i = OpNo + 1, e = Operands.size(); i != e; ++i)
+ if (Operands[i].isReg())
+ assert(!Operands[i].isTied() && "Cannot move tied operands");
+#endif
+
Operands.erase(Operands.begin()+OpNo);
if (RegInfo) {
return false;
}
+InlineAsm::AsmDialect MachineInstr::getInlineAsmDialect() const {
+ assert(isInlineAsm() && "getInlineAsmDialect() only works for inline asms!");
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ return InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect) != 0);
+}
+
int MachineInstr::findInlineAsmFlagIdx(unsigned OpIdx,
unsigned *GroupNo) const {
assert(isInlineAsm() && "Expected an inline asm instruction");
unsigned MachineInstr::getBundleSize() const {
assert(isBundle() && "Expecting a bundle");
- MachineBasicBlock::const_instr_iterator I = *this;
+ const MachineBasicBlock *MBB = getParent();
+ MachineBasicBlock::const_instr_iterator I = *this, E = MBB->instr_end();
unsigned Size = 0;
- while ((++I)->isInsideBundle()) {
+ while ((++I != E) && I->isInsideBundle()) {
++Size;
}
assert(Size > 1 && "Malformed bundle");
return -1;
}
-/// Given the index of a tied register operand, find the operand it is tied to.
-/// Defs are tied to uses and vice versa. Returns the index of the tied operand
-/// which must exist.
-unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const {
- // It doesn't usually happen, but an instruction can have multiple pairs of
- // tied operands.
- SmallVector<unsigned, 4> Uses, Defs;
- unsigned PairNo = ~0u;
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = getOperand(i);
- if (!MO.isReg() || !MO.isTied())
- continue;
- if (MO.isUse()) {
- if (i == OpIdx)
- PairNo = Uses.size();
- Uses.push_back(i);
- } else {
- if (i == OpIdx)
- PairNo = Defs.size();
- Defs.push_back(i);
- }
+// MachineOperand::TiedTo is 4 bits wide.
+const unsigned TiedMax = 15;
+
+/// tieOperands - Mark operands at DefIdx and UseIdx as tied to each other.
+///
+/// Use and def operands can be tied together, indicated by a non-zero TiedTo
+/// field. TiedTo can have these values:
+///
+/// 0: Operand is not tied to anything.
+/// 1 to TiedMax-1: Tied to getOperand(TiedTo-1).
+/// TiedMax: Tied to an operand >= TiedMax-1.
+///
+/// The tied def must be one of the first TiedMax operands on a normal
+/// instruction. INLINEASM instructions allow more tied defs.
+///
+void MachineInstr::tieOperands(unsigned DefIdx, unsigned UseIdx) {
+ MachineOperand &DefMO = getOperand(DefIdx);
+ MachineOperand &UseMO = getOperand(UseIdx);
+ assert(DefMO.isDef() && "DefIdx must be a def operand");
+ assert(UseMO.isUse() && "UseIdx must be a use operand");
+ assert(!DefMO.isTied() && "Def is already tied to another use");
+ assert(!UseMO.isTied() && "Use is already tied to another def");
+
+ if (DefIdx < TiedMax)
+ UseMO.TiedTo = DefIdx + 1;
+ else {
+ // Inline asm can use the group descriptors to find tied operands, but on
+ // normal instruction, the tied def must be within the first TiedMax
+ // operands.
+ assert(isInlineAsm() && "DefIdx out of range");
+ UseMO.TiedTo = TiedMax;
}
- // For each tied use there must be a tied def and vice versa.
- assert(Uses.size() == Defs.size() && "Tied uses and defs don't match");
- assert(PairNo < Uses.size() && "OpIdx must be a tied register operand");
- // Find the matching operand.
- return (getOperand(OpIdx).isDef() ? Uses : Defs)[PairNo];
+ // UseIdx can be out of range, we'll search for it in findTiedOperandIdx().
+ DefMO.TiedTo = std::min(UseIdx + 1, TiedMax);
}
-/// 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 (isInlineAsm()) {
- assert(DefOpIdx > InlineAsm::MIOp_FirstOperand);
- 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;
- int FlagIdx = findInlineAsmFlagIdx(DefOpIdx, &DefNo);
- if (FlagIdx < 0)
- return false;
-
- // Which part of the group is DefOpIdx?
- unsigned DefPart = DefOpIdx - (FlagIdx + 1);
+/// Given the index of a tied register operand, find the operand it is tied to.
+/// Defs are tied to uses and vice versa. Returns the index of the tied operand
+/// which must exist.
+unsigned MachineInstr::findTiedOperandIdx(unsigned OpIdx) const {
+ const MachineOperand &MO = getOperand(OpIdx);
+ assert(MO.isTied() && "Operand isn't tied");
- for (unsigned i = InlineAsm::MIOp_FirstOperand, 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;
- }
+ // Normally TiedTo is in range.
+ if (MO.TiedTo < TiedMax)
+ return MO.TiedTo - 1;
- assert(getOperand(DefOpIdx).isDef() && "DefOpIdx is not a def!");
- const MCInstrDesc &MCID = getDesc();
- for (unsigned i = 0, e = MCID.getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = getOperand(i);
- if (MO.isReg() && MO.isUse() &&
- MCID.getOperandConstraint(i, MCOI::TIED_TO) == (int)DefOpIdx) {
- if (UseOpIdx)
- *UseOpIdx = (unsigned)i;
- return true;
+ // Uses on normal instructions can be out of range.
+ if (!isInlineAsm()) {
+ // Normal tied defs must be in the 0..TiedMax-1 range.
+ if (MO.isUse())
+ return TiedMax - 1;
+ // MO is a def. Search for the tied use.
+ for (unsigned i = TiedMax - 1, e = getNumOperands(); i != e; ++i) {
+ const MachineOperand &UseMO = getOperand(i);
+ if (UseMO.isReg() && UseMO.isUse() && UseMO.TiedTo == OpIdx + 1)
+ return i;
}
+ llvm_unreachable("Can't find tied use");
}
- 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 (isInlineAsm()) {
- const MachineOperand &MO = getOperand(UseOpIdx);
- if (!MO.isReg() || !MO.isUse() || MO.getReg() == 0)
- return false;
- // Find the flag operand corresponding to UseOpIdx
- int FlagIdx = findInlineAsmFlagIdx(UseOpIdx);
- if (FlagIdx < 0)
- return false;
+ // Now deal with inline asm by parsing the operand group descriptor flags.
+ // Find the beginning of each operand group.
+ SmallVector<unsigned, 8> GroupIdx;
+ unsigned OpIdxGroup = ~0u;
+ unsigned NumOps;
+ for (unsigned i = InlineAsm::MIOp_FirstOperand, e = getNumOperands(); i < e;
+ i += NumOps) {
+ const MachineOperand &FlagMO = getOperand(i);
+ assert(FlagMO.isImm() && "Invalid tied operand on inline asm");
+ unsigned CurGroup = GroupIdx.size();
+ GroupIdx.push_back(i);
+ NumOps = 1 + InlineAsm::getNumOperandRegisters(FlagMO.getImm());
+ // OpIdx belongs to this operand group.
+ if (OpIdx > i && OpIdx < i + NumOps)
+ OpIdxGroup = CurGroup;
+ unsigned TiedGroup;
+ if (!InlineAsm::isUseOperandTiedToDef(FlagMO.getImm(), TiedGroup))
+ continue;
+ // Operands in this group are tied to operands in TiedGroup which must be
+ // earlier. Find the number of operands between the two groups.
+ unsigned Delta = i - GroupIdx[TiedGroup];
- const MachineOperand &UFMO = getOperand(FlagIdx);
- unsigned DefNo;
- if (InlineAsm::isUseOperandTiedToDef(UFMO.getImm(), DefNo)) {
- if (!DefOpIdx)
- return true;
+ // OpIdx is a use tied to TiedGroup.
+ if (OpIdxGroup == CurGroup)
+ return OpIdx - Delta;
- unsigned DefIdx = InlineAsm::MIOp_FirstOperand;
- // Remember to adjust the index. First operand is asm string, second is
- // the HasSideEffects and AlignStack bits, 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;
+ // OpIdx is a def tied to this use group.
+ if (OpIdxGroup == TiedGroup)
+ return OpIdx + Delta;
}
-
- const MCInstrDesc &MCID = getDesc();
- if (UseOpIdx >= MCID.getNumOperands())
- return false;
- const MachineOperand &MO = getOperand(UseOpIdx);
- if (!MO.isReg() || !MO.isUse())
- return false;
- int DefIdx = MCID.getOperandConstraint(UseOpIdx, MCOI::TIED_TO);
- if (DefIdx == -1)
- return false;
- if (DefOpIdx)
- *DefOpIdx = (unsigned)DefIdx;
- return true;
+ llvm_unreachable("Invalid tied operand on inline asm");
}
/// clearKillInfo - Clears kill flags on all operands.
// Ignore stuff that we obviously can't move.
//
// Treat volatile loads as stores. This is not strictly necessary for
- // volatiles, but it is required for atomic loads. It is now allowed to move
+ // 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() ||
(mayLoad() && hasOrderedMemoryRef())) {
}
void MachineInstr::dump() const {
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dbgs() << " " << *this;
+#endif
}
static void printDebugLoc(DebugLoc DL, const MachineFunction *MF,
OS << " [sideeffect]";
if (ExtraInfo & InlineAsm::Extra_IsAlignStack)
OS << " [alignstack]";
+ if (getInlineAsmDialect() == InlineAsm::AD_ATT)
+ OS << " [attdialect]";
+ if (getInlineAsmDialect() == InlineAsm::AD_Intel)
+ OS << " [inteldialect]";
StartOp = AsmDescOp = InlineAsm::MIOp_FirstOperand;
FirstOp = false;