"Target didn't implement TargetInstrInfo::getOutliningType!");
}
- /// Returns target-defined flags defining properties of the MBB for
- /// the outliner.
- virtual unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const {
- return 0x0;
+ /// Optional target hook that returns true if \p MBB is safe to outline from,
+ /// and returns any target-specific information in \p Flags.
+ virtual bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
+ unsigned &Flags) const {
+ return true;
}
/// Insert a custom frame for outlined functions.
/// \param TII \p TargetInstrInfo for the function.
void convertToUnsignedVec(MachineBasicBlock &MBB,
const TargetInstrInfo &TII) {
- unsigned Flags = TII.getMachineOutlinerMBBFlags(MBB);
+ unsigned Flags;
+
+ // Don't even map in this case.
+ if (!TII.isMBBSafeToOutlineFrom(MBB, Flags))
+ return;
+
MachineBasicBlock::iterator It = MBB.begin();
// The number of instructions in this block that will be considered for
return true;
}
-unsigned
-AArch64InstrInfo::getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const {
- unsigned Flags = 0x0;
- // Check if there's a call inside this MachineBasicBlock. If there is, then
- // set a flag.
- if (any_of(MBB, [](MachineInstr &MI) { return MI.isCall(); }))
- Flags |= MachineOutlinerMBBFlags::HasCalls;
-
+bool AArch64InstrInfo::isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
+ unsigned &Flags) const {
// Check if LR is available through all of the MBB. If it's not, then set
// a flag.
assert(MBB.getParent()->getRegInfo().tracksLiveness() &&
"Suitable Machine Function for outlining must track liveness");
- LiveRegUnits LRU(getRegisterInfo());
- LRU.addLiveOuts(MBB);
+ LiveRegUnits ModifiedRegUnits(getRegisterInfo());
+ LiveRegUnits UsedRegUnits(getRegisterInfo());
+ ModifiedRegUnits.addLiveOuts(MBB);
+ UsedRegUnits.addLiveOuts(MBB);
+ const TargetRegisterInfo *TRI = &getRegisterInfo();
- std::for_each(MBB.rbegin(),
- MBB.rend(),
- [&LRU](MachineInstr &MI) { LRU.accumulate(MI); });
+ std::for_each(MBB.rbegin(), MBB.rend(),
+ [&ModifiedRegUnits, &UsedRegUnits, &TRI](MachineInstr &MI) {
+ LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits,
+ UsedRegUnits, TRI);
+ });
+
+ // If one of these registers is live out of the MBB, but not modified in the
+ // MBB, then we can't outline.
+ if ((ModifiedRegUnits.available(AArch64::W16) &&
+ !UsedRegUnits.available(AArch64::W16)) ||
+ (ModifiedRegUnits.available(AArch64::W17) &&
+ !UsedRegUnits.available(AArch64::W17)) ||
+ (ModifiedRegUnits.available(AArch64::NZCV) &&
+ !UsedRegUnits.available(AArch64::NZCV)))
+ return false;
- if (!LRU.available(AArch64::LR))
- Flags |= MachineOutlinerMBBFlags::LRUnavailableSomewhere;
+ // Check if there's a call inside this MachineBasicBlock. If there is, then
+ // set a flag.
+ if (any_of(MBB, [](MachineInstr &MI) { return MI.isCall(); }))
+ Flags |= MachineOutlinerMBBFlags::HasCalls;
+
+ if (!ModifiedRegUnits.available(AArch64::LR) ||
+ !UsedRegUnits.available(AArch64::LR))
+ Flags |= MachineOutlinerMBBFlags::LRUnavailableSomewhere;
- return Flags;
+ return true;
}
outliner::InstrType
std::vector<outliner::Candidate> &RepeatedSequenceLocs) const override;
outliner::InstrType
getOutliningType(MachineBasicBlock::iterator &MIT, unsigned Flags) const override;
- unsigned getMachineOutlinerMBBFlags(MachineBasicBlock &MBB) const override;
+ bool isMBBSafeToOutlineFrom(MachineBasicBlock &MBB,
+ unsigned &Flags) const override;
void buildOutlinedFrame(MachineBasicBlock &MBB, MachineFunction &MF,
const outliner::OutlinedFunction &OF) const override;
MachineBasicBlock::iterator