#ifndef LLVM_CODEGEN_MACHINEINSTR_H
#define LLVM_CODEGEN_MACHINEINSTR_H
-#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/MC/MCInstrDesc.h"
-#include "llvm/Target/TargetOpcodes.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/InlineAsm.h"
+#include "llvm/MC/MCInstrDesc.h"
#include "llvm/Support/DebugLoc.h"
+#include "llvm/Target/TargetOpcodes.h"
#include <vector>
namespace llvm {
NoFlags = 0,
FrameSetup = 1 << 0, // Instruction is used as a part of
// function frame setup code.
- InsideBundle = 1 << 1 // Instruction is inside a bundle (not
- // the first MI in a bundle)
+ BundledPred = 1 << 1, // Instruction has bundled predecessors.
+ BundledSucc = 1 << 2 // Instruction has bundled successors.
};
private:
const MCInstrDesc *MCID; // Instruction descriptor.
// anything other than to convey comment
// information to AsmPrinter.
+ uint16_t NumMemRefs; // information on memory references
+ mmo_iterator MemRefs;
+
std::vector<MachineOperand> Operands; // the operands
- mmo_iterator MemRefs; // information on memory references
- mmo_iterator MemRefsEnd;
MachineBasicBlock *Parent; // Pointer to the owning basic block.
DebugLoc debugLoc; // Source line information.
- MachineInstr(const MachineInstr&); // DO NOT IMPLEMENT
- void operator=(const MachineInstr&); // DO NOT IMPLEMENT
+ MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION;
+ void operator=(const MachineInstr&) LLVM_DELETED_FUNCTION;
// Intrusive list support
friend struct ilist_traits<MachineInstr>;
/// MachineInstr in the given MachineFunction.
MachineInstr(MachineFunction &, const MachineInstr &);
- /// MachineInstr ctor - This constructor creates a dummy MachineInstr with
- /// MCID NULL and no operands.
- MachineInstr();
-
- // The next two constructors have DebugLoc and non-DebugLoc versions;
- // over time, the non-DebugLoc versions should be phased out and eventually
- // removed.
-
- /// MachineInstr ctor - This constructor creates a MachineInstr and adds the
- /// implicit operands. It reserves space for the number of operands specified
- /// by the MCInstrDesc. The version with a DebugLoc should be preferred.
- explicit MachineInstr(const MCInstrDesc &MCID, bool NoImp = false);
-
- /// 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. The version with a DebugLoc should be preferred.
- MachineInstr(MachineBasicBlock *MBB, const MCInstrDesc &MCID);
-
/// MachineInstr ctor - This constructor create a MachineInstr and add the
/// implicit operands. It reserves space for number of operands specified by
/// MCInstrDesc. An explicit DebugLoc is supplied.
- explicit MachineInstr(const MCInstrDesc &MCID, const DebugLoc dl,
- bool NoImp = false);
-
- /// 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(MachineBasicBlock *MBB, const DebugLoc dl,
- const MCInstrDesc &MCID);
+ MachineInstr(const MCInstrDesc &MCID, const DebugLoc dl, bool NoImp = false);
~MachineInstr();
Flags = flags;
}
+ /// clearFlag - Clear a MI flag.
+ void clearFlag(MIFlag Flag) {
+ Flags &= ~((uint8_t)Flag);
+ }
+
/// isInsideBundle - Return true if MI is in a bundle (but not the first MI
/// in a bundle).
///
/// ----------------
/// |
/// ----------------
- /// | MI * |
+ /// | MI * |
/// ----------------
/// |
/// ----------------
- /// | MI * |
+ /// | MI * |
/// ----------------
/// In this case, the first MI starts a bundle but is not inside a bundle, the
/// next 2 MIs are considered "inside" the bundle.
/// ----------------
/// |
/// ----------------
- /// | MI * |
+ /// | MI * |
/// ----------------
/// |
/// ----------------
- /// | MI * |
+ /// | MI * |
/// ----------------
/// The first instruction has the special opcode "BUNDLE". It's not "inside"
/// a bundle, but the next three MIs are.
bool isInsideBundle() const {
- return getFlag(InsideBundle);
+ return getFlag(BundledPred);
}
+ /// setIsInsideBundle - Set InsideBundle bit.
+ ///
+ void setIsInsideBundle(bool Val = true) {
+ if (Val)
+ setFlag(BundledPred);
+ else
+ clearFlag(BundledPred);
+ }
+
+ /// isBundled - Return true if this instruction part of a bundle. This is true
+ /// if either itself or its following instruction is marked "InsideBundle".
+ bool isBundled() const;
+
+ /// Return true if this instruction is part of a bundle, and it is not the
+ /// first instruction in the bundle.
+ bool isBundledWithPred() const { return getFlag(BundledPred); }
+
+ /// Return true if this instruction is part of a bundle, and it is not the
+ /// last instruction in the bundle.
+ bool isBundledWithSucc() const { return getFlag(BundledSucc); }
+
+ /// Bundle this instruction with its predecessor. This can be an unbundled
+ /// instruction, or it can be the first instruction in a bundle.
+ void bundleWithPred();
+
+ /// Bundle this instruction with its successor. This can be an unbundled
+ /// instruction, or it can be the last instruction in a bundle.
+ void bundleWithSucc();
+
+ /// Break bundle above this instruction.
+ void unbundleFromPred();
+
+ /// Break bundle below this instruction.
+ void unbundleFromSucc();
+
/// getDebugLoc - Returns the debug location id of this MachineInstr.
///
DebugLoc getDebugLoc() const { return debugLoc; }
/// Access to memory operands of the instruction
mmo_iterator memoperands_begin() const { return MemRefs; }
- mmo_iterator memoperands_end() const { return MemRefsEnd; }
- bool memoperands_empty() const { return MemRefsEnd == MemRefs; }
+ mmo_iterator memoperands_end() const { return MemRefs + NumMemRefs; }
+ bool memoperands_empty() const { return NumMemRefs == 0; }
/// hasOneMemOperand - Return true if this instruction has exactly one
/// MachineMemOperand.
bool hasOneMemOperand() const {
- return MemRefsEnd - MemRefs == 1;
+ return NumMemRefs == 1;
}
/// API for querying MachineInstr properties. They are the same as MCInstrDesc
/// queries but they are bundle aware.
+ enum QueryType {
+ IgnoreBundle, // Ignore bundles
+ AnyInBundle, // Return true if any instruction in bundle has property
+ AllInBundle // Return true if all instructions in bundle have property
+ };
+
/// hasProperty - Return true if the instruction (or in the case of a bundle,
/// the instructions inside the bundle) has the specified property.
/// The first argument is the property being queried.
/// The second argument indicates whether the query should look inside
/// instruction bundles.
- /// If the third argument is true, than the query can return true when *any*
- /// of the bundled instructions has the queried property. If it's false, then
- /// this can return true iff *all* of the instructions have the property.
- bool hasProperty(unsigned Flag,
- bool PeekInBundle = true, bool IsOr = true) const;
+ bool hasProperty(unsigned MCFlag, QueryType Type = AnyInBundle) const {
+ // Inline the fast path.
+ if (Type == IgnoreBundle || !isBundle())
+ return getDesc().getFlags() & (1 << MCFlag);
+
+ // If we have a bundle, take the slow path.
+ return hasPropertyInBundle(1 << MCFlag, Type);
+ }
/// isVariadic - Return true if this instruction can have a variable number of
/// operands. In this case, the variable operands will be after the normal
/// operands but before the implicit definitions and uses (if any are
/// present).
- bool isVariadic() const {
- return hasProperty(MCID::Variadic, false);
+ bool isVariadic(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Variadic, Type);
}
/// hasOptionalDef - Set if this instruction has an optional definition, e.g.
/// ARM instructions which can set condition code if 's' bit is set.
- bool hasOptionalDef() const {
- return hasProperty(MCID::HasOptionalDef, false);
+ bool hasOptionalDef(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::HasOptionalDef, Type);
}
/// isPseudo - Return true if this is a pseudo instruction that doesn't
/// correspond to a real machine instruction.
///
- bool isPseudo() const {
- return hasProperty(MCID::Pseudo, false);
+ bool isPseudo(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Pseudo, Type);
}
- bool isReturn() const {
- return hasProperty(MCID::Return);
+ bool isReturn(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Return, Type);
}
- bool isCall() const {
- return hasProperty(MCID::Call);
+ bool isCall(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Call, Type);
}
/// isBarrier - Returns true if the specified instruction stops control flow
/// from executing the instruction immediately following it. Examples include
/// unconditional branches and return instructions.
- bool isBarrier() const {
- return hasProperty(MCID::Barrier);
+ bool isBarrier(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Barrier, Type);
}
/// isTerminator - Returns true if this instruction part of the terminator for
///
/// Various passes use this to insert code into the bottom of a basic block,
/// but before control flow occurs.
- bool isTerminator() const {
- return hasProperty(MCID::Terminator);
+ bool isTerminator(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Terminator, Type);
}
/// isBranch - Returns true if this is a conditional, unconditional, or
/// indirect branch. Predicates below can be used to discriminate between
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
/// get more information.
- bool isBranch() const {
- return hasProperty(MCID::Branch);
+ bool isBranch(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::Branch, Type);
}
/// isIndirectBranch - Return true if this is an indirect branch, such as a
/// branch through a register.
- bool isIndirectBranch() const {
- return hasProperty(MCID::IndirectBranch);
+ bool isIndirectBranch(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::IndirectBranch, Type);
}
/// isConditionalBranch - Return true if this is a branch which may fall
/// through to the next instruction or may transfer control flow to some other
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
/// information about this branch.
- bool isConditionalBranch() const {
- return isBranch() & !isBarrier() & !isIndirectBranch();
+ bool isConditionalBranch(QueryType Type = AnyInBundle) const {
+ return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type);
}
/// isUnconditionalBranch - Return true if this is a branch which always
/// transfers control flow to some other block. The
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
/// about this branch.
- bool isUnconditionalBranch() const {
- return isBranch() & isBarrier() & !isIndirectBranch();
+ bool isUnconditionalBranch(QueryType Type = AnyInBundle) const {
+ return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type);
}
// isPredicable - Return true if this instruction has a predicate operand that
// controls execution. It may be set to 'always', or may be set to other
/// values. There are various methods in TargetInstrInfo that can be used to
/// control and modify the predicate in this instruction.
- bool isPredicable() const {
+ bool isPredicable(QueryType Type = AllInBundle) const {
// If it's a bundle than all bundled instructions must be predicable for this
// to return true.
- return hasProperty(MCID::Predicable, true, false);
+ return hasProperty(MCID::Predicable, Type);
}
/// isCompare - Return true if this instruction is a comparison.
- bool isCompare() const {
- return hasProperty(MCID::Compare, false);
+ bool isCompare(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Compare, Type);
}
/// isMoveImmediate - Return true if this instruction is a move immediate
/// (including conditional moves) instruction.
- bool isMoveImmediate() const {
- return hasProperty(MCID::MoveImm, false);
+ bool isMoveImmediate(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::MoveImm, Type);
}
/// isBitcast - Return true if this instruction is a bitcast instruction.
///
- bool isBitcast() const {
- return hasProperty(MCID::Bitcast, false);
+ bool isBitcast(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Bitcast, Type);
+ }
+
+ /// isSelect - Return true if this instruction is a select instruction.
+ ///
+ bool isSelect(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Select, Type);
}
/// isNotDuplicable - Return true if this instruction cannot be safely
/// duplicated. For example, if the instruction has a unique labels attached
/// to it, duplicating it would cause multiple definition errors.
- bool isNotDuplicable() const {
- return hasProperty(MCID::NotDuplicable);
+ bool isNotDuplicable(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::NotDuplicable, Type);
}
/// hasDelaySlot - Returns true if the specified instruction has a delay slot
/// which must be filled by the code generator.
- bool hasDelaySlot() const {
- return hasProperty(MCID::DelaySlot);
+ bool hasDelaySlot(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::DelaySlot, Type);
}
/// canFoldAsLoad - Return true for instructions that can be folded as
/// on x86, to allow them to be folded when it is beneficial.
/// This should only be set on instructions that return a value in their
/// only virtual register definition.
- bool canFoldAsLoad() const {
- return hasProperty(MCID::FoldableAsLoad, false);
+ bool canFoldAsLoad(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::FoldableAsLoad, Type);
}
//===--------------------------------------------------------------------===//
/// mayLoad - Return true if this instruction could possibly read memory.
/// Instructions with this flag set are not necessarily simple load
/// instructions, they may load a value and modify it, for example.
- bool mayLoad() const {
- return hasProperty(MCID::MayLoad);
+ bool mayLoad(QueryType Type = AnyInBundle) const {
+ if (isInlineAsm()) {
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_MayLoad)
+ return true;
+ }
+ return hasProperty(MCID::MayLoad, Type);
}
/// Instructions with this flag set are not necessarily simple store
/// instructions, they may store a modified value based on their operands, or
/// may not actually modify anything, for example.
- bool mayStore() const {
- return hasProperty(MCID::MayStore);
+ bool mayStore(QueryType Type = AnyInBundle) const {
+ if (isInlineAsm()) {
+ unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
+ if (ExtraInfo & InlineAsm::Extra_MayStore)
+ return true;
+ }
+ return hasProperty(MCID::MayStore, Type);
}
//===--------------------------------------------------------------------===//
/// sometimes. In these cases, the call to commuteInstruction will fail.
/// Also note that some instructions require non-trivial modification to
/// commute them.
- bool isCommutable() const {
- return hasProperty(MCID::Commutable, false);
+ bool isCommutable(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::Commutable, Type);
}
/// isConvertibleTo3Addr - Return true if this is a 2-address instruction
/// is allowed to fail if the transformation isn't valid for this specific
/// instruction (e.g. shl reg, 4 on x86).
///
- bool isConvertibleTo3Addr() const {
- return hasProperty(MCID::ConvertibleTo3Addr, false);
+ bool isConvertibleTo3Addr(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::ConvertibleTo3Addr, Type);
}
/// usesCustomInsertionHook - Return true if this instruction requires
///
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
/// is used to insert this into the MachineBasicBlock.
- bool usesCustomInsertionHook() const {
- return hasProperty(MCID::UsesCustomInserter, false);
+ bool usesCustomInsertionHook(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::UsesCustomInserter, Type);
}
/// hasPostISelHook - Return true if this instruction requires *adjustment*
/// after instruction selection by calling a target hook. For example, this
/// can be used to fill in ARM 's' optional operand depending on whether
/// the conditional flag register is used.
- bool hasPostISelHook() const {
- return hasProperty(MCID::HasPostISelHook, false);
+ bool hasPostISelHook(QueryType Type = IgnoreBundle) const {
+ return hasProperty(MCID::HasPostISelHook, Type);
}
/// isRematerializable - Returns true if this instruction is a candidate for
/// remat. This flag is deprecated, please don't use it anymore. If this
/// flag is set, the isReallyTriviallyReMaterializable() method is called to
/// verify the instruction is really rematable.
- bool isRematerializable() const {
+ bool isRematerializable(QueryType Type = AllInBundle) const {
// It's only possible to re-mat a bundle if all bundled instructions are
// re-materializable.
- return hasProperty(MCID::Rematerializable, true, false);
+ return hasProperty(MCID::Rematerializable, Type);
}
/// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
/// where we would like to remat or hoist the instruction, but not if it costs
/// more than moving the instruction into the appropriate register. Note, we
/// are not marking copies from and to the same register class with this flag.
- bool isAsCheapAsAMove() const {
+ bool isAsCheapAsAMove(QueryType Type = AllInBundle) const {
// Only returns true for a bundle if all bundled instructions are cheap.
// FIXME: This probably requires a target hook.
- return hasProperty(MCID::CheapAsAMove, true, true);
+ return hasProperty(MCID::CheapAsAMove, Type);
}
/// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
/// even / odd pair, ARM::STM registers have to be in ascending order.
/// Post-register allocation passes should not attempt to change allocations
/// for sources of instructions with this flag.
- bool hasExtraSrcRegAllocReq() const {
- return hasProperty(MCID::ExtraSrcRegAllocReq);
+ bool hasExtraSrcRegAllocReq(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::ExtraSrcRegAllocReq, Type);
}
/// hasExtraDefRegAllocReq - Returns true if this instruction def operands
/// even / odd pair, ARM::LDM registers have to be in ascending order.
/// Post-register allocation passes should not attempt to change allocations
/// for definitions of instructions with this flag.
- bool hasExtraDefRegAllocReq() const {
- return hasProperty(MCID::ExtraDefRegAllocReq);
+ bool hasExtraDefRegAllocReq(QueryType Type = AnyInBundle) const {
+ return hasProperty(MCID::ExtraDefRegAllocReq, Type);
}
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
bool isStackAligningInlineAsm() const;
+ InlineAsm::AsmDialect getInlineAsmDialect() const;
bool isInsertSubreg() const {
return getOpcode() == TargetOpcode::INSERT_SUBREG;
}
bool isRegSequence() const {
return getOpcode() == TargetOpcode::REG_SEQUENCE;
}
+ bool isBundle() const {
+ return getOpcode() == TargetOpcode::BUNDLE;
+ }
bool isCopy() const {
return getOpcode() == TargetOpcode::COPY;
}
getOperand(0).getSubReg() == getOperand(1).getSubReg();
}
+ /// isTransient - Return true if this is a transient instruction that is
+ /// either very likely to be eliminated during register allocation (such as
+ /// copy-like instructions), or if this instruction doesn't have an
+ /// execution-time cost.
+ bool isTransient() const {
+ switch(getOpcode()) {
+ default: return false;
+ // Copy-like instructions are usually eliminated during register allocation.
+ case TargetOpcode::PHI:
+ case TargetOpcode::COPY:
+ case TargetOpcode::INSERT_SUBREG:
+ case TargetOpcode::SUBREG_TO_REG:
+ case TargetOpcode::REG_SEQUENCE:
+ // Pseudo-instructions that don't produce any real output.
+ case TargetOpcode::IMPLICIT_DEF:
+ case TargetOpcode::KILL:
+ case TargetOpcode::PROLOG_LABEL:
+ case TargetOpcode::EH_LABEL:
+ case TargetOpcode::GC_LABEL:
+ case TargetOpcode::DBG_VALUE:
+ return true;
+ }
+ }
+
+ /// getBundleSize - Return the number of instructions inside the MI bundle.
+ unsigned getBundleSize() const;
+
/// readsRegister - Return true if the MachineInstr reads the specified
/// register. If TargetRegisterInfo is passed, then it also checks if there
/// is a read of a super-register.
/// that are not dead are skipped. If Overlap is true, then it also looks for
/// defs that merely overlap the specified register. If TargetRegisterInfo is
/// non-null, then it also checks if there is a def of a super-register.
+ /// This may also return a register mask operand when Overlap is true.
int findRegisterDefOperandIdx(unsigned Reg,
bool isDead = false, bool Overlap = false,
const TargetRegisterInfo *TRI = NULL) const;
const TargetInstrInfo *TII,
const TargetRegisterInfo *TRI) const;
+ /// tieOperands - Add a tie between the register operands at DefIdx and
+ /// UseIdx. The tie will cause the register allocator to ensure that the two
+ /// operands are assigned the same physical register.
+ ///
+ /// Tied operands are managed automatically for explicit operands in the
+ /// MCInstrDesc. This method is for exceptional cases like inline asm.
+ void tieOperands(unsigned DefIdx, unsigned UseIdx);
+
+ /// findTiedOperandIdx - 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 findTiedOperandIdx(unsigned OpIdx) const;
+
/// 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 isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx = 0) const;
+ /// first tied use operand index by reference if UseOpIdx is not null.
+ bool isRegTiedToUseOperand(unsigned DefOpIdx, unsigned *UseOpIdx = 0) const {
+ const MachineOperand &MO = getOperand(DefOpIdx);
+ if (!MO.isReg() || !MO.isDef() || !MO.isTied())
+ return false;
+ if (UseOpIdx)
+ *UseOpIdx = findTiedOperandIdx(DefOpIdx);
+ return true;
+ }
/// isRegTiedToDefOperand - Return true if the use operand of the specified
/// index is tied to an def operand. It also returns the def operand index by
/// reference if DefOpIdx is not null.
- bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const;
+ bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const {
+ const MachineOperand &MO = getOperand(UseOpIdx);
+ if (!MO.isReg() || !MO.isUse() || !MO.isTied())
+ return false;
+ if (DefOpIdx)
+ *DefOpIdx = findTiedOperandIdx(UseOpIdx);
+ return true;
+ }
/// clearKillInfo - Clears kill flags on all operands.
///
const TargetRegisterInfo *RegInfo,
bool AddIfNotFound = false);
+ /// clearRegisterKills - Clear all kill flags affecting Reg. If RegInfo is
+ /// provided, this includes super-register kills.
+ void clearRegisterKills(unsigned Reg, const TargetRegisterInfo *RegInfo);
+
/// addRegisterDead - We have determined MI defined a register without a use.
/// Look for the operand that defines it and mark it as IsDead. If
/// AddIfNotFound is true, add a implicit operand if it's not found. Returns
/// setPhysRegsDeadExcept - Mark every physreg used by this instruction as
/// dead except those in the UsedRegs list.
- void setPhysRegsDeadExcept(const SmallVectorImpl<unsigned> &UsedRegs,
+ ///
+ /// On instructions with register mask operands, also add implicit-def
+ /// operands for all registers in UsedRegs.
+ void setPhysRegsDeadExcept(ArrayRef<unsigned> UsedRegs,
const TargetRegisterInfo &TRI);
/// isSafeToMove - Return true if it is safe to move this instruction. If
bool isSafeToReMat(const TargetInstrInfo *TII, AliasAnalysis *AA,
unsigned DstReg) const;
- /// hasVolatileMemoryRef - Return true if this instruction may have a
- /// volatile memory reference, or if the information describing the
- /// memory reference is not available. Return false if it is known to
- /// have no volatile memory references.
- bool hasVolatileMemoryRef() const;
+ /// hasOrderedMemoryRef - Return true if this instruction may have an ordered
+ /// or volatile memory reference, or if the information describing the memory
+ /// reference is not available. Return false if it is known to have no
+ /// ordered or volatile memory references.
+ bool hasOrderedMemoryRef() const;
/// isInvariantLoad - Return true if this instruction is loading from a
/// location whose value is invariant across the function. For example,
/// list. This does not transfer ownership.
void setMemRefs(mmo_iterator NewMemRefs, mmo_iterator NewMemRefsEnd) {
MemRefs = NewMemRefs;
- MemRefsEnd = NewMemRefsEnd;
+ NumMemRefs = NewMemRefsEnd - NewMemRefs;
}
private:
/// return null.
MachineRegisterInfo *getRegInfo();
+ /// untieRegOperand - Break any tie involving OpIdx.
+ void untieRegOperand(unsigned OpIdx) {
+ MachineOperand &MO = getOperand(OpIdx);
+ if (MO.isReg() && MO.isTied()) {
+ getOperand(findTiedOperandIdx(OpIdx)).TiedTo = 0;
+ MO.TiedTo = 0;
+ }
+ }
+
/// addImplicitDefUseOperands - Add all implicit def and use operands to
/// this instruction.
void addImplicitDefUseOperands();
/// RemoveRegOperandsFromUseLists - Unlink all of the register operands in
/// this instruction from their respective use lists. This requires that the
/// operands already be on their use lists.
- void RemoveRegOperandsFromUseLists();
+ void RemoveRegOperandsFromUseLists(MachineRegisterInfo&);
/// AddRegOperandsToUseLists - Add all of the register operands in
/// this instruction from their respective use lists. This requires that the
/// operands not be on their use lists yet.
- void AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo);
+ void AddRegOperandsToUseLists(MachineRegisterInfo&);
+
+ /// hasPropertyInBundle - Slow path for hasProperty when we're dealing with a
+ /// bundle.
+ bool hasPropertyInBundle(unsigned Mask, QueryType Type) const;
};
/// MachineInstrExpressionTrait - Special DenseMapInfo traits to compare