summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorJessica Paquette <jpaquette@apple.com>2018-06-27 17:43:27 +0000
committerJessica Paquette <jpaquette@apple.com>2018-06-27 17:43:27 +0000
commitf472f6159a0d42d6f2144c457ea32543ff5410a1 (patch)
treeb1c2aadead5ce6f16a48169632f548028c666eb3 /llvm/lib
parentd8ba8ae875dfa20b573425e1a0764d4c635e04f4 (diff)
downloadbcm5719-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.cpp1
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.cpp65
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstrInfo.h3
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(
OpenPOWER on IntegriCloud