DB.finalize();
}
+ // Outlined functions shouldn't preserve liveness.
+ MF.getProperties().reset(MachineFunctionProperties::Property::TracksLiveness);
MF.getRegInfo().freezeReservedRegs(MF);
return &MF;
}
MachineBasicBlock::iterator EndIt = Mapper.InstrList[EndIdx];
assert(EndIt != MBB->end() && "EndIt out of bounds!");
- EndIt++; // Erase needs one past the end index.
-
// Does this candidate have a function yet?
if (!OF.MF) {
OF.MF = createOutlinedFunction(M, OF, Mapper);
const TargetInstrInfo &TII = *STI.getInstrInfo();
// Insert a call to the new function and erase the old sequence.
- TII.insertOutlinedCall(M, *MBB, StartIt, *MF, C.MInfo);
+ auto CallInst = TII.insertOutlinedCall(M, *MBB, StartIt, *MF, C.MInfo);
StartIt = Mapper.InstrList[C.getStartIdx()];
- MBB->erase(StartIt, EndIt);
+ // If the caller tracks liveness, then we need to make sure that anything
+ // we outline doesn't break liveness assumptions.
+ // The outlined functions themselves currently don't track liveness, but
+ // we should make sure that the ranges we yank things out of aren't
+ // wrong.
+ if (MBB->getParent()->getProperties().hasProperty(
+ MachineFunctionProperties::Property::TracksLiveness)) {
+ // Helper lambda for adding implicit def operands to the call instruction.
+ auto CopyDefs = [&CallInst](MachineInstr &MI) {
+ for (MachineOperand &MOP : MI.operands()) {
+ // Skip over anything that isn't a register.
+ if (!MOP.isReg())
+ continue;
+
+ // If it's a def, add it to the call instruction.
+ if (MOP.isDef())
+ CallInst->addOperand(
+ MachineOperand::CreateReg(MOP.getReg(), true, /* isDef = true */
+ true /* isImp = true */));
+ }
+ };
+
+ // Copy over the defs in the outlined range.
+ // First inst in outlined range <-- Anything that's defined in this
+ // ... .. range has to be added as an implicit
+ // Last inst in outlined range <-- def to the call instruction.
+ std::for_each(CallInst, EndIt, CopyDefs);
+ }
+
+ EndIt++; // Erase needs one past the end index.
+ MBB->erase(StartIt, EndIt);
OutlinedSomething = true;
// Statistics.
return It;
}
+ // We want to return the spot where we inserted the call.
+ MachineBasicBlock::iterator CallPt;
+
// We have a default call. Save the link register.
MachineInstr *STRXpre = BuildMI(MF, DebugLoc(), get(AArch64::STRXpre))
.addReg(AArch64::SP, RegState::Define)
// Insert the call.
It = MBB.insert(It, BuildMI(MF, DebugLoc(), get(AArch64::BL))
.addGlobalAddress(M.getNamedValue(MF.getName())));
-
+ CallPt = It;
It++;
// Restore the link register.
.addImm(16);
It = MBB.insert(It, LDRXpost);
- return It;
+ return CallPt;
}