[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
This commit is contained in:
Jessica Paquette 2018-11-14 22:23:38 +00:00
parent 2a8a665e1f
commit 27e1754fc9
2 changed files with 39 additions and 16 deletions

View File

@ -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);

View File

@ -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);