diff options
author | Jessica Paquette <jpaquette@apple.com> | 2018-06-27 17:43:27 +0000 |
---|---|---|
committer | Jessica Paquette <jpaquette@apple.com> | 2018-06-27 17:43:27 +0000 |
commit | f472f6159a0d42d6f2144c457ea32543ff5410a1 (patch) | |
tree | b1c2aadead5ce6f16a48169632f548028c666eb3 /llvm/lib | |
parent | d8ba8ae875dfa20b573425e1a0764d4c635e04f4 (diff) | |
download | bcm5719-llvm-f472f6159a0d42d6f2144c457ea32543ff5410a1.tar.gz bcm5719-llvm-f472f6159a0d42d6f2144c457ea32543ff5410a1.zip |
[MachineOutliner] Don't outline sequences where x16/x17/nzcv are live across
It isn't safe to outline sequences of instructions where x16/x17/nzcv live
across the sequence.
This teaches the outliner to check whether or not a specific canidate has
x16/x17/nzcv live across it and discard the candidate in the case that that is
true.
https://bugs.llvm.org/show_bug.cgi?id=37573
https://reviews.llvm.org/D47655
llvm-svn: 335758
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/MachineOutliner.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 65 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64InstrInfo.h | 3 |
3 files changed, 41 insertions, 28 deletions
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp index fde35202a34..8f78240e1f7 100644 --- a/llvm/lib/CodeGen/MachineOutliner.cpp +++ b/llvm/lib/CodeGen/MachineOutliner.cpp @@ -65,7 +65,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DIBuilder.h" #include "llvm/IR/IRBuilder.h" diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 1ad51d5a449..58bd3496d4b 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -19,7 +19,6 @@ #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" @@ -4928,25 +4927,6 @@ enum MachineOutlinerMBBFlags { HasCalls = 0x4 }; -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); -} - outliner::TargetCostInfo AArch64InstrInfo::getOutlininingCandidateInfo( std::vector<outliner::Candidate> &RepeatedSequenceLocs) const { @@ -4961,8 +4941,38 @@ AArch64InstrInfo::getOutlininingCandidateInfo( unsigned NumBytesForCall = 12; unsigned NumBytesToCreateFrame = 4; - auto DoesntNeedLRSave = - [this](outliner::Candidate &I) {return canOutlineWithoutLRSave(I.back());}; + // Compute liveness information for each candidate. + const TargetRegisterInfo &TRI = getRegisterInfo(); + std::for_each(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(), + [&TRI](outliner::Candidate &C) { C.initLRU(TRI); }); + + // According to the AArch64 Procedure Call Standard, the following are + // undefined on entry/exit from a function call: + // + // * Registers x16, x17, (and thus w16, w17) + // * Condition codes (and thus the NZCV register) + // + // Because if this, we can't outline any sequence of instructions where + // one + // of these registers is live into/across it. Thus, we need to delete + // those + // candidates. + auto CantGuaranteeValueAcrossCall = [](outliner::Candidate &C) { + 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()); + + // At this point, we have only "safe" candidates to outline. Figure out + // frame + call instruction information. unsigned LastInstrOpcode = RepeatedSequenceLocs[0].back()->getOpcode(); @@ -4983,8 +4993,15 @@ AArch64InstrInfo::getOutlininingCandidateInfo( NumBytesToCreateFrame = 0; } - else if (std::all_of(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(), - DoesntNeedLRSave)) { + // Make sure that LR isn't live on entry to this candidate. The only + // instructions that use LR that could possibly appear in a repeated sequence + // are calls. Therefore, we only have to check and see if LR is dead on entry + // to (or exit from) some candidate. + else if (std::all_of(RepeatedSequenceLocs.begin(), + RepeatedSequenceLocs.end(), + [](outliner::Candidate &C) { + return C.LRU.available(AArch64::LR); + })) { CallID = MachineOutlinerNoLRSave; FrameID = MachineOutlinerNoLRSave; NumBytesForCall = 4; diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.h b/llvm/lib/Target/AArch64/AArch64InstrInfo.h index 634aaa21d1b..0e5e7976f93 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.h +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.h @@ -238,9 +238,6 @@ public: /// AArch64 supports the MachineOutliner. bool useMachineOutliner() const override { return true; } - - bool - canOutlineWithoutLRSave(MachineBasicBlock::iterator &CallInsertionPt) const; bool isFunctionSafeToOutlineFrom(MachineFunction &MF, bool OutlineFromLinkOnceODRs) const override; outliner::TargetCostInfo getOutlininingCandidateInfo( |