/// \brief Returns the number of instructions that will be taken to call a
/// function defined by the sequence on the closed interval [ \p StartIt, \p
/// EndIt].
- virtual size_t
+ ///
+ /// \returns The number of instructions for the call in the first member,
+ /// and a target-defined unsigned describing what type of call to emit in the
+ /// second member.
+ virtual std::pair<size_t, unsigned>
getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt,
MachineBasicBlock::iterator &EndIt) const {
llvm_unreachable(
/// \brief Returns the number of instructions that will be taken to construct
/// an outlined function frame for a function defined on the closed interval
/// [ \p StartIt, \p EndIt].
- virtual size_t
- getOutliningFrameOverhead(MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const {
+ ///
+ /// \returns The number of instructions for the frame in the first member
+ /// and a target-defined unsigned describing what type of frame to construct
+ /// in the second member.
+ virtual std::pair<size_t, unsigned> getOutliningFrameOverhead(
+ std::vector<
+ std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
+ &CandidateClass) const {
llvm_unreachable(
- "Target didn't implement TargetInstrInfo::getOutliningCallOverhead!");
+ "Target didn't implement TargetInstrInfo::getOutliningFrameOverhead!");
}
/// Represents how an instruction should be mapped by the outliner.
/// emitted.
virtual void insertOutlinerEpilogue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned FrameClass) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::insertOutlinerEpilogue!");
}
virtual MachineBasicBlock::iterator
insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &It, MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned CallClass) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::insertOutlinedCall!");
}
/// This may be empty, in which case no prologue will be emitted.
virtual void insertOutlinerPrologue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned FrameClass) const {
llvm_unreachable(
"Target didn't implement TargetInstrInfo::insertOutlinerPrologue!");
}
/// \p OutlinedFunctions.
size_t FunctionIdx;
+ /// Target-defined unsigned defining how to emit a call for this candidate.
+ unsigned CallClass = 0;
+
/// \brief The number of instructions that would be saved by outlining every
/// candidate of this type.
///
/// for some given candidate.
unsigned Benefit = 0;
- Candidate(size_t StartIdx, size_t Len, size_t FunctionIdx)
- : StartIdx(StartIdx), Len(Len), FunctionIdx(FunctionIdx) {}
+ Candidate(size_t StartIdx, size_t Len, size_t FunctionIdx, unsigned CallClass)
+ : StartIdx(StartIdx), Len(Len), FunctionIdx(FunctionIdx),
+ CallClass(CallClass) {}
Candidate() {}
/// The number of instructions this function would save.
unsigned Benefit = 0;
- /// \brief Set to true if candidates for this outlined function should be
- /// replaced with tail calls to this OutlinedFunction.
- bool IsTailCall = false;
+ /// Target-defined unsigned defining how to emit the frame for this function.
+ unsigned FrameClass = 0;
OutlinedFunction(size_t Name, size_t OccurrenceCount,
const std::vector<unsigned> &Sequence, unsigned Benefit,
- bool IsTailCall)
+ unsigned FrameClass)
: Name(Name), OccurrenceCount(OccurrenceCount), Sequence(Sequence),
- Benefit(Benefit), IsTailCall(IsTailCall) {}
+ Benefit(Benefit), FrameClass(FrameClass) {}
};
/// Represents an undefined index in the suffix tree.
// Figure out if this candidate is beneficial.
size_t StringLen = Leaf->ConcatLen - Leaf->size();
size_t CallOverhead = 0;
- size_t FrameOverhead = 0;
size_t SequenceOverhead = StringLen;
+ // If this is a beneficial class of candidate, then every one is stored in
+ // this vector.
+ std::vector<Candidate> CandidatesForRepeatedSeq;
+
+ // Used for getOutliningFrameOverhead.
+ // FIXME: CandidatesForRepeatedSeq and this should be combined.
+ std::vector<
+ std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
+ CandidateClass;
+
// Figure out the call overhead for each instance of the sequence.
for (auto &ChildPair : Parent.Children) {
SuffixTreeNode *M = ChildPair.second;
MachineBasicBlock::iterator StartIt = Mapper.InstrList[M->SuffixIdx];
MachineBasicBlock::iterator EndIt =
Mapper.InstrList[M->SuffixIdx + StringLen - 1];
- CallOverhead += TII.getOutliningCallOverhead(StartIt, EndIt);
+
+ // Get the overhead for calling a function for this sequence and any
+ // target-specified data for how to construct the call.
+ std::pair<size_t, unsigned> CallOverheadPair =
+ TII.getOutliningCallOverhead(StartIt, EndIt);
+ CallOverhead += CallOverheadPair.first;
+ CandidatesForRepeatedSeq.emplace_back(M->SuffixIdx, StringLen, FnIdx,
+ CallOverheadPair.second);
+ CandidateClass.emplace_back(std::make_pair(StartIt, EndIt));
+
+ // Never visit this leaf again.
+ M->IsInTree = false;
}
}
- // Figure out how many instructions it'll take to construct an outlined
- // function frame for this sequence.
- MachineBasicBlock::iterator StartIt = Mapper.InstrList[Leaf->SuffixIdx];
- MachineBasicBlock::iterator EndIt =
- Mapper.InstrList[Leaf->SuffixIdx + StringLen - 1];
- FrameOverhead = TII.getOutliningFrameOverhead(StartIt, EndIt);
+ std::pair<size_t, unsigned> FrameOverheadPair =
+ TII.getOutliningFrameOverhead(CandidateClass);
+ size_t FrameOverhead = FrameOverheadPair.first;
size_t OutliningCost = CallOverhead + FrameOverhead + SequenceOverhead;
size_t NotOutliningCost = SequenceOverhead * Parent.OccurrenceCount;
if (StringLen > MaxLen)
MaxLen = StringLen;
- unsigned OccurrenceCount = 0;
- for (auto &ChildPair : Parent.Children) {
- SuffixTreeNode *M = ChildPair.second;
-
- // Is it a leaf? If so, we have an occurrence of this candidate.
- if (M && M->IsInTree && M->isLeaf()) {
- OccurrenceCount++;
- CandidateList.emplace_back(M->SuffixIdx, StringLen, FnIdx);
- CandidateList.back().Benefit = Benefit;
- M->IsInTree = false;
- }
+ // At this point, the candidate class is seen as beneficial. Set their
+ // benefit values and save them in the candidate list.
+ for (Candidate &C : CandidatesForRepeatedSeq) {
+ C.Benefit = Benefit;
+ CandidateList.push_back(C);
}
// Save the function for the new candidate sequence.
for (unsigned i = Leaf->SuffixIdx; i < Leaf->SuffixIdx + StringLen; i++)
CandidateSequence.push_back(ST.Str[i]);
- FunctionList.emplace_back(FnIdx, OccurrenceCount, CandidateSequence,
- Benefit, false);
+ FunctionList.emplace_back(FnIdx, CandidatesForRepeatedSeq.size(),
+ CandidateSequence, Benefit,
+ FrameOverheadPair.second);
// Move to the next function.
FnIdx++;
MachineBasicBlock::iterator StartIt = Mapper.InstrList[C2.StartIdx];
MachineBasicBlock::iterator EndIt =
Mapper.InstrList[C2.StartIdx + C2.Len - 1];
- F2.Benefit += TII.getOutliningCallOverhead(StartIt, EndIt);
+
+ F2.Benefit += TII.getOutliningCallOverhead(StartIt, EndIt).first;
// Add back one instance of the sequence.
if (F2.Sequence.size() > F2.Benefit)
MachineBasicBlock::iterator StartIt = Mapper.InstrList[C1.StartIdx];
MachineBasicBlock::iterator EndIt =
Mapper.InstrList[C1.StartIdx + C1.Len - 1];
- F2.Benefit += TII.getOutliningCallOverhead(StartIt, EndIt);
+
+ F1.Benefit += TII.getOutliningCallOverhead(StartIt, EndIt).first;
// Add back one instance of the sequence.
if (F1.Sequence.size() > F1.Benefit)
MaxCandidateLen =
findCandidates(ST, TII, Mapper, CandidateList, FunctionList);
- for (auto &OF : FunctionList)
- OF.IsTailCall =
- Mapper.IntegerInstructionMap[OF.Sequence.back()]->isTerminator();
-
// Sort the candidates in decending order. This will simplify the outlining
// process when we have to remove the candidates from the mapping by
// allowing us to cut them out without keeping track of an offset.
// Insert the new function into the module.
MF.insert(MF.begin(), &MBB);
- TII.insertOutlinerPrologue(MBB, MF, OF.IsTailCall);
+ TII.insertOutlinerPrologue(MBB, MF, OF.FrameClass);
// Copy over the instructions for the function using the integer mappings in
// its sequence.
MBB.insert(MBB.end(), NewMI);
}
- TII.insertOutlinerEpilogue(MBB, MF, OF.IsTailCall);
+ TII.insertOutlinerEpilogue(MBB, MF, OF.FrameClass);
return &MF;
}
const TargetInstrInfo &TII = *STI.getInstrInfo();
// Insert a call to the new function and erase the old sequence.
- TII.insertOutlinedCall(M, *MBB, StartIt, *MF, OF.IsTailCall);
+ TII.insertOutlinedCall(M, *MBB, StartIt, *MF, C.CallClass);
StartIt = Mapper.InstrList[C.StartIdx];
MBB->erase(StartIt, EndIt);
return makeArrayRef(TargetFlags);
}
-size_t AArch64InstrInfo::getOutliningCallOverhead(
+// Constants defining how certain sequences should be outlined.
+const unsigned MachineOutlinerDefaultFn = 0;
+const unsigned MachineOutlinerTailCallFn = 1;
+
+std::pair<size_t, unsigned> AArch64InstrInfo::getOutliningCallOverhead(
MachineBasicBlock::iterator &StartIt,
MachineBasicBlock::iterator &EndIt) const {
// Is this a tail-call?
- if (EndIt->isTerminator())
- return 1; // Yes, so we don't need to save/restore LR.
+ if (EndIt->isTerminator()) {
+ // Yes, so we only have to emit a call. Return a cost of 1 + signify that
+ // this candidate should be tail-called.
+ return std::make_pair(1, MachineOutlinerTailCallFn);
+ }
// No, so save + restore LR.
- return 3;
+ return std::make_pair(3, MachineOutlinerDefaultFn);
}
-size_t AArch64InstrInfo::getOutliningFrameOverhead(
- MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const {
+std::pair<size_t, unsigned> AArch64InstrInfo::getOutliningFrameOverhead(
+ std::vector<std::pair<MachineBasicBlock::iterator,
+ MachineBasicBlock::iterator>> &CandidateClass) const {
- // Is this a tail-call?
- if (EndIt->isTerminator())
- return 0; // Yes, so we already have a return.
+ // Is the last instruction in this class a terminator?
+ if (CandidateClass[0].second->isTerminator())
+ return std::make_pair(0, MachineOutlinerTailCallFn);
// No, so we have to add a return to the end.
- return 1;
+ return std::make_pair(1, MachineOutlinerDefaultFn);
}
bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
void AArch64InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned FrameClass) const {
// If this is a tail call outlined function, then there's already a return.
- if (IsTailCall)
+ if (FrameClass == MachineOutlinerTailCallFn)
return;
// It's not a tail call, so we have to insert the return ourselves.
void AArch64InstrInfo::insertOutlinerPrologue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {}
+ unsigned FrameClass) const {}
MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall(
Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It,
- MachineFunction &MF, bool IsTailCall) const {
+ MachineFunction &MF, unsigned CallClass) const {
// Are we tail calling?
- if (IsTailCall) {
+ if (CallClass == MachineOutlinerTailCallFn) {
// If yes, then we can just branch to the label.
- It = MBB.insert(It,
- BuildMI(MF, DebugLoc(), get(AArch64::B))
- .addGlobalAddress(M.getNamedValue(MF.getName())));
+ It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::B))
+ .addGlobalAddress(M.getNamedValue(MF.getName())));
return It;
}
It++;
// Insert the call.
- It = MBB.insert(It,
- BuildMI(MF, DebugLoc(), get(AArch64::BL))
- .addGlobalAddress(M.getNamedValue(MF.getName())));
+ It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
+ .addGlobalAddress(M.getNamedValue(MF.getName())));
It++;
default:
llvm_unreachable("Opcode has no flag setting equivalent!");
// 32-bit cases:
- case AArch64::ADDWri: Is64Bit = false; return AArch64::ADDSWri;
- case AArch64::ADDWrr: Is64Bit = false; return AArch64::ADDSWrr;
- case AArch64::ADDWrs: Is64Bit = false; return AArch64::ADDSWrs;
- case AArch64::ADDWrx: Is64Bit = false; return AArch64::ADDSWrx;
- case AArch64::ANDWri: Is64Bit = false; return AArch64::ANDSWri;
- case AArch64::ANDWrr: Is64Bit = false; return AArch64::ANDSWrr;
- case AArch64::ANDWrs: Is64Bit = false; return AArch64::ANDSWrs;
- case AArch64::BICWrr: Is64Bit = false; return AArch64::BICSWrr;
- case AArch64::BICWrs: Is64Bit = false; return AArch64::BICSWrs;
- case AArch64::SUBWri: Is64Bit = false; return AArch64::SUBSWri;
- case AArch64::SUBWrr: Is64Bit = false; return AArch64::SUBSWrr;
- case AArch64::SUBWrs: Is64Bit = false; return AArch64::SUBSWrs;
- case AArch64::SUBWrx: Is64Bit = false; return AArch64::SUBSWrx;
+ case AArch64::ADDWri:
+ Is64Bit = false;
+ return AArch64::ADDSWri;
+ case AArch64::ADDWrr:
+ Is64Bit = false;
+ return AArch64::ADDSWrr;
+ case AArch64::ADDWrs:
+ Is64Bit = false;
+ return AArch64::ADDSWrs;
+ case AArch64::ADDWrx:
+ Is64Bit = false;
+ return AArch64::ADDSWrx;
+ case AArch64::ANDWri:
+ Is64Bit = false;
+ return AArch64::ANDSWri;
+ case AArch64::ANDWrr:
+ Is64Bit = false;
+ return AArch64::ANDSWrr;
+ case AArch64::ANDWrs:
+ Is64Bit = false;
+ return AArch64::ANDSWrs;
+ case AArch64::BICWrr:
+ Is64Bit = false;
+ return AArch64::BICSWrr;
+ case AArch64::BICWrs:
+ Is64Bit = false;
+ return AArch64::BICSWrs;
+ case AArch64::SUBWri:
+ Is64Bit = false;
+ return AArch64::SUBSWri;
+ case AArch64::SUBWrr:
+ Is64Bit = false;
+ return AArch64::SUBSWrr;
+ case AArch64::SUBWrs:
+ Is64Bit = false;
+ return AArch64::SUBSWrs;
+ case AArch64::SUBWrx:
+ Is64Bit = false;
+ return AArch64::SUBSWrx;
// 64-bit cases:
- case AArch64::ADDXri: Is64Bit = true; return AArch64::ADDSXri;
- case AArch64::ADDXrr: Is64Bit = true; return AArch64::ADDSXrr;
- case AArch64::ADDXrs: Is64Bit = true; return AArch64::ADDSXrs;
- case AArch64::ADDXrx: Is64Bit = true; return AArch64::ADDSXrx;
- case AArch64::ANDXri: Is64Bit = true; return AArch64::ANDSXri;
- case AArch64::ANDXrr: Is64Bit = true; return AArch64::ANDSXrr;
- case AArch64::ANDXrs: Is64Bit = true; return AArch64::ANDSXrs;
- case AArch64::BICXrr: Is64Bit = true; return AArch64::BICSXrr;
- case AArch64::BICXrs: Is64Bit = true; return AArch64::BICSXrs;
- case AArch64::SUBXri: Is64Bit = true; return AArch64::SUBSXri;
- case AArch64::SUBXrr: Is64Bit = true; return AArch64::SUBSXrr;
- case AArch64::SUBXrs: Is64Bit = true; return AArch64::SUBSXrs;
- case AArch64::SUBXrx: Is64Bit = true; return AArch64::SUBSXrx;
+ case AArch64::ADDXri:
+ Is64Bit = true;
+ return AArch64::ADDSXri;
+ case AArch64::ADDXrr:
+ Is64Bit = true;
+ return AArch64::ADDSXrr;
+ case AArch64::ADDXrs:
+ Is64Bit = true;
+ return AArch64::ADDSXrs;
+ case AArch64::ADDXrx:
+ Is64Bit = true;
+ return AArch64::ADDSXrx;
+ case AArch64::ANDXri:
+ Is64Bit = true;
+ return AArch64::ANDSXri;
+ case AArch64::ANDXrr:
+ Is64Bit = true;
+ return AArch64::ANDSXrr;
+ case AArch64::ANDXrs:
+ Is64Bit = true;
+ return AArch64::ANDSXrs;
+ case AArch64::BICXrr:
+ Is64Bit = true;
+ return AArch64::BICSXrr;
+ case AArch64::BICXrs:
+ Is64Bit = true;
+ return AArch64::BICSXrs;
+ case AArch64::SUBXri:
+ Is64Bit = true;
+ return AArch64::SUBSXri;
+ case AArch64::SUBXrr:
+ Is64Bit = true;
+ return AArch64::SUBSXrr;
+ case AArch64::SUBXrs:
+ Is64Bit = true;
+ return AArch64::SUBSXrs;
+ case AArch64::SUBXrx:
+ Is64Bit = true;
+ return AArch64::SUBSXrx;
}
}
-
/// Return true if this is a load/store that can be potentially paired/merged.
bool isCandidateToMergeOrPair(MachineInstr &MI) const;
/// Return true when there is potentially a faster code sequence
/// for an instruction chain ending in ``Root``. All potential patterns are
/// listed in the ``Patterns`` array.
- bool getMachineCombinerPatterns(MachineInstr &Root,
- SmallVectorImpl<MachineCombinerPattern> &Patterns)
- const override;
+ bool getMachineCombinerPatterns(
+ MachineInstr &Root,
+ SmallVectorImpl<MachineCombinerPattern> &Patterns) const override;
/// Return true when Inst is associative and commutative so that it can be
/// reassociated.
bool isAssociativeAndCommutative(const MachineInstr &Inst) const override;
getSerializableMachineMemOperandTargetFlags() const override;
bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override;
- size_t getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const override;
- size_t getOutliningFrameOverhead(MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const override;
+ std::pair<size_t, unsigned>
+ getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt,
+ MachineBasicBlock::iterator &EndIt) const override;
+ std::pair<size_t, unsigned> getOutliningFrameOverhead(
+ std::vector<
+ std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
+ &CandidateClass) const override;
AArch64GenInstrInfo::MachineOutlinerInstrType
getOutliningType(MachineInstr &MI) const override;
- void insertOutlinerEpilogue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- bool IsTailCall) const override;
- void insertOutlinerPrologue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- bool isTailCall) const override;
+ void insertOutlinerEpilogue(MachineBasicBlock &MBB, MachineFunction &MF,
+ unsigned FrameClass) const override;
+ void insertOutlinerPrologue(MachineBasicBlock &MBB, MachineFunction &MF,
+ unsigned FrameClass) const override;
MachineBasicBlock::iterator
insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &It,
- MachineFunction &MF,
- bool IsTailCall) const override;
+ MachineBasicBlock::iterator &It, MachineFunction &MF,
+ unsigned CallClass) const override;
/// Returns true if the instruction has a shift by immediate that can be
/// executed in one cycle less.
bool isFalkorShiftExtFast(const MachineInstr &MI) const;
-private:
+private:
/// \brief Sets the offsets on outlined instructions in \p MBB which use SP
/// so that they will be valid post-outlining.
///
/// FP. Return false if the offset could not be handled directly in MI, and
/// return the left-over portion by reference.
bool rewriteAArch64FrameIndex(MachineInstr &MI, unsigned FrameRegIdx,
- unsigned FrameReg, int &Offset,
- const AArch64InstrInfo *TII);
+ unsigned FrameReg, int &Offset,
+ const AArch64InstrInfo *TII);
/// \brief Use to report the frame offset status in isAArch64FrameOffsetLegal.
enum AArch64FrameOffsetStatus {
/// (possibly with @p OutUnscaledOp if OutUseUnscaledOp is true) and that
/// is a legal offset.
int isAArch64FrameOffsetLegal(const MachineInstr &MI, int &Offset,
- bool *OutUseUnscaledOp = nullptr,
- unsigned *OutUnscaledOp = nullptr,
- int *EmittableOffset = nullptr);
+ bool *OutUseUnscaledOp = nullptr,
+ unsigned *OutUnscaledOp = nullptr,
+ int *EmittableOffset = nullptr);
static inline bool isUncondBranchOpcode(int Opc) { return Opc == AArch64::B; }
}
}
-static inline bool isIndirectBranchOpcode(int Opc) { return Opc == AArch64::BR; }
+static inline bool isIndirectBranchOpcode(int Opc) {
+ return Opc == AArch64::BR;
+}
} // end namespace llvm
FunctionPass*
llvm::createCleanupLocalDynamicTLSPass() { return new LDTLSCleanup(); }
-size_t X86InstrInfo::getOutliningCallOverhead(
-MachineBasicBlock::iterator &StartIt,
-MachineBasicBlock::iterator &EndIt) const {
- // We just have to emit a call, so return 1.
- return 1;
+// Constants defining how certain sequences should be outlined.
+const unsigned MachineOutlinerDefaultFn = 0;
+const unsigned MachineOutlinerTailCallFn = 1;
+
+std::pair<size_t, unsigned> X86InstrInfo::getOutliningCallOverhead(
+ MachineBasicBlock::iterator &StartIt,
+ MachineBasicBlock::iterator &EndIt) const {
+
+ // Is this a tail call? If it is, make note of it.
+ if (EndIt->isTerminator())
+ return std::make_pair(1, MachineOutlinerTailCallFn);
+
+ return std::make_pair(1, MachineOutlinerDefaultFn);
}
-size_t X86InstrInfo::getOutliningFrameOverhead(
-MachineBasicBlock::iterator &StartIt,
-MachineBasicBlock::iterator &EndIt) const {
+std::pair<size_t, unsigned> X86InstrInfo::getOutliningFrameOverhead(
+ std::vector<std::pair<MachineBasicBlock::iterator,
+ MachineBasicBlock::iterator>> &CandidateClass) const {
// Is this a tail-call?
- if (EndIt->isTerminator())
- return 0; // Yes, so we already have a return.
+ // Is the last instruction in this class a terminator?
+ if (CandidateClass[0].second->isTerminator())
+ return std::make_pair(0, MachineOutlinerTailCallFn);
// No, so we have to add a return to the end.
- return 1;
+ return std::make_pair(1, MachineOutlinerDefaultFn);
}
bool X86InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const {
void X86InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned FrameClass) const {
// If we're a tail call, we already have a return, so don't do anything.
- if (IsTailCall)
+ if (FrameClass == MachineOutlinerTailCallFn)
return;
// We're a normal call, so our sequence doesn't have a return instruction.
void X86InstrInfo::insertOutlinerPrologue(MachineBasicBlock &MBB,
MachineFunction &MF,
- bool IsTailCall) const {}
+ unsigned FrameClass) const {}
MachineBasicBlock::iterator
X86InstrInfo::insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
MachineBasicBlock::iterator &It,
MachineFunction &MF,
- bool IsTailCall) const {
+ unsigned CallClass) const {
// Is it a tail call?
- if (IsTailCall) {
+ if (CallClass == MachineOutlinerTailCallFn) {
// Yes, just insert a JMP.
It = MBB.insert(It,
BuildMI(MF, DebugLoc(), get(X86::JMP_1))
#include "X86GenInstrInfo.inc"
namespace llvm {
- class MachineInstrBuilder;
- class X86RegisterInfo;
- class X86Subtarget;
+class MachineInstrBuilder;
+class X86RegisterInfo;
+class X86Subtarget;
namespace X86 {
- // X86 specific condition code. These correspond to X86_*_COND in
- // X86InstrInfo.td. They must be kept in synch.
+// X86 specific condition code. These correspond to X86_*_COND in
+// X86InstrInfo.td. They must be kept in synch.
enum CondCode {
COND_A = 0,
COND_AE = 1,
/// GetOppositeBranchCondition - Return the inverse of the specified cond,
/// e.g. turning COND_E to COND_NE.
CondCode GetOppositeBranchCondition(CondCode CC);
-} // end namespace X86;
-
+} // namespace X86
/// isGlobalStubReference - Return true if the specified TargetFlag operand is
/// a reference to a stub for a global, not the global itself.
inline static bool isGlobalStubReference(unsigned char TargetFlag) {
switch (TargetFlag) {
- case X86II::MO_DLLIMPORT: // dllimport stub.
- case X86II::MO_GOTPCREL: // rip-relative GOT reference.
- case X86II::MO_GOT: // normal GOT reference.
- case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref.
- case X86II::MO_DARWIN_NONLAZY: // Normal $non_lazy_ptr ref.
+ case X86II::MO_DLLIMPORT: // dllimport stub.
+ case X86II::MO_GOTPCREL: // rip-relative GOT reference.
+ case X86II::MO_GOT: // normal GOT reference.
+ case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref.
+ case X86II::MO_DARWIN_NONLAZY: // Normal $non_lazy_ptr ref.
return true;
default:
return false;
/// is true, the addressing mode has the PIC base register added in (e.g. EBX).
inline static bool isGlobalRelativeToPICBase(unsigned char TargetFlag) {
switch (TargetFlag) {
- case X86II::MO_GOTOFF: // isPICStyleGOT: local global.
- case X86II::MO_GOT: // isPICStyleGOT: other global.
- case X86II::MO_PIC_BASE_OFFSET: // Darwin local global.
- case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global.
- case X86II::MO_TLVP: // ??? Pretty sure..
+ case X86II::MO_GOTOFF: // isPICStyleGOT: local global.
+ case X86II::MO_GOT: // isPICStyleGOT: other global.
+ case X86II::MO_PIC_BASE_OFFSET: // Darwin local global.
+ case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Darwin/32 external global.
+ case X86II::MO_TLVP: // ??? Pretty sure..
return true;
default:
return false;
}
inline static bool isScale(const MachineOperand &MO) {
- return MO.isImm() &&
- (MO.getImm() == 1 || MO.getImm() == 2 ||
- MO.getImm() == 4 || MO.getImm() == 8);
+ return MO.isImm() && (MO.getImm() == 1 || MO.getImm() == 2 ||
+ MO.getImm() == 4 || MO.getImm() == 8);
}
inline static bool isLeaMem(const MachineInstr &MI, unsigned Op) {
/// RegOp2MemOpTable3Addr, RegOp2MemOpTable0, RegOp2MemOpTable1,
/// RegOp2MemOpTable2, RegOp2MemOpTable3 - Load / store folding opcode maps.
///
- typedef DenseMap<unsigned,
- std::pair<uint16_t, uint16_t> > RegOp2MemOpTableType;
+ typedef DenseMap<unsigned, std::pair<uint16_t, uint16_t>>
+ RegOp2MemOpTableType;
RegOp2MemOpTableType RegOp2MemOpTable2Addr;
RegOp2MemOpTableType RegOp2MemOpTable0;
RegOp2MemOpTableType RegOp2MemOpTable1;
/// MemOp2RegOpTable - Load / store unfolding opcode map.
///
- typedef DenseMap<unsigned,
- std::pair<uint16_t, uint16_t> > MemOp2RegOpTableType;
+ typedef DenseMap<unsigned, std::pair<uint16_t, uint16_t>>
+ MemOp2RegOpTableType;
MemOp2RegOpTableType MemOp2RegOpTable;
static void AddTableEntry(RegOp2MemOpTableType &R2MTable,
- MemOp2RegOpTableType &M2RTable,
- uint16_t RegOp, uint16_t MemOp, uint16_t Flags);
+ MemOp2RegOpTableType &M2RTable, uint16_t RegOp,
+ uint16_t MemOp, uint16_t Flags);
virtual void anchor();
/// true, then it's expected the pre-extension value is available as a subreg
/// of the result register. This also returns the sub-register index in
/// SubIdx.
- bool isCoalescableExtInstr(const MachineInstr &MI,
- unsigned &SrcReg, unsigned &DstReg,
- unsigned &SubIdx) const override;
+ bool isCoalescableExtInstr(const MachineInstr &MI, unsigned &SrcReg,
+ unsigned &DstReg, unsigned &SubIdx) const override;
unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
/// operand to the LEA instruction.
bool classifyLEAReg(MachineInstr &MI, const MachineOperand &Src,
unsigned LEAOpcode, bool AllowSP, unsigned &NewSrc,
- bool &isKill, bool &isUndef,
- MachineOperand &ImplicitOp, LiveVariables *LV) const;
+ bool &isKill, bool &isUndef, MachineOperand &ImplicitOp,
+ LiveVariables *LV) const;
/// convertToThreeAddress - This method must be implemented by targets that
/// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target
/// FMA213 #1, #2, #3
/// results into instruction with adjusted opcode:
/// FMA231 #3, #2, #1
- bool findFMA3CommutedOpIndices(const MachineInstr &MI,
- unsigned &SrcOpIdx1,
+ bool findFMA3CommutedOpIndices(const MachineInstr &MI, unsigned &SrcOpIdx1,
unsigned &SrcOpIdx2,
const X86InstrFMA3Group &FMA3Group) const;
/// FMA213 #1, #2, #3
/// results into instruction with adjusted opcode:
/// FMA231 #3, #2, #1
- unsigned getFMA3OpcodeToCommuteOperands(const MachineInstr &MI,
- unsigned SrcOpIdx1,
- unsigned SrcOpIdx2,
- const X86InstrFMA3Group &FMA3Group) const;
+ unsigned
+ getFMA3OpcodeToCommuteOperands(const MachineInstr &MI, unsigned SrcOpIdx1,
+ unsigned SrcOpIdx2,
+ const X86InstrFMA3Group &FMA3Group) const;
// Branch analysis.
bool isUnpredicatedTerminator(const MachineInstr &MI) const override;
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
const DebugLoc &DL,
int *BytesAdded = nullptr) const override;
- bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond,
- unsigned, unsigned, int&, int&, int&) const override;
+ bool canInsertSelect(const MachineBasicBlock &, ArrayRef<MachineOperand> Cond,
+ unsigned, unsigned, int &, int &, int &) const override;
void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
const DebugLoc &DL, unsigned DstReg,
ArrayRef<MachineOperand> Cond, unsigned TrueReg,
const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override;
void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned SrcReg, bool isKill, int FrameIndex,
+ MachineBasicBlock::iterator MI, unsigned SrcReg,
+ bool isKill, int FrameIndex,
const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
const TargetRegisterClass *RC,
MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
+ SmallVectorImpl<MachineInstr *> &NewMIs) const;
void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
+ MachineBasicBlock::iterator MI, unsigned DestReg,
+ int FrameIndex, const TargetRegisterClass *RC,
const TargetRegisterInfo *TRI) const override;
void loadRegFromAddr(MachineFunction &MF, unsigned DestReg,
const TargetRegisterClass *RC,
MachineInstr::mmo_iterator MMOBegin,
MachineInstr::mmo_iterator MMOEnd,
- SmallVectorImpl<MachineInstr*> &NewMIs) const;
+ SmallVectorImpl<MachineInstr *> &NewMIs) const;
bool expandPostRAPseudo(MachineInstr &MI) const override;
SmallVectorImpl<MachineInstr *> &NewMIs) const override;
bool unfoldMemoryOperand(SelectionDAG &DAG, SDNode *N,
- SmallVectorImpl<SDNode*> &NewNodes) const override;
+ SmallVectorImpl<SDNode *> &NewNodes) const override;
/// getOpcodeAfterMemoryUnfold - Returns the opcode of the would be new
/// instruction after load / store are unfolded from an instruction of the
/// possible. If LoadRegIndex is non-null, it is filled in with the operand
/// index of the operand which will hold the register holding the loaded
/// value.
- unsigned getOpcodeAfterMemoryUnfold(unsigned Opc,
- bool UnfoldLoad, bool UnfoldStore,
- unsigned *LoadRegIndex = nullptr) const override;
+ unsigned
+ getOpcodeAfterMemoryUnfold(unsigned Opc, bool UnfoldLoad, bool UnfoldStore,
+ unsigned *LoadRegIndex = nullptr) const override;
/// areLoadsFromSameBasePtr - This is used by the pre-regalloc scheduler
/// to determine if two loads are loading from the same base address. It
int64_t &Offset2) const override;
/// shouldScheduleLoadsNear - This is a used by the pre-regalloc scheduler to
- /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads should
- /// be scheduled togther. On some targets if two loads are loading from
+ /// determine (in conjunction with areLoadsFromSameBasePtr) if two loads
+ /// should be scheduled togther. On some targets if two loads are loading from
/// addresses in the same cache line, it's better if they are scheduled
/// together. This function takes two integers that represent the load offsets
/// from the common base address. It returns true if it decides it's desirable
/// to schedule the two loads together. "NumLoads" is the number of loads that
/// have already been scheduled after Load1.
- bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2,
- int64_t Offset1, int64_t Offset2,
+ bool shouldScheduleLoadsNear(SDNode *Load1, SDNode *Load2, int64_t Offset1,
+ int64_t Offset2,
unsigned NumLoads) const override;
void getNoop(MCInst &NopInst) const override;
const MachineInstr &UseMI,
unsigned UseIdx) const override;
- bool useMachineCombiner() const override {
- return true;
- }
+ bool useMachineCombiner() const override { return true; }
bool isAssociativeAndCommutative(const MachineInstr &Inst) const override;
ArrayRef<std::pair<unsigned, const char *>>
getSerializableDirectMachineOperandTargetFlags() const override;
- size_t getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const override;
-
- size_t getOutliningFrameOverhead(MachineBasicBlock::iterator &StartIt,
- MachineBasicBlock::iterator &EndIt) const override;
+ std::pair<size_t, unsigned>
+ getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt,
+ MachineBasicBlock::iterator &EndIt) const override;
+
+ std::pair<size_t, unsigned> getOutliningFrameOverhead(
+ std::vector<
+ std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>>
+ &CandidateClass) const override;
bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override;
llvm::X86GenInstrInfo::MachineOutlinerInstrType
getOutliningType(MachineInstr &MI) const override;
- void insertOutlinerEpilogue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- bool IsTailCall) const override;
+ void insertOutlinerEpilogue(MachineBasicBlock &MBB, MachineFunction &MF,
+ unsigned FrameClass) const override;
- void insertOutlinerPrologue(MachineBasicBlock &MBB,
- MachineFunction &MF,
- bool isTailCall) const override;
+ void insertOutlinerPrologue(MachineBasicBlock &MBB, MachineFunction &MF,
+ unsigned FrameClass) const override;
MachineBasicBlock::iterator
insertOutlinedCall(Module &M, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator &It,
- MachineFunction &MF,
- bool IsTailCall) const override;
+ MachineBasicBlock::iterator &It, MachineFunction &MF,
+ unsigned CallClass) const override;
+
protected:
/// Commutes the operands in the given instruction by changing the operands
/// order and/or changing the instruction's opcode and/or the immediate value
unsigned &SrcOpIdx2) const;
};
-} // End llvm namespace
+} // namespace llvm
#endif