forked from OSchip/llvm-project
[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:
parent
2a8a665e1f
commit
27e1754fc9
|
@ -85,6 +85,9 @@ public:
|
||||||
/// Target-specific flags for this Candidate's MBB.
|
/// Target-specific flags for this Candidate's MBB.
|
||||||
unsigned Flags = 0x0;
|
unsigned Flags = 0x0;
|
||||||
|
|
||||||
|
/// True if initLRU has been called on this Candidate.
|
||||||
|
bool LRUWasSet = false;
|
||||||
|
|
||||||
/// Return the number of instructions in this Candidate.
|
/// Return the number of instructions in this Candidate.
|
||||||
unsigned getLength() const { return Len; }
|
unsigned getLength() const { return Len; }
|
||||||
|
|
||||||
|
@ -141,6 +144,10 @@ public:
|
||||||
void initLRU(const TargetRegisterInfo &TRI) {
|
void initLRU(const TargetRegisterInfo &TRI) {
|
||||||
assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
|
assert(MBB->getParent()->getRegInfo().tracksLiveness() &&
|
||||||
"Candidate's Machine Function must track liveness");
|
"Candidate's Machine Function must track liveness");
|
||||||
|
// Only initialize once.
|
||||||
|
if (LRUWasSet)
|
||||||
|
return;
|
||||||
|
LRUWasSet = true;
|
||||||
LRU.init(TRI);
|
LRU.init(TRI);
|
||||||
LRU.addLiveOuts(*MBB);
|
LRU.addLiveOuts(*MBB);
|
||||||
|
|
||||||
|
|
|
@ -5101,11 +5101,13 @@ enum MachineOutlinerClass {
|
||||||
|
|
||||||
enum MachineOutlinerMBBFlags {
|
enum MachineOutlinerMBBFlags {
|
||||||
LRUnavailableSomewhere = 0x2,
|
LRUnavailableSomewhere = 0x2,
|
||||||
HasCalls = 0x4
|
HasCalls = 0x4,
|
||||||
|
UnsafeRegsDead = 0x8
|
||||||
};
|
};
|
||||||
|
|
||||||
unsigned
|
unsigned
|
||||||
AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const {
|
AArch64InstrInfo::findRegisterToSaveLRTo(const outliner::Candidate &C) const {
|
||||||
|
assert(C.LRUWasSet && "LRU wasn't set?");
|
||||||
MachineFunction *MF = C.getMF();
|
MachineFunction *MF = C.getMF();
|
||||||
const AArch64RegisterInfo *ARI = static_cast<const AArch64RegisterInfo *>(
|
const AArch64RegisterInfo *ARI = static_cast<const AArch64RegisterInfo *>(
|
||||||
MF->getSubtarget().getRegisterInfo());
|
MF->getSubtarget().getRegisterInfo());
|
||||||
|
@ -5141,9 +5143,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
|
||||||
// Compute liveness information for each candidate, and set FlagsSetInAll.
|
// Compute liveness information for each candidate, and set FlagsSetInAll.
|
||||||
const TargetRegisterInfo &TRI = getRegisterInfo();
|
const TargetRegisterInfo &TRI = getRegisterInfo();
|
||||||
std::for_each(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
|
std::for_each(RepeatedSequenceLocs.begin(), RepeatedSequenceLocs.end(),
|
||||||
[&TRI, &FlagsSetInAll](outliner::Candidate &C) {
|
[&FlagsSetInAll](outliner::Candidate &C) {
|
||||||
FlagsSetInAll &= C.Flags;
|
FlagsSetInAll &= C.Flags;
|
||||||
C.initLRU(TRI);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// According to the AArch64 Procedure Call Standard, the following are
|
// 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
|
// of these registers is live into/across it. Thus, we need to delete
|
||||||
// those
|
// those
|
||||||
// candidates.
|
// 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;
|
LiveRegUnits LRU = C.LRU;
|
||||||
return (!LRU.available(AArch64::W16) || !LRU.available(AArch64::W17) ||
|
return (!LRU.available(AArch64::W16) || !LRU.available(AArch64::W17) ||
|
||||||
!LRU.available(AArch64::NZCV));
|
!LRU.available(AArch64::NZCV));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Erase every candidate that violates the restrictions above. (It could be
|
// Are there any candidates where those registers are live?
|
||||||
// true that we have viable candidates, so it's not worth bailing out in
|
if (!(FlagsSetInAll & UnsafeRegsDead)) {
|
||||||
// the case that, say, 1 out of 20 candidates violate the restructions.)
|
// Erase every candidate that violates the restrictions above. (It could be
|
||||||
RepeatedSequenceLocs.erase(std::remove_if(RepeatedSequenceLocs.begin(),
|
// true that we have viable candidates, so it's not worth bailing out in
|
||||||
RepeatedSequenceLocs.end(),
|
// the case that, say, 1 out of 20 candidates violate the restructions.)
|
||||||
CantGuaranteeValueAcrossCall),
|
RepeatedSequenceLocs.erase(std::remove_if(RepeatedSequenceLocs.begin(),
|
||||||
RepeatedSequenceLocs.end());
|
RepeatedSequenceLocs.end(),
|
||||||
|
CantGuaranteeValueAcrossCall),
|
||||||
|
RepeatedSequenceLocs.end());
|
||||||
|
|
||||||
// If the sequence doesn't have enough candidates left, then we're done.
|
// If the sequence doesn't have enough candidates left, then we're done.
|
||||||
if (RepeatedSequenceLocs.size() < 2)
|
if (RepeatedSequenceLocs.size() < 2)
|
||||||
return outliner::OutlinedFunction();
|
return outliner::OutlinedFunction();
|
||||||
|
}
|
||||||
|
|
||||||
// At this point, we have only "safe" candidates to outline. Figure out
|
// At this point, we have only "safe" candidates to outline. Figure out
|
||||||
// frame + call instruction information.
|
// frame + call instruction information.
|
||||||
|
@ -5216,7 +5225,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
|
||||||
// to (or exit from) some candidate.
|
// to (or exit from) some candidate.
|
||||||
else if (std::all_of(RepeatedSequenceLocs.begin(),
|
else if (std::all_of(RepeatedSequenceLocs.begin(),
|
||||||
RepeatedSequenceLocs.end(),
|
RepeatedSequenceLocs.end(),
|
||||||
[](outliner::Candidate &C) {
|
[&TRI](outliner::Candidate &C) {
|
||||||
|
C.initLRU(TRI);
|
||||||
return C.LRU.available(AArch64::LR);
|
return C.LRU.available(AArch64::LR);
|
||||||
})) {
|
})) {
|
||||||
FrameID = MachineOutlinerNoLRSave;
|
FrameID = MachineOutlinerNoLRSave;
|
||||||
|
@ -5227,7 +5237,8 @@ AArch64InstrInfo::getOutliningCandidateInfo(
|
||||||
// LR is live, so we need to save it. Decide whether it should be saved to
|
// 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.
|
// the stack, or if it can be saved to a register.
|
||||||
else {
|
else {
|
||||||
if (all_of(RepeatedSequenceLocs, [this](outliner::Candidate &C) {
|
if (all_of(RepeatedSequenceLocs, [this, &TRI](outliner::Candidate &C) {
|
||||||
|
C.initLRU(TRI);
|
||||||
return findRegisterToSaveLRTo(C);
|
return findRegisterToSaveLRTo(C);
|
||||||
})) {
|
})) {
|
||||||
// Every candidate has an available callee-saved register for the save.
|
// 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 W17AvailableInBlock = LRU.available(AArch64::W17);
|
||||||
bool NZCVAvailableInBlock = LRU.available(AArch64::NZCV);
|
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.
|
// Now, add the live outs to the set.
|
||||||
LRU.addLiveOuts(MBB);
|
LRU.addLiveOuts(MBB);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue