forked from OSchip/llvm-project
Make MachineInstr instruction property queries more flexible. This change all
clients to decide whether to look inside bundled instructions and whether the query should return true if any / all bundled instructions have the queried property. llvm-svn: 146168
This commit is contained in:
parent
3294538546
commit
cdf89fdeaf
|
@ -277,6 +277,12 @@ public:
|
||||||
/// API for querying MachineInstr properties. They are the same as MCInstrDesc
|
/// API for querying MachineInstr properties. They are the same as MCInstrDesc
|
||||||
/// queries but they are bundle aware.
|
/// 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,
|
/// hasProperty - Return true if the instruction (or in the case of a bundle,
|
||||||
/// the instructions inside the bundle) has the specified property.
|
/// the instructions inside the bundle) has the specified property.
|
||||||
/// The first argument is the property being queried.
|
/// The first argument is the property being queried.
|
||||||
|
@ -285,43 +291,42 @@ public:
|
||||||
/// If the third argument is true, than the query can return true when *any*
|
/// 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
|
/// 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.
|
/// this can return true iff *all* of the instructions have the property.
|
||||||
bool hasProperty(unsigned Flag,
|
bool hasProperty(unsigned Flag, QueryType Type = AnyInBundle) const;
|
||||||
bool PeekInBundle = true, bool IsOr = true) const;
|
|
||||||
|
|
||||||
/// isVariadic - Return true if this instruction can have a variable number of
|
/// 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. In this case, the variable operands will be after the normal
|
||||||
/// operands but before the implicit definitions and uses (if any are
|
/// operands but before the implicit definitions and uses (if any are
|
||||||
/// present).
|
/// present).
|
||||||
bool isVariadic() const {
|
bool isVariadic(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::Variadic, false);
|
return hasProperty(MCID::Variadic, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasOptionalDef - Set if this instruction has an optional definition, e.g.
|
/// hasOptionalDef - Set if this instruction has an optional definition, e.g.
|
||||||
/// ARM instructions which can set condition code if 's' bit is set.
|
/// ARM instructions which can set condition code if 's' bit is set.
|
||||||
bool hasOptionalDef() const {
|
bool hasOptionalDef(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::HasOptionalDef, false);
|
return hasProperty(MCID::HasOptionalDef, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isPseudo - Return true if this is a pseudo instruction that doesn't
|
/// isPseudo - Return true if this is a pseudo instruction that doesn't
|
||||||
/// correspond to a real machine instruction.
|
/// correspond to a real machine instruction.
|
||||||
///
|
///
|
||||||
bool isPseudo() const {
|
bool isPseudo(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::Pseudo, false);
|
return hasProperty(MCID::Pseudo, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isReturn() const {
|
bool isReturn(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::Return);
|
return hasProperty(MCID::Return, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isCall() const {
|
bool isCall(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::Call);
|
return hasProperty(MCID::Call, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isBarrier - Returns true if the specified instruction stops control flow
|
/// isBarrier - Returns true if the specified instruction stops control flow
|
||||||
/// from executing the instruction immediately following it. Examples include
|
/// from executing the instruction immediately following it. Examples include
|
||||||
/// unconditional branches and return instructions.
|
/// unconditional branches and return instructions.
|
||||||
bool isBarrier() const {
|
bool isBarrier(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::Barrier);
|
return hasProperty(MCID::Barrier, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isTerminator - Returns true if this instruction part of the terminator for
|
/// isTerminator - Returns true if this instruction part of the terminator for
|
||||||
|
@ -330,78 +335,78 @@ public:
|
||||||
///
|
///
|
||||||
/// Various passes use this to insert code into the bottom of a basic block,
|
/// Various passes use this to insert code into the bottom of a basic block,
|
||||||
/// but before control flow occurs.
|
/// but before control flow occurs.
|
||||||
bool isTerminator() const {
|
bool isTerminator(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::Terminator);
|
return hasProperty(MCID::Terminator, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isBranch - Returns true if this is a conditional, unconditional, or
|
/// isBranch - Returns true if this is a conditional, unconditional, or
|
||||||
/// indirect branch. Predicates below can be used to discriminate between
|
/// indirect branch. Predicates below can be used to discriminate between
|
||||||
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
|
/// these cases, and the TargetInstrInfo::AnalyzeBranch method can be used to
|
||||||
/// get more information.
|
/// get more information.
|
||||||
bool isBranch() const {
|
bool isBranch(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::Branch);
|
return hasProperty(MCID::Branch, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isIndirectBranch - Return true if this is an indirect branch, such as a
|
/// isIndirectBranch - Return true if this is an indirect branch, such as a
|
||||||
/// branch through a register.
|
/// branch through a register.
|
||||||
bool isIndirectBranch() const {
|
bool isIndirectBranch(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::IndirectBranch);
|
return hasProperty(MCID::IndirectBranch, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isConditionalBranch - Return true if this is a branch which may fall
|
/// isConditionalBranch - Return true if this is a branch which may fall
|
||||||
/// through to the next instruction or may transfer control flow to some other
|
/// through to the next instruction or may transfer control flow to some other
|
||||||
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
|
/// block. The TargetInstrInfo::AnalyzeBranch method can be used to get more
|
||||||
/// information about this branch.
|
/// information about this branch.
|
||||||
bool isConditionalBranch() const {
|
bool isConditionalBranch(QueryType Type = AnyInBundle) const {
|
||||||
return isBranch() & !isBarrier() & !isIndirectBranch();
|
return isBranch(Type) & !isBarrier(Type) & !isIndirectBranch(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isUnconditionalBranch - Return true if this is a branch which always
|
/// isUnconditionalBranch - Return true if this is a branch which always
|
||||||
/// transfers control flow to some other block. The
|
/// transfers control flow to some other block. The
|
||||||
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
|
/// TargetInstrInfo::AnalyzeBranch method can be used to get more information
|
||||||
/// about this branch.
|
/// about this branch.
|
||||||
bool isUnconditionalBranch() const {
|
bool isUnconditionalBranch(QueryType Type = AnyInBundle) const {
|
||||||
return isBranch() & isBarrier() & !isIndirectBranch();
|
return isBranch(Type) & isBarrier(Type) & !isIndirectBranch(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// isPredicable - Return true if this instruction has a predicate operand that
|
// 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
|
// 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
|
/// values. There are various methods in TargetInstrInfo that can be used to
|
||||||
/// control and modify the predicate in this instruction.
|
/// 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
|
// If it's a bundle than all bundled instructions must be predicable for this
|
||||||
// to return true.
|
// to return true.
|
||||||
return hasProperty(MCID::Predicable, true, false);
|
return hasProperty(MCID::Predicable, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isCompare - Return true if this instruction is a comparison.
|
/// isCompare - Return true if this instruction is a comparison.
|
||||||
bool isCompare() const {
|
bool isCompare(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::Compare, false);
|
return hasProperty(MCID::Compare, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isMoveImmediate - Return true if this instruction is a move immediate
|
/// isMoveImmediate - Return true if this instruction is a move immediate
|
||||||
/// (including conditional moves) instruction.
|
/// (including conditional moves) instruction.
|
||||||
bool isMoveImmediate() const {
|
bool isMoveImmediate(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::MoveImm, false);
|
return hasProperty(MCID::MoveImm, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isBitcast - Return true if this instruction is a bitcast instruction.
|
/// isBitcast - Return true if this instruction is a bitcast instruction.
|
||||||
///
|
///
|
||||||
bool isBitcast() const {
|
bool isBitcast(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::Bitcast, false);
|
return hasProperty(MCID::Bitcast, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isNotDuplicable - Return true if this instruction cannot be safely
|
/// isNotDuplicable - Return true if this instruction cannot be safely
|
||||||
/// duplicated. For example, if the instruction has a unique labels attached
|
/// duplicated. For example, if the instruction has a unique labels attached
|
||||||
/// to it, duplicating it would cause multiple definition errors.
|
/// to it, duplicating it would cause multiple definition errors.
|
||||||
bool isNotDuplicable() const {
|
bool isNotDuplicable(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::NotDuplicable);
|
return hasProperty(MCID::NotDuplicable, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasDelaySlot - Returns true if the specified instruction has a delay slot
|
/// hasDelaySlot - Returns true if the specified instruction has a delay slot
|
||||||
/// which must be filled by the code generator.
|
/// which must be filled by the code generator.
|
||||||
bool hasDelaySlot() const {
|
bool hasDelaySlot(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::DelaySlot);
|
return hasProperty(MCID::DelaySlot, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// canFoldAsLoad - Return true for instructions that can be folded as
|
/// canFoldAsLoad - Return true for instructions that can be folded as
|
||||||
|
@ -412,8 +417,8 @@ public:
|
||||||
/// on x86, to allow them to be folded when it is beneficial.
|
/// 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
|
/// This should only be set on instructions that return a value in their
|
||||||
/// only virtual register definition.
|
/// only virtual register definition.
|
||||||
bool canFoldAsLoad() const {
|
bool canFoldAsLoad(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::FoldableAsLoad, false);
|
return hasProperty(MCID::FoldableAsLoad, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -423,8 +428,8 @@ public:
|
||||||
/// mayLoad - Return true if this instruction could possibly read memory.
|
/// mayLoad - Return true if this instruction could possibly read memory.
|
||||||
/// Instructions with this flag set are not necessarily simple load
|
/// Instructions with this flag set are not necessarily simple load
|
||||||
/// instructions, they may load a value and modify it, for example.
|
/// instructions, they may load a value and modify it, for example.
|
||||||
bool mayLoad() const {
|
bool mayLoad(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::MayLoad);
|
return hasProperty(MCID::MayLoad, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -432,8 +437,8 @@ public:
|
||||||
/// Instructions with this flag set are not necessarily simple store
|
/// Instructions with this flag set are not necessarily simple store
|
||||||
/// instructions, they may store a modified value based on their operands, or
|
/// instructions, they may store a modified value based on their operands, or
|
||||||
/// may not actually modify anything, for example.
|
/// may not actually modify anything, for example.
|
||||||
bool mayStore() const {
|
bool mayStore(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::MayStore);
|
return hasProperty(MCID::MayStore, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
|
@ -450,8 +455,8 @@ public:
|
||||||
/// sometimes. In these cases, the call to commuteInstruction will fail.
|
/// sometimes. In these cases, the call to commuteInstruction will fail.
|
||||||
/// Also note that some instructions require non-trivial modification to
|
/// Also note that some instructions require non-trivial modification to
|
||||||
/// commute them.
|
/// commute them.
|
||||||
bool isCommutable() const {
|
bool isCommutable(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::Commutable, false);
|
return hasProperty(MCID::Commutable, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isConvertibleTo3Addr - Return true if this is a 2-address instruction
|
/// isConvertibleTo3Addr - Return true if this is a 2-address instruction
|
||||||
|
@ -468,8 +473,8 @@ public:
|
||||||
/// is allowed to fail if the transformation isn't valid for this specific
|
/// is allowed to fail if the transformation isn't valid for this specific
|
||||||
/// instruction (e.g. shl reg, 4 on x86).
|
/// instruction (e.g. shl reg, 4 on x86).
|
||||||
///
|
///
|
||||||
bool isConvertibleTo3Addr() const {
|
bool isConvertibleTo3Addr(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::ConvertibleTo3Addr, false);
|
return hasProperty(MCID::ConvertibleTo3Addr, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// usesCustomInsertionHook - Return true if this instruction requires
|
/// usesCustomInsertionHook - Return true if this instruction requires
|
||||||
|
@ -480,26 +485,26 @@ public:
|
||||||
///
|
///
|
||||||
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
|
/// If this is true, the TargetLoweringInfo::InsertAtEndOfBasicBlock method
|
||||||
/// is used to insert this into the MachineBasicBlock.
|
/// is used to insert this into the MachineBasicBlock.
|
||||||
bool usesCustomInsertionHook() const {
|
bool usesCustomInsertionHook(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::UsesCustomInserter, false);
|
return hasProperty(MCID::UsesCustomInserter, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasPostISelHook - Return true if this instruction requires *adjustment*
|
/// hasPostISelHook - Return true if this instruction requires *adjustment*
|
||||||
/// after instruction selection by calling a target hook. For example, this
|
/// after instruction selection by calling a target hook. For example, this
|
||||||
/// can be used to fill in ARM 's' optional operand depending on whether
|
/// can be used to fill in ARM 's' optional operand depending on whether
|
||||||
/// the conditional flag register is used.
|
/// the conditional flag register is used.
|
||||||
bool hasPostISelHook() const {
|
bool hasPostISelHook(QueryType Type = IgnoreBundle) const {
|
||||||
return hasProperty(MCID::HasPostISelHook, false);
|
return hasProperty(MCID::HasPostISelHook, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isRematerializable - Returns true if this instruction is a candidate for
|
/// isRematerializable - Returns true if this instruction is a candidate for
|
||||||
/// remat. This flag is deprecated, please don't use it anymore. If this
|
/// remat. This flag is deprecated, please don't use it anymore. If this
|
||||||
/// flag is set, the isReallyTriviallyReMaterializable() method is called to
|
/// flag is set, the isReallyTriviallyReMaterializable() method is called to
|
||||||
/// verify the instruction is really rematable.
|
/// 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
|
// It's only possible to re-mat a bundle if all bundled instructions are
|
||||||
// re-materializable.
|
// re-materializable.
|
||||||
return hasProperty(MCID::Rematerializable, true, false);
|
return hasProperty(MCID::Rematerializable, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
|
/// isAsCheapAsAMove - Returns true if this instruction has the same cost (or
|
||||||
|
@ -508,10 +513,10 @@ public:
|
||||||
/// where we would like to remat or hoist the instruction, but not if it costs
|
/// 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
|
/// 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.
|
/// 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.
|
// Only returns true for a bundle if all bundled instructions are cheap.
|
||||||
// FIXME: This probably requires a target hook.
|
// 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
|
/// hasExtraSrcRegAllocReq - Returns true if this instruction source operands
|
||||||
|
@ -520,8 +525,8 @@ public:
|
||||||
/// even / odd pair, ARM::STM registers have to be in ascending order.
|
/// even / odd pair, ARM::STM registers have to be in ascending order.
|
||||||
/// Post-register allocation passes should not attempt to change allocations
|
/// Post-register allocation passes should not attempt to change allocations
|
||||||
/// for sources of instructions with this flag.
|
/// for sources of instructions with this flag.
|
||||||
bool hasExtraSrcRegAllocReq() const {
|
bool hasExtraSrcRegAllocReq(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::ExtraSrcRegAllocReq);
|
return hasProperty(MCID::ExtraSrcRegAllocReq, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// hasExtraDefRegAllocReq - Returns true if this instruction def operands
|
/// hasExtraDefRegAllocReq - Returns true if this instruction def operands
|
||||||
|
@ -530,8 +535,8 @@ public:
|
||||||
/// even / odd pair, ARM::LDM registers have to be in ascending order.
|
/// even / odd pair, ARM::LDM registers have to be in ascending order.
|
||||||
/// Post-register allocation passes should not attempt to change allocations
|
/// Post-register allocation passes should not attempt to change allocations
|
||||||
/// for definitions of instructions with this flag.
|
/// for definitions of instructions with this flag.
|
||||||
bool hasExtraDefRegAllocReq() const {
|
bool hasExtraDefRegAllocReq(QueryType Type = AnyInBundle) const {
|
||||||
return hasProperty(MCID::ExtraDefRegAllocReq);
|
return hasProperty(MCID::ExtraDefRegAllocReq, Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -749,24 +749,24 @@ void MachineInstr::addMemOperand(MachineFunction &MF,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
MachineInstr::hasProperty(unsigned MCFlag, bool PeekInBundle, bool IsOr) const {
|
MachineInstr::hasProperty(unsigned MCFlag, QueryType Type) const {
|
||||||
if (!PeekInBundle || getOpcode() != TargetOpcode::BUNDLE)
|
if (Type == IgnoreBundle || getOpcode() != TargetOpcode::BUNDLE)
|
||||||
return getDesc().getFlags() & (1 << MCFlag);
|
return getDesc().getFlags() & (1 << MCFlag);
|
||||||
|
|
||||||
const MachineBasicBlock *MBB = getParent();
|
const MachineBasicBlock *MBB = getParent();
|
||||||
MachineBasicBlock::const_insn_iterator MII = *this; ++MII;
|
MachineBasicBlock::const_insn_iterator MII = *this; ++MII;
|
||||||
while (MII != MBB->end() && MII->isInsideBundle()) {
|
while (MII != MBB->end() && MII->isInsideBundle()) {
|
||||||
if (MII->getDesc().getFlags() & (1 << MCFlag)) {
|
if (MII->getDesc().getFlags() & (1 << MCFlag)) {
|
||||||
if (IsOr)
|
if (Type == AnyInBundle)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (!IsOr)
|
if (Type == AllInBundle)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
++MII;
|
++MII;
|
||||||
}
|
}
|
||||||
|
|
||||||
return !IsOr;
|
return Type == AllInBundle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MachineInstr::isIdenticalTo(const MachineInstr *Other,
|
bool MachineInstr::isIdenticalTo(const MachineInstr *Other,
|
||||||
|
|
Loading…
Reference in New Issue