From 27e1754fc9876562aee4df252350a415309fcfb9 Mon Sep 17 00:00:00 2001 From: Jessica Paquette Date: Wed, 14 Nov 2018 22:23:38 +0000 Subject: [PATCH] [MachineOutliner][NFC] Don't compute liveness if X16/X17/NZCV are unused Using the MBB flags, we can tell if X16/X17/NZCV are unused in a block, and also not live out. If this holds for all MBBs, then we can avoid checking for liveness on that candidate. Furthermore, if it holds for an individual candidate's MBB, then we can avoid checking for liveness on that candidate. llvm-svn: 346901 --- llvm/include/llvm/CodeGen/MachineOutliner.h | 7 +++ 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 2bd39b2392d2..01d660a47a66 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 6a47f705c9aa..534ea05f7829 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( 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);