aboutsummaryrefslogtreecommitdiff
path: root/include/llvm/Target/TargetInstrInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/Target/TargetInstrInfo.h')
-rw-r--r--include/llvm/Target/TargetInstrInfo.h140
1 files changed, 125 insertions, 15 deletions
diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h
index 247d694f2e47..0dc9cf70d335 100644
--- a/include/llvm/Target/TargetInstrInfo.h
+++ b/include/llvm/Target/TargetInstrInfo.h
@@ -152,6 +152,31 @@ public:
unsigned getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; }
unsigned getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; }
+ /// Returns true if the argument is a frame pseudo instruction.
+ bool isFrameInstr(const MachineInstr &I) const {
+ return I.getOpcode() == getCallFrameSetupOpcode() ||
+ I.getOpcode() == getCallFrameDestroyOpcode();
+ }
+
+ /// Returns true if the argument is a frame setup pseudo instruction.
+ bool isFrameSetup(const MachineInstr &I) const {
+ return I.getOpcode() == getCallFrameSetupOpcode();
+ }
+
+ /// Returns size of the frame associated with the given frame instruction.
+ /// For frame setup instruction this is frame that is set up space set up
+ /// after the instruction. For frame destroy instruction this is the frame
+ /// freed by the caller.
+ /// Note, in some cases a call frame (or a part of it) may be prepared prior
+ /// to the frame setup instruction. It occurs in the calls that involve
+ /// inalloca arguments. This function reports only the size of the frame part
+ /// that is set up between the frame setup and destroy pseudo instructions.
+ int64_t getFrameSize(const MachineInstr &I) const {
+ assert(isFrameInstr(I));
+ assert(I.getOperand(0).getImm() >= 0);
+ return I.getOperand(0).getImm();
+ }
+
unsigned getCatchReturnOpcode() const { return CatchRetOpcode; }
unsigned getReturnOpcode() const { return ReturnOpcode; }
@@ -1070,15 +1095,6 @@ public:
llvm_unreachable("target did not implement shouldClusterMemOps()");
}
- /// Can this target fuse the given instructions if they are scheduled
- /// adjacent. Note that you have to add:
- /// DAG.addMutation(createMacroFusionDAGMutation());
- /// to TargetPassConfig::createMachineScheduler() to have an effect.
- virtual bool shouldScheduleAdjacent(const MachineInstr &First,
- const MachineInstr &Second) const {
- llvm_unreachable("target did not implement shouldScheduleAdjacent()");
- }
-
/// Reverses the branch condition of the specified condition list,
/// returning false on success and true if it cannot be reversed.
virtual
@@ -1108,6 +1124,25 @@ public:
/// terminator instruction that has not been predicated.
virtual bool isUnpredicatedTerminator(const MachineInstr &MI) const;
+ /// Returns true if MI is an unconditional tail call.
+ virtual bool isUnconditionalTailCall(const MachineInstr &MI) const {
+ return false;
+ }
+
+ /// Returns true if the tail call can be made conditional on BranchCond.
+ virtual bool
+ canMakeTailCallConditional(SmallVectorImpl<MachineOperand> &Cond,
+ const MachineInstr &TailCall) const {
+ return false;
+ }
+
+ /// Replace the conditional branch in MBB with a conditional tail call.
+ virtual void replaceBranchWithTailCall(MachineBasicBlock &MBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ const MachineInstr &TailCall) const {
+ llvm_unreachable("Target didn't implement replaceBranchWithTailCall!");
+ }
+
/// Convert the instruction into a predicated instruction.
/// It returns true if the operation was successful.
virtual bool PredicateInstruction(MachineInstr &MI,
@@ -1132,7 +1167,7 @@ public:
/// Return true if the specified instruction can be predicated.
/// By default, this returns true for every instruction with a
/// PredicateOperand.
- virtual bool isPredicable(MachineInstr &MI) const {
+ virtual bool isPredicable(const MachineInstr &MI) const {
return MI.getDesc().isPredicable();
}
@@ -1427,10 +1462,17 @@ public:
return nullptr;
}
- // Sometimes, it is possible for the target
- // to tell, even without aliasing information, that two MIs access different
- // memory addresses. This function returns true if two MIs access different
- // memory addresses and false otherwise.
+ /// Sometimes, it is possible for the target
+ /// to tell, even without aliasing information, that two MIs access different
+ /// memory addresses. This function returns true if two MIs access different
+ /// memory addresses and false otherwise.
+ ///
+ /// Assumes any physical registers used to compute addresses have the same
+ /// value for both instructions. (This is the most useful assumption for
+ /// post-RA scheduling.)
+ ///
+ /// See also MachineInstr::mayAlias, which is implemented on top of this
+ /// function.
virtual bool
areMemAccessesTriviallyDisjoint(MachineInstr &MIa, MachineInstr &MIb,
AliasAnalysis *AA = nullptr) const {
@@ -1486,11 +1528,79 @@ public:
return None;
}
- /// Determines whether |Inst| is a tail call instruction.
+ /// Determines whether \p Inst is a tail call instruction. Override this
+ /// method on targets that do not properly set MCID::Return and MCID::Call on
+ /// tail call instructions."
virtual bool isTailCall(const MachineInstr &Inst) const {
+ return Inst.isReturn() && Inst.isCall();
+ }
+
+ /// True if the instruction is bound to the top of its basic block and no
+ /// other instructions shall be inserted before it. This can be implemented
+ /// to prevent register allocator to insert spills before such instructions.
+ virtual bool isBasicBlockPrologue(const MachineInstr &MI) const {
return false;
}
+ /// \brief Return how many instructions would be saved by outlining a
+ /// sequence containing \p SequenceSize instructions that appears
+ /// \p Occurrences times in a module.
+ virtual unsigned getOutliningBenefit(size_t SequenceSize, size_t Occurrences,
+ bool CanBeTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::getOutliningBenefit!");
+ }
+
+ /// Represents how an instruction should be mapped by the outliner.
+ /// \p Legal instructions are those which are safe to outline.
+ /// \p Illegal instructions are those which cannot be outlined.
+ /// \p Invisible instructions are instructions which can be outlined, but
+ /// shouldn't actually impact the outlining result.
+ enum MachineOutlinerInstrType {Legal, Illegal, Invisible};
+
+ /// Returns how or if \p MI should be outlined.
+ virtual MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::getOutliningType!");
+ }
+
+ /// Insert a custom epilogue for outlined functions.
+ /// This may be empty, in which case no epilogue or return statement will be
+ /// emitted.
+ virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB,
+ MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!");
+ }
+
+ /// Insert a call to an outlined function into the program.
+ /// Returns an iterator to the spot where we inserted the call. This must be
+ /// implemented by the target.
+ virtual MachineBasicBlock::iterator
+ insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator &It, MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinedCall!");
+ }
+
+ /// Insert a custom prologue for outlined functions.
+ /// This may be empty, in which case no prologue will be emitted.
+ virtual void insertOutlinerPrologue(MachineBasicBlock &MBB,
+ MachineFunction &MF,
+ bool IsTailCall) const {
+ llvm_unreachable(
+ "Target didn't implement TargetInstrInfo::insertOutlinerPrologue!");
+ }
+
+ /// Return true if the function can safely be outlined from.
+ /// By default, this means that the function has no red zone.
+ virtual bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
+ llvm_unreachable("Target didn't implement "
+ "TargetInstrInfo::isFunctionSafeToOutlineFrom!");
+ }
+
private:
unsigned CallFrameSetupOpcode, CallFrameDestroyOpcode;
unsigned CatchRetOpcode;