diff options
Diffstat (limited to 'llvm/lib/Target')
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 173 | ||||
| -rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.h | 15 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.cpp | 84 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.h | 14 |
4 files changed, 204 insertions, 82 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 163891a9d01..1d35fb3da2b 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/LiveRegUnits.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -4534,38 +4535,124 @@ AArch64InstrInfo::getSerializableMachineMemOperandTargetFlags() const { return makeArrayRef(TargetFlags); } -// 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()) { - // 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); - } +/// Constants defining how certain sequences should be outlined. +/// This encompasses how an outlined function should be called, and what kind of +/// frame should be emitted for that outlined function. +/// +/// \p MachineOutlinerDefault implies that the function should be called with +/// a save and restore of LR to the stack. +/// +/// That is, +/// +/// I1 Save LR OUTLINED_FUNCTION: +/// I2 --> BL OUTLINED_FUNCTION I1 +/// I3 Restore LR I2 +/// I3 +/// RET +/// +/// * Call construction overhead: 3 (save + BL + restore) +/// * Frame construction overhead: 1 (ret) +/// * Requires stack fixups? Yes +/// +/// \p MachineOutlinerTailCall implies that the function is being created from +/// a sequence of instructions ending in a return. +/// +/// That is, +/// +/// I1 OUTLINED_FUNCTION: +/// I2 --> B OUTLINED_FUNCTION I1 +/// RET I2 +/// RET +/// +/// * Call construction overhead: 1 (B) +/// * Frame construction overhead: 0 (Return included in sequence) +/// * Requires stack fixups? No +/// +/// \p MachineOutlinerNoLRSave implies that the function should be called using +/// a BL instruction, but doesn't require LR to be saved and restored. This +/// happens when LR is known to be dead. +/// +/// That is, +/// +/// I1 OUTLINED_FUNCTION: +/// I2 --> BL OUTLINED_FUNCTION I1 +/// I3 I2 +/// I3 +/// RET +/// +/// * Call construction overhead: 1 (BL) +/// * Frame construction overhead: 1 (RET) +/// * Requires stack fixups? No +/// +enum MachineOutlinerClass { + MachineOutlinerDefault, /// Emit a save, restore, call, and return. + MachineOutlinerTailCall, /// Only emit a branch. + MachineOutlinerNoLRSave /// Emit a call and return. +}; - // No, so save + restore LR. - return std::make_pair(3, MachineOutlinerDefaultFn); +bool AArch64InstrInfo::canOutlineWithoutLRSave( + MachineBasicBlock::iterator &CallInsertionPt) const { + // Was LR saved in the function containing this basic block? + MachineBasicBlock &MBB = *(CallInsertionPt->getParent()); + LiveRegUnits LRU(getRegisterInfo()); + LRU.addLiveOuts(MBB); + + // Get liveness information from the end of the block to the end of the + // prospective outlined region. + std::for_each(MBB.rbegin(), + (MachineBasicBlock::reverse_iterator)CallInsertionPt, + [&LRU](MachineInstr &MI) {LRU.stepBackward(MI);} + ); + + // If the link register is available at this point, then we can safely outline + // the region without saving/restoring LR. Otherwise, we must emit a save and + // restore. + return LRU.available(AArch64::LR); } -std::pair<size_t, unsigned> AArch64InstrInfo::getOutliningFrameOverhead( - std::vector<std::pair<MachineBasicBlock::iterator, - MachineBasicBlock::iterator>> &CandidateClass) const { +AArch64GenInstrInfo::MachineOutlinerInfo +AArch64InstrInfo::getOutlininingCandidateInfo( + std::vector< + std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>> + &RepeatedSequenceLocs) const { + + unsigned CallID = MachineOutlinerDefault; + unsigned FrameID = MachineOutlinerDefault; + unsigned NumInstrsForCall = 3; + unsigned NumInstrsToCreateFrame = 1; + + auto DoesntNeedLRSave = + [this](std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator> + &I) { return canOutlineWithoutLRSave(I.second); }; + + // If the last instruction in any candidate is a terminator, then we should + // tail call all of the candidates. + if (RepeatedSequenceLocs[0].second->isTerminator()) { + CallID = MachineOutlinerTailCall; + FrameID = MachineOutlinerTailCall; + NumInstrsForCall = 1; + NumInstrsToCreateFrame = 0; + } - // Is the last instruction in this class a terminator? - if (CandidateClass[0].second->isTerminator()) - return std::make_pair(0, MachineOutlinerTailCallFn); + else if (std::all_of(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(), + DoesntNeedLRSave)) { + CallID = MachineOutlinerNoLRSave; + FrameID = MachineOutlinerNoLRSave; + NumInstrsForCall = 1; + NumInstrsToCreateFrame = 1; + } - // No, so we have to add a return to the end. - return std::make_pair(1, MachineOutlinerDefaultFn); + return MachineOutlinerInfo(NumInstrsForCall, NumInstrsToCreateFrame, CallID, + FrameID); } bool AArch64InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const { - return MF.getFunction()->hasFnAttribute(Attribute::NoRedZone); + // If MF has a red zone, then we ought not to outline from it, since outlined + // functions can modify/read from the stack. + // If MF's address is taken, then we don't want to outline from it either + // since we don't really know what the user is doing with it. + return MF.getFunction()->hasFnAttribute(Attribute::NoRedZone) && + !MF.getFunction()->hasAddressTaken(); } AArch64GenInstrInfo::MachineOutlinerInstrType @@ -4607,6 +4694,10 @@ AArch64InstrInfo::getOutliningType(MachineInstr &MI) const { if (MOP.isCPI() || MOP.isJTI() || MOP.isCFIIndex() || MOP.isFI() || MOP.isTargetIndex()) return MachineOutlinerInstrType::Illegal; + + // Don't outline anything that uses the link register. + if (MOP.isReg() && getRegisterInfo().regsOverlap(MOP.getReg(), AArch64::LR)) + return MachineOutlinerInstrType::Illegal; } // Does this use the stack? @@ -4676,12 +4767,12 @@ void AArch64InstrInfo::fixupPostOutline(MachineBasicBlock &MBB) const { } } -void AArch64InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB, - MachineFunction &MF, - unsigned FrameClass) const { +void AArch64InstrInfo::insertOutlinerEpilogue( + MachineBasicBlock &MBB, MachineFunction &MF, + const MachineOutlinerInfo &MInfo) const { // If this is a tail call outlined function, then there's already a return. - if (FrameClass == MachineOutlinerTailCallFn) + if (MInfo.FrameConstructionID == MachineOutlinerTailCall) return; // It's not a tail call, so we have to insert the return ourselves. @@ -4689,28 +4780,40 @@ void AArch64InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB, .addReg(AArch64::LR, RegState::Undef); MBB.insert(MBB.end(), ret); + // Did we have to modify the stack by saving the link register? + if (MInfo.FrameConstructionID == MachineOutlinerNoLRSave) + return; + + // We modified the stack. // Walk over the basic block and fix up all the stack accesses. fixupPostOutline(MBB); } -void AArch64InstrInfo::insertOutlinerPrologue(MachineBasicBlock &MBB, - MachineFunction &MF, - unsigned FrameClass) const {} +void AArch64InstrInfo::insertOutlinerPrologue( + MachineBasicBlock &MBB, MachineFunction &MF, + const MachineOutlinerInfo &MInfo) const {} MachineBasicBlock::iterator AArch64InstrInfo::insertOutlinedCall( Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, - MachineFunction &MF, unsigned CallClass) const { + MachineFunction &MF, const MachineOutlinerInfo &MInfo) const { // Are we tail calling? - if (CallClass == MachineOutlinerTailCallFn) { + if (MInfo.CallConstructionID == MachineOutlinerTailCall) { // 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()))); return It; } - // We're not tail calling, so we have to save LR before the call and restore - // it after. + // Are we saving the link register? + if (MInfo.CallConstructionID == MachineOutlinerNoLRSave) { + // No, so just insert the call. + It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL)) + .addGlobalAddress(M.getNamedValue(MF.getName()))); + return It; + } + + // We have a default call. Save the link register. MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre)) .addReg(AArch64::SP, RegState::Define) .addReg(AArch64::LR) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index 4d510efcea3..9a338b53c7a 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -350,24 +350,23 @@ public: ArrayRef<std::pair<MachineMemOperand::Flags, const char *>> getSerializableMachineMemOperandTargetFlags() const override; + bool + canOutlineWithoutLRSave(MachineBasicBlock::iterator &CallInsertionPt) const; bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override; - std::pair<size_t, unsigned> - getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt, - MachineBasicBlock::iterator &EndIt) const override; - std::pair<size_t, unsigned> getOutliningFrameOverhead( + MachineOutlinerInfo getOutlininingCandidateInfo( std::vector< std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>> - &CandidateClass) const override; + &RepeatedSequenceLocs) const override; AArch64GenInstrInfo::MachineOutlinerInstrType getOutliningType(MachineInstr &MI) const override; void insertOutlinerEpilogue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const override; + const MachineOutlinerInfo &MInfo) const override; void insertOutlinerPrologue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const override; + const MachineOutlinerInfo &MInfo) const override; MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, - unsigned CallClass) const override; + const MachineOutlinerInfo &MInfo) const override; /// Returns true if the instruction has a shift left that can be executed /// more efficiently. bool isExynosShiftLeftFast(const MachineInstr &MI) const; diff --git a/llvm/lib/Target/X86/X86InstrInfo.cpp b/llvm/lib/Target/X86/X86InstrInfo.cpp index 0561bcd8d0a..6dcfa97b851 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.cpp +++ b/llvm/lib/Target/X86/X86InstrInfo.cpp @@ -10723,31 +10723,54 @@ char LDTLSCleanup::ID = 0; FunctionPass* llvm::createCleanupLocalDynamicTLSPass() { return new LDTLSCleanup(); } -// 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); -} - -std::pair<size_t, unsigned> X86InstrInfo::getOutliningFrameOverhead( - std::vector<std::pair<MachineBasicBlock::iterator, - MachineBasicBlock::iterator>> &CandidateClass) const { - // Is this a tail-call? - // Is the last instruction in this class a terminator? - if (CandidateClass[0].second->isTerminator()) - return std::make_pair(0, MachineOutlinerTailCallFn); +/// Constants defining how certain sequences should be outlined. +/// +/// \p MachineOutlinerDefault implies that the function is called with a call +/// instruction, and a return must be emitted for the outlined function frame. +/// +/// That is, +/// +/// I1 OUTLINED_FUNCTION: +/// I2 --> call OUTLINED_FUNCTION I1 +/// I3 I2 +/// I3 +/// ret +/// +/// * Call construction overhead: 1 (call instruction) +/// * Frame construction overhead: 1 (return instruction) +/// +/// \p MachineOutlinerTailCall implies that the function is being tail called. +/// A jump is emitted instead of a call, and the return is already present in +/// the outlined sequence. That is, +/// +/// I1 OUTLINED_FUNCTION: +/// I2 --> jmp OUTLINED_FUNCTION I1 +/// ret I2 +/// ret +/// +/// * Call construction overhead: 1 (jump instruction) +/// * Frame construction overhead: 0 (don't need to return) +/// +enum MachineOutlinerClass { + MachineOutlinerDefault, + MachineOutlinerTailCall +}; - // No, so we have to add a return to the end. - return std::make_pair(1, MachineOutlinerDefaultFn); +X86GenInstrInfo::MachineOutlinerInfo +X86InstrInfo::getOutlininingCandidateInfo( + std::vector< + std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>> + &RepeatedSequenceLocs) const { + + if (RepeatedSequenceLocs[0].second->isTerminator()) + return MachineOutlinerInfo(1, // Number of instructions to emit call. + 0, // Number of instructions to emit frame. + MachineOutlinerTailCall, // Type of call. + MachineOutlinerTailCall // Type of frame. + ); + + return MachineOutlinerInfo(1, 1, MachineOutlinerDefault, + MachineOutlinerDefault); } bool X86InstrInfo::isFunctionSafeToOutlineFrom(MachineFunction &MF) const { @@ -10811,10 +10834,10 @@ X86InstrInfo::getOutliningType(MachineInstr &MI) const { void X86InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const { - + const MachineOutlinerInfo &MInfo) + const { // If we're a tail call, we already have a return, so don't do anything. - if (FrameClass == MachineOutlinerTailCallFn) + if (MInfo.FrameConstructionID == MachineOutlinerTailCall) return; // We're a normal call, so our sequence doesn't have a return instruction. @@ -10825,15 +10848,16 @@ void X86InstrInfo::insertOutlinerEpilogue(MachineBasicBlock &MBB, void X86InstrInfo::insertOutlinerPrologue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const {} + const MachineOutlinerInfo &MInfo) + const {} MachineBasicBlock::iterator X86InstrInfo::insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, - unsigned CallClass) const { + const MachineOutlinerInfo &MInfo) const { // Is it a tail call? - if (CallClass == MachineOutlinerTailCallFn) { + if (MInfo.CallConstructionID == MachineOutlinerTailCall) { // Yes, just insert a JMP. It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(X86::JMP_1)) diff --git a/llvm/lib/Target/X86/X86InstrInfo.h b/llvm/lib/Target/X86/X86InstrInfo.h index 00684f52cb3..8bbf7dc6d23 100644 --- a/llvm/lib/Target/X86/X86InstrInfo.h +++ b/llvm/lib/Target/X86/X86InstrInfo.h @@ -559,14 +559,10 @@ public: ArrayRef<std::pair<unsigned, const char *>> getSerializableDirectMachineOperandTargetFlags() const override; - std::pair<size_t, unsigned> - getOutliningCallOverhead(MachineBasicBlock::iterator &StartIt, - MachineBasicBlock::iterator &EndIt) const override; - - std::pair<size_t, unsigned> getOutliningFrameOverhead( + virtual MachineOutlinerInfo getOutlininingCandidateInfo( std::vector< std::pair<MachineBasicBlock::iterator, MachineBasicBlock::iterator>> - &CandidateClass) const override; + &RepeatedSequenceLocs) const override; bool isFunctionSafeToOutlineFrom(MachineFunction &MF) const override; @@ -574,15 +570,15 @@ public: getOutliningType(MachineInstr &MI) const override; void insertOutlinerEpilogue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const override; + const MachineOutlinerInfo &MInfo) const override; void insertOutlinerPrologue(MachineBasicBlock &MBB, MachineFunction &MF, - unsigned FrameClass) const override; + const MachineOutlinerInfo &MInfo) const override; MachineBasicBlock::iterator insertOutlinedCall(Module &M, MachineBasicBlock &MBB, MachineBasicBlock::iterator &It, MachineFunction &MF, - unsigned CallClass) const override; + const MachineOutlinerInfo &MInfo) const override; protected: /// Commutes the operands in the given instruction by changing the operands |

