mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-13 14:47:00 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146168 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e9c1e07c5f
commit
43d5d4ca1c
@ -277,6 +277,12 @@ public:
|
||||
/// 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.
|
||||
@ -285,43 +291,42 @@ public:
|
||||
/// 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 Flag, QueryType Type = AnyInBundle) const;
|
||||
|
||||
/// 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
|
||||
@ -330,78 +335,78 @@ public:
|
||||
///
|
||||
/// 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);
|
||||
}
|
||||
|
||||
/// 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
|
||||
@ -412,8 +417,8 @@ public:
|
||||
/// 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);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -423,8 +428,8 @@ public:
|
||||
/// 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 {
|
||||
return hasProperty(MCID::MayLoad, Type);
|
||||
}
|
||||
|
||||
|
||||
@ -432,8 +437,8 @@ public:
|
||||
/// 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 {
|
||||
return hasProperty(MCID::MayStore, Type);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -450,8 +455,8 @@ public:
|
||||
/// 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
|
||||
@ -468,8 +473,8 @@ public:
|
||||
/// 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
|
||||
@ -480,26 +485,26 @@ public:
|
||||
///
|
||||
/// 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
|
||||
@ -508,10 +513,10 @@ public:
|
||||
/// 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
|
||||
@ -520,8 +525,8 @@ public:
|
||||
/// 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
|
||||
@ -530,8 +535,8 @@ public:
|
||||
/// 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -749,24 +749,24 @@ void MachineInstr::addMemOperand(MachineFunction &MF,
|
||||
}
|
||||
|
||||
bool
|
||||
MachineInstr::hasProperty(unsigned MCFlag, bool PeekInBundle, bool IsOr) const {
|
||||
if (!PeekInBundle || getOpcode() != TargetOpcode::BUNDLE)
|
||||
MachineInstr::hasProperty(unsigned MCFlag, QueryType Type) const {
|
||||
if (Type == IgnoreBundle || getOpcode() != TargetOpcode::BUNDLE)
|
||||
return getDesc().getFlags() & (1 << MCFlag);
|
||||
|
||||
const MachineBasicBlock *MBB = getParent();
|
||||
MachineBasicBlock::const_insn_iterator MII = *this; ++MII;
|
||||
while (MII != MBB->end() && MII->isInsideBundle()) {
|
||||
if (MII->getDesc().getFlags() & (1 << MCFlag)) {
|
||||
if (IsOr)
|
||||
if (Type == AnyInBundle)
|
||||
return true;
|
||||
} else {
|
||||
if (!IsOr)
|
||||
if (Type == AllInBundle)
|
||||
return false;
|
||||
}
|
||||
++MII;
|
||||
}
|
||||
|
||||
return !IsOr;
|
||||
return Type == AllInBundle;
|
||||
}
|
||||
|
||||
bool MachineInstr::isIdenticalTo(const MachineInstr *Other,
|
||||
|
Loading…
Reference in New Issue
Block a user