diff options
-rw-r--r-- | llvm/include/llvm/CodeGen/MachineOutliner.h | 7 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 48 |
2 files changed, 39 insertions, 16 deletions
diff --git a/llvm/include/llvm/CodeGen/MachineOutliner.h b/llvm/include/llvm/CodeGen/MachineOutliner.h index 2bd39b2392d..01d660a47a6 100644 --- a/llvm/include/llvm/CodeGen/MachineOutliner.h +++ b/llvm/include/llvm/CodeGen/MachineOutliner.h @@ -85,6 +85,9 @@ public: /// Target-specific flags for this Candidate's MBB. unsigned Flags = 0x0; + /// True if initLRU has been called on this Candidate. + bool LRUWasSet = false; + /// Return the number of instructions in this Candidate. unsigned getLength() const { return Len; } @@ -141,6 +144,10 @@ public: void initLRU(const TargetRegisterInfo &TRI) { assert(MBB->getParent()->getRegInfo().tracksLiveness() && "Candidate's Machine Function must track liveness"); + // Only initialize once. + if (LRUWasSet) + return; + LRUWasSet = true; LRU.init(TRI); LRU.addLiveOuts(*MBB); diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 6a47f705c9a..534ea05f782 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -5101,11 +5101,13 @@ enum MachineOutlinerClass { enum MachineOutlinerMBBFlags { LRUnavailableSomewhere = 0x2, - HasCalls = 0x4 + HasCalls = 0x4, + UnsafeRegsDead = 0x8 }; unsigned AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const { + assert(C.LRUWasSet && "LRU wasn't set?"); MachineFunction *MF = C.getMF(); const AArch64RegisterInfo *ARI = static_cast<const AArch64RegisterInfo *>( MF->getSubtarget().getRegisterInfo()); @@ -5141,9 +5143,8 @@ AArch64InstrInfo::getOutliningCandidateInfo( // Compute liveness information for each candidate, and set FlagsSetInAll. const TargetRegisterInfo &TRI = getRegisterInfo(); std::for_each(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(), - [&TRI, &FlagsSetInAll](outliner::Candidate &C) { + [&FlagsSetInAll](outliner::Candidate &C) { FlagsSetInAll &= C.Flags; - C.initLRU(TRI); }); // According to the AArch64 Procedure Call Standard, the following are @@ -5157,23 +5158,31 @@ AArch64InstrInfo::getOutliningCandidateInfo( // of these registers is live into/across it. Thus, we need to delete // those // candidates. - auto CantGuaranteeValueAcrossCall = [](outliner::Candidate &C) { + auto CantGuaranteeValueAcrossCall = [&TRI](outliner::Candidate &C) { + // If the unsafe registers in this block are all dead, then we don't need + // to compute liveness here. + if (C.Flags & UnsafeRegsDead) + return false; + C.initLRU(TRI); LiveRegUnits LRU = C.LRU; return (!LRU.available(AArch64::W16) || !LRU.available(AArch64::W17) || !LRU.available(AArch64::NZCV)); }; - // Erase every candidate that violates the restrictions above. (It could be - // true that we have viable candidates, so it's not worth bailing out in - // the case that, say, 1 out of 20 candidates violate the restructions.) - RepeatedSequenceLocs.erase(std::remove_if(RepeatedSequenceLocs.begin(), - RepeatedSequenceLocs.end(), - CantGuaranteeValueAcrossCall), - RepeatedSequenceLocs.end()); + // Are there any candidates where those registers are live? + if (!(FlagsSetInAll & UnsafeRegsDead)) { + // Erase every candidate that violates the restrictions above. (It could be + // true that we have viable candidates, so it's not worth bailing out in + // the case that, say, 1 out of 20 candidates violate the restructions.) + RepeatedSequenceLocs.erase(std::remove_if(RepeatedSequenceLocs.begin(), + RepeatedSequenceLocs.end(), + CantGuaranteeValueAcrossCall), + RepeatedSequenceLocs.end()); - // If the sequence doesn't have enough candidates left, then we're done. - if (RepeatedSequenceLocs.size() < 2) - return outliner::OutlinedFunction(); + // If the sequence doesn't have enough candidates left, then we're done. + if (RepeatedSequenceLocs.size() < 2) + return outliner::OutlinedFunction(); + } // At this point, we have only "safe" candidates to outline. Figure out // frame + call instruction information. @@ -5216,7 +5225,8 @@ AArch64InstrInfo::getOutliningCandidateInfo( // to (or exit from) some candidate. else if (std::all_of(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(), - [](outliner::Candidate &C) { + [&TRI](outliner::Candidate &C) { + C.initLRU(TRI); return C.LRU.available(AArch64::LR); })) { FrameID = MachineOutlinerNoLRSave; @@ -5227,7 +5237,8 @@ AArch64InstrInfo::getOutliningCandidateInfo( // LR is live, so we need to save it. Decide whether it should be saved to // the stack, or if it can be saved to a register. else { - if (all_of(RepeatedSequenceLocs, [this](outliner::Candidate &C) { + if (all_of(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) { + C.initLRU(TRI); return findRegisterToSaveLRTo(C); })) { // Every candidate has an available callee-saved register for the save. @@ -5311,6 +5322,11 @@ bool AArch64InstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB, bool W17AvailableInBlock = LRU.available(AArch64::W17); bool NZCVAvailableInBlock = LRU.available(AArch64::NZCV); + // If all of these are dead (and not live out), we know we don't have to check + // them later. + if (W16AvailableInBlock && W17AvailableInBlock && NZCVAvailableInBlock) + Flags |= MachineOutlinerMBBFlags::UnsafeRegsDead; + // Now, add the live outs to the set. LRU.addLiveOuts(MBB); |