forked from OSchip/llvm-project
[Hexagon] Delay emission of CFI instructions
Emit the CFI instructions after all code transformation have been done. This will avoid any interference between CFI instructions and packetization. llvm-svn: 250714
This commit is contained in:
parent
e734195ce3
commit
db8677067c
|
@ -147,6 +147,45 @@ static cl::opt<unsigned> ShrinkLimit("shrink-frame-limit", cl::init(UINT_MAX),
|
||||||
cl::Hidden, cl::ZeroOrMore, cl::desc("Max count of stack frame "
|
cl::Hidden, cl::ZeroOrMore, cl::desc("Max count of stack frame "
|
||||||
"shrink-wraps"));
|
"shrink-wraps"));
|
||||||
|
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
void initializeHexagonCallFrameInformationPass(PassRegistry&);
|
||||||
|
FunctionPass *createHexagonCallFrameInformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class HexagonCallFrameInformation : public MachineFunctionPass {
|
||||||
|
public:
|
||||||
|
static char ID;
|
||||||
|
HexagonCallFrameInformation() : MachineFunctionPass(ID) {
|
||||||
|
PassRegistry &PR = *PassRegistry::getPassRegistry();
|
||||||
|
initializeHexagonCallFrameInformationPass(PR);
|
||||||
|
}
|
||||||
|
bool runOnMachineFunction(MachineFunction &MF) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
char HexagonCallFrameInformation::ID = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HexagonCallFrameInformation::runOnMachineFunction(MachineFunction &MF) {
|
||||||
|
auto &HFI = *MF.getSubtarget<HexagonSubtarget>().getFrameLowering();
|
||||||
|
bool NeedCFI = MF.getMMI().hasDebugInfo() ||
|
||||||
|
MF.getFunction()->needsUnwindTableEntry();
|
||||||
|
|
||||||
|
if (!NeedCFI)
|
||||||
|
return false;
|
||||||
|
HFI.insertCFIInstructions(MF);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITIALIZE_PASS(HexagonCallFrameInformation, "hexagon-cfi",
|
||||||
|
"Hexagon call frame information", false, false)
|
||||||
|
|
||||||
|
FunctionPass *llvm::createHexagonCallFrameInformation() {
|
||||||
|
return new HexagonCallFrameInformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
/// Map a register pair Reg to the subregister that has the greater "number",
|
/// Map a register pair Reg to the subregister that has the greater "number",
|
||||||
/// i.e. D3 (aka R7:6) will be mapped to R7, etc.
|
/// i.e. D3 (aka R7:6) will be mapped to R7, etc.
|
||||||
|
@ -383,10 +422,8 @@ void HexagonFrameLowering::emitPrologue(MachineFunction &MF,
|
||||||
void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB) const {
|
void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB) const {
|
||||||
MachineFunction &MF = *MBB.getParent();
|
MachineFunction &MF = *MBB.getParent();
|
||||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
MachineModuleInfo &MMI = MF.getMMI();
|
|
||||||
MachineBasicBlock::iterator MBBI = MBB.begin();
|
|
||||||
auto &HTM = static_cast<const HexagonTargetMachine&>(MF.getTarget());
|
auto &HTM = static_cast<const HexagonTargetMachine&>(MF.getTarget());
|
||||||
auto &HST = static_cast<const HexagonSubtarget&>(MF.getSubtarget());
|
auto &HST = MF.getSubtarget<HexagonSubtarget>();
|
||||||
auto &HII = *HST.getInstrInfo();
|
auto &HII = *HST.getInstrInfo();
|
||||||
auto &HRI = *HST.getRegisterInfo();
|
auto &HRI = *HST.getRegisterInfo();
|
||||||
DebugLoc dl;
|
DebugLoc dl;
|
||||||
|
@ -405,10 +442,6 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB) const {
|
||||||
|
|
||||||
bool AlignStack = (MaxAlign > getStackAlignment());
|
bool AlignStack = (MaxAlign > getStackAlignment());
|
||||||
|
|
||||||
// Check if frame moves are needed for EH.
|
|
||||||
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
|
||||||
MF.getFunction()->needsUnwindTableEntry();
|
|
||||||
|
|
||||||
// Get the number of bytes to allocate from the FrameInfo.
|
// Get the number of bytes to allocate from the FrameInfo.
|
||||||
unsigned NumBytes = MFI->getStackSize();
|
unsigned NumBytes = MFI->getStackSize();
|
||||||
unsigned SP = HRI.getStackRegister();
|
unsigned SP = HRI.getStackRegister();
|
||||||
|
@ -469,89 +502,6 @@ void HexagonFrameLowering::insertPrologueInBlock(MachineBasicBlock &MBB) const {
|
||||||
.addReg(SP)
|
.addReg(SP)
|
||||||
.addImm(-int64_t(MaxAlign));
|
.addImm(-int64_t(MaxAlign));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needsFrameMoves) {
|
|
||||||
std::vector<MCCFIInstruction> Instructions = MMI.getFrameInstructions();
|
|
||||||
MCSymbol *FrameLabel = MMI.getContext().createTempSymbol();
|
|
||||||
|
|
||||||
// Advance CFA. DW_CFA_def_cfa
|
|
||||||
unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(), true);
|
|
||||||
unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(), true);
|
|
||||||
|
|
||||||
// CFA = FP + 8
|
|
||||||
unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfa(
|
|
||||||
FrameLabel, DwFPReg, -8));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(CFIIndex);
|
|
||||||
|
|
||||||
// R31 (return addr) = CFA - #4
|
|
||||||
CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset(
|
|
||||||
FrameLabel, DwRAReg, -4));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(CFIIndex);
|
|
||||||
|
|
||||||
// R30 (frame ptr) = CFA - #8)
|
|
||||||
CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset(
|
|
||||||
FrameLabel, DwFPReg, -8));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(CFIIndex);
|
|
||||||
|
|
||||||
unsigned int regsToMove[] = {
|
|
||||||
Hexagon::R1, Hexagon::R0, Hexagon::R3, Hexagon::R2,
|
|
||||||
Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,
|
|
||||||
Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,
|
|
||||||
Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,
|
|
||||||
Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9, Hexagon::D10,
|
|
||||||
Hexagon::D11, Hexagon::D12, Hexagon::D13, Hexagon::NoRegister
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
|
||||||
|
|
||||||
for (unsigned i = 0; regsToMove[i] != Hexagon::NoRegister; ++i) {
|
|
||||||
for (unsigned I = 0, E = CSI.size(); I < E; ++I) {
|
|
||||||
if (CSI[I].getReg() == regsToMove[i]) {
|
|
||||||
// Subtract 8 to make room for R30 and R31, which are added above.
|
|
||||||
unsigned FrameReg;
|
|
||||||
int64_t Offset =
|
|
||||||
getFrameIndexReference(MF, CSI[I].getFrameIdx(), FrameReg) - 8;
|
|
||||||
|
|
||||||
assert(FrameReg == HRI.getFrameRegister() &&
|
|
||||||
"FrameReg from getFrameIndexReference should be the default "
|
|
||||||
"frame reg");
|
|
||||||
|
|
||||||
if (regsToMove[i] < Hexagon::D0 || regsToMove[i] > Hexagon::D15) {
|
|
||||||
unsigned DwarfReg = HRI.getDwarfRegNum(regsToMove[i], true);
|
|
||||||
unsigned CFIIndex = MMI.addFrameInst(
|
|
||||||
MCCFIInstruction::createOffset(FrameLabel,
|
|
||||||
DwarfReg, Offset));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(CFIIndex);
|
|
||||||
} else {
|
|
||||||
// Split the double regs into subregs, and generate appropriate
|
|
||||||
// cfi_offsets.
|
|
||||||
// The only reason, we are split double regs is, llvm-mc does not
|
|
||||||
// understand paired registers for cfi_offset.
|
|
||||||
// Eg .cfi_offset r1:0, -64
|
|
||||||
unsigned HiReg = getMax32BitSubRegister(regsToMove[i], HRI);
|
|
||||||
unsigned LoReg = getMax32BitSubRegister(regsToMove[i], HRI, false);
|
|
||||||
unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg, true);
|
|
||||||
unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg, true);
|
|
||||||
unsigned HiCFIIndex = MMI.addFrameInst(
|
|
||||||
MCCFIInstruction::createOffset(FrameLabel,
|
|
||||||
HiDwarfReg, Offset+4));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(HiCFIIndex);
|
|
||||||
unsigned LoCFIIndex = MMI.addFrameInst(
|
|
||||||
MCCFIInstruction::createOffset(FrameLabel,
|
|
||||||
LoDwarfReg, Offset));
|
|
||||||
BuildMI(MBB, MBBI, dl, HII.get(TargetOpcode::CFI_INSTRUCTION))
|
|
||||||
.addCFIIndex(LoCFIIndex);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} // for CSI.size()
|
|
||||||
} // for regsToMove
|
|
||||||
} // needsFrameMoves
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
|
void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
|
||||||
|
@ -636,6 +586,128 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool IsAllocFrame(MachineBasicBlock::const_iterator It) {
|
||||||
|
if (!It->isBundle())
|
||||||
|
return It->getOpcode() == Hexagon::S2_allocframe;
|
||||||
|
auto End = It->getParent()->instr_end();
|
||||||
|
MachineBasicBlock::const_instr_iterator I = It.getInstrIterator();
|
||||||
|
while (++I != End && I->isBundled())
|
||||||
|
if (I->getOpcode() == Hexagon::S2_allocframe)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator FindAllocFrame(MachineBasicBlock &B) {
|
||||||
|
for (auto &I : B)
|
||||||
|
if (IsAllocFrame(I))
|
||||||
|
return I;
|
||||||
|
return B.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HexagonFrameLowering::insertCFIInstructions(MachineFunction &MF) const {
|
||||||
|
for (auto &B : MF) {
|
||||||
|
auto AF = FindAllocFrame(B);
|
||||||
|
if (AF == B.end())
|
||||||
|
continue;
|
||||||
|
insertCFIInstructionsAt(B, ++AF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void HexagonFrameLowering::insertCFIInstructionsAt(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator At) const {
|
||||||
|
MachineFunction &MF = *MBB.getParent();
|
||||||
|
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
|
MachineModuleInfo &MMI = MF.getMMI();
|
||||||
|
auto &HST = MF.getSubtarget<HexagonSubtarget>();
|
||||||
|
auto &HII = *HST.getInstrInfo();
|
||||||
|
auto &HRI = *HST.getRegisterInfo();
|
||||||
|
|
||||||
|
// If CFI instructions have debug information attached, something goes
|
||||||
|
// wrong with the final assembly generation: the prolog_end is placed
|
||||||
|
// in a wrong location.
|
||||||
|
DebugLoc DL;
|
||||||
|
const MCInstrDesc &CFID = HII.get(TargetOpcode::CFI_INSTRUCTION);
|
||||||
|
|
||||||
|
MCSymbol *FrameLabel = MMI.getContext().createTempSymbol();
|
||||||
|
|
||||||
|
// Advance CFA. DW_CFA_def_cfa
|
||||||
|
unsigned DwFPReg = HRI.getDwarfRegNum(HRI.getFrameRegister(), true);
|
||||||
|
unsigned DwRAReg = HRI.getDwarfRegNum(HRI.getRARegister(), true);
|
||||||
|
|
||||||
|
// CFA = FP + 8
|
||||||
|
auto DefCfa = MCCFIInstruction::createDefCfa(FrameLabel, DwFPReg, -8);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(DefCfa));
|
||||||
|
|
||||||
|
// R31 (return addr) = CFA - #4
|
||||||
|
auto OffR31 = MCCFIInstruction::createOffset(FrameLabel, DwRAReg, -4);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(OffR31));
|
||||||
|
|
||||||
|
// R30 (frame ptr) = CFA - #8)
|
||||||
|
auto OffR30 = MCCFIInstruction::createOffset(FrameLabel, DwFPReg, -8);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(OffR30));
|
||||||
|
|
||||||
|
static unsigned int RegsToMove[] = {
|
||||||
|
Hexagon::R1, Hexagon::R0, Hexagon::R3, Hexagon::R2,
|
||||||
|
Hexagon::R17, Hexagon::R16, Hexagon::R19, Hexagon::R18,
|
||||||
|
Hexagon::R21, Hexagon::R20, Hexagon::R23, Hexagon::R22,
|
||||||
|
Hexagon::R25, Hexagon::R24, Hexagon::R27, Hexagon::R26,
|
||||||
|
Hexagon::D0, Hexagon::D1, Hexagon::D8, Hexagon::D9,
|
||||||
|
Hexagon::D10, Hexagon::D11, Hexagon::D12, Hexagon::D13,
|
||||||
|
Hexagon::NoRegister
|
||||||
|
};
|
||||||
|
|
||||||
|
const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo();
|
||||||
|
|
||||||
|
for (unsigned i = 0; RegsToMove[i] != Hexagon::NoRegister; ++i) {
|
||||||
|
unsigned Reg = RegsToMove[i];
|
||||||
|
auto IfR = [Reg] (const CalleeSavedInfo &C) -> bool {
|
||||||
|
return C.getReg() == Reg;
|
||||||
|
};
|
||||||
|
auto F = std::find_if(CSI.begin(), CSI.end(), IfR);
|
||||||
|
if (F == CSI.end())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Subtract 8 to make room for R30 and R31, which are added above.
|
||||||
|
unsigned FrameReg;
|
||||||
|
int64_t Offset = getFrameIndexReference(MF, F->getFrameIdx(), FrameReg) - 8;
|
||||||
|
|
||||||
|
if (Reg < Hexagon::D0 || Reg > Hexagon::D15) {
|
||||||
|
unsigned DwarfReg = HRI.getDwarfRegNum(Reg, true);
|
||||||
|
auto OffReg = MCCFIInstruction::createOffset(FrameLabel, DwarfReg,
|
||||||
|
Offset);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(OffReg));
|
||||||
|
} else {
|
||||||
|
// Split the double regs into subregs, and generate appropriate
|
||||||
|
// cfi_offsets.
|
||||||
|
// The only reason, we are split double regs is, llvm-mc does not
|
||||||
|
// understand paired registers for cfi_offset.
|
||||||
|
// Eg .cfi_offset r1:0, -64
|
||||||
|
|
||||||
|
unsigned HiReg = HRI.getSubReg(Reg, Hexagon::subreg_hireg);
|
||||||
|
unsigned LoReg = HRI.getSubReg(Reg, Hexagon::subreg_loreg);
|
||||||
|
unsigned HiDwarfReg = HRI.getDwarfRegNum(HiReg, true);
|
||||||
|
unsigned LoDwarfReg = HRI.getDwarfRegNum(LoReg, true);
|
||||||
|
auto OffHi = MCCFIInstruction::createOffset(FrameLabel, HiDwarfReg,
|
||||||
|
Offset+4);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(OffHi));
|
||||||
|
auto OffLo = MCCFIInstruction::createOffset(FrameLabel, LoDwarfReg,
|
||||||
|
Offset);
|
||||||
|
BuildMI(MBB, At, DL, CFID)
|
||||||
|
.addCFIIndex(MMI.addFrameInst(OffLo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
|
bool HexagonFrameLowering::hasFP(const MachineFunction &MF) const {
|
||||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||||
const HexagonMachineFunctionInfo *FuncInfo =
|
const HexagonMachineFunctionInfo *FuncInfo =
|
||||||
|
@ -742,7 +814,7 @@ bool HexagonFrameLowering::insertCSRSpillsInBlock(MachineBasicBlock &MBB,
|
||||||
|
|
||||||
MachineBasicBlock::iterator MI = MBB.begin();
|
MachineBasicBlock::iterator MI = MBB.begin();
|
||||||
MachineFunction &MF = *MBB.getParent();
|
MachineFunction &MF = *MBB.getParent();
|
||||||
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
|
||||||
|
|
||||||
if (useSpillFunction(MF, CSI)) {
|
if (useSpillFunction(MF, CSI)) {
|
||||||
unsigned MaxReg = getMaxCalleeSavedReg(CSI, HRI);
|
unsigned MaxReg = getMaxCalleeSavedReg(CSI, HRI);
|
||||||
|
@ -750,7 +822,7 @@ bool HexagonFrameLowering::insertCSRSpillsInBlock(MachineBasicBlock &MBB,
|
||||||
// Call spill function.
|
// Call spill function.
|
||||||
DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
|
DebugLoc DL = MI != MBB.end() ? MI->getDebugLoc() : DebugLoc();
|
||||||
MachineInstr *SaveRegsCall =
|
MachineInstr *SaveRegsCall =
|
||||||
BuildMI(MBB, MI, DL, TII.get(Hexagon::SAVE_REGISTERS_CALL_V4))
|
BuildMI(MBB, MI, DL, HII.get(Hexagon::SAVE_REGISTERS_CALL_V4))
|
||||||
.addExternalSymbol(SpillFun);
|
.addExternalSymbol(SpillFun);
|
||||||
// Add callee-saved registers as use.
|
// Add callee-saved registers as use.
|
||||||
addCalleeSaveRegistersAsImpOperand(SaveRegsCall, MaxReg, false);
|
addCalleeSaveRegistersAsImpOperand(SaveRegsCall, MaxReg, false);
|
||||||
|
@ -768,7 +840,7 @@ bool HexagonFrameLowering::insertCSRSpillsInBlock(MachineBasicBlock &MBB,
|
||||||
bool IsKill = !HRI.isEHReturnCalleeSaveReg(Reg);
|
bool IsKill = !HRI.isEHReturnCalleeSaveReg(Reg);
|
||||||
int FI = CSI[i].getFrameIdx();
|
int FI = CSI[i].getFrameIdx();
|
||||||
const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);
|
const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);
|
||||||
TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, FI, RC, &HRI);
|
HII.storeRegToStackSlot(MBB, MI, Reg, IsKill, FI, RC, &HRI);
|
||||||
if (IsKill)
|
if (IsKill)
|
||||||
MBB.addLiveIn(Reg);
|
MBB.addLiveIn(Reg);
|
||||||
}
|
}
|
||||||
|
@ -783,7 +855,7 @@ bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &MBB,
|
||||||
|
|
||||||
MachineBasicBlock::iterator MI = MBB.getFirstTerminator();
|
MachineBasicBlock::iterator MI = MBB.getFirstTerminator();
|
||||||
MachineFunction &MF = *MBB.getParent();
|
MachineFunction &MF = *MBB.getParent();
|
||||||
const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();
|
auto &HII = *MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
|
||||||
|
|
||||||
if (useRestoreFunction(MF, CSI)) {
|
if (useRestoreFunction(MF, CSI)) {
|
||||||
bool HasTC = hasTailCall(MBB) || !hasReturn(MBB);
|
bool HasTC = hasTailCall(MBB) || !hasReturn(MBB);
|
||||||
|
@ -798,14 +870,14 @@ bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &MBB,
|
||||||
|
|
||||||
if (HasTC) {
|
if (HasTC) {
|
||||||
unsigned ROpc = Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
|
unsigned ROpc = Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4;
|
||||||
DeallocCall = BuildMI(MBB, MI, DL, TII.get(ROpc))
|
DeallocCall = BuildMI(MBB, MI, DL, HII.get(ROpc))
|
||||||
.addExternalSymbol(RestoreFn);
|
.addExternalSymbol(RestoreFn);
|
||||||
} else {
|
} else {
|
||||||
// The block has a return.
|
// The block has a return.
|
||||||
MachineBasicBlock::iterator It = MBB.getFirstTerminator();
|
MachineBasicBlock::iterator It = MBB.getFirstTerminator();
|
||||||
assert(It->isReturn() && std::next(It) == MBB.end());
|
assert(It->isReturn() && std::next(It) == MBB.end());
|
||||||
unsigned ROpc = Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
|
unsigned ROpc = Hexagon::RESTORE_DEALLOC_RET_JMP_V4;
|
||||||
DeallocCall = BuildMI(MBB, It, DL, TII.get(ROpc))
|
DeallocCall = BuildMI(MBB, It, DL, HII.get(ROpc))
|
||||||
.addExternalSymbol(RestoreFn);
|
.addExternalSymbol(RestoreFn);
|
||||||
// Transfer the function live-out registers.
|
// Transfer the function live-out registers.
|
||||||
DeallocCall->copyImplicitOps(MF, It);
|
DeallocCall->copyImplicitOps(MF, It);
|
||||||
|
@ -818,7 +890,7 @@ bool HexagonFrameLowering::insertCSRRestoresInBlock(MachineBasicBlock &MBB,
|
||||||
unsigned Reg = CSI[i].getReg();
|
unsigned Reg = CSI[i].getReg();
|
||||||
const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);
|
const TargetRegisterClass *RC = HRI.getMinimalPhysRegClass(Reg);
|
||||||
int FI = CSI[i].getFrameIdx();
|
int FI = CSI[i].getFrameIdx();
|
||||||
TII.loadRegFromStackSlot(MBB, MI, Reg, FI, RC, &HRI);
|
HII.loadRegFromStackSlot(MBB, MI, Reg, FI, RC, &HRI);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,8 @@ public:
|
||||||
bool needsAligna(const MachineFunction &MF) const;
|
bool needsAligna(const MachineFunction &MF) const;
|
||||||
MachineInstr *getAlignaInstr(MachineFunction &MF) const;
|
MachineInstr *getAlignaInstr(MachineFunction &MF) const;
|
||||||
|
|
||||||
|
void insertCFIInstructions(MachineFunction &MF) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<CalleeSavedInfo> CSIVect;
|
typedef std::vector<CalleeSavedInfo> CSIVect;
|
||||||
|
|
||||||
|
@ -87,6 +89,8 @@ private:
|
||||||
const HexagonRegisterInfo &HRI) const;
|
const HexagonRegisterInfo &HRI) const;
|
||||||
bool insertCSRRestoresInBlock(MachineBasicBlock &MBB, const CSIVect &CSI,
|
bool insertCSRRestoresInBlock(MachineBasicBlock &MBB, const CSIVect &CSI,
|
||||||
const HexagonRegisterInfo &HRI) const;
|
const HexagonRegisterInfo &HRI) const;
|
||||||
|
void insertCFIInstructionsAt(MachineBasicBlock &MBB,
|
||||||
|
MachineBasicBlock::iterator At) const;
|
||||||
|
|
||||||
void adjustForCalleeSavedRegsSpillCall(MachineFunction &MF) const;
|
void adjustForCalleeSavedRegsSpillCall(MachineFunction &MF) const;
|
||||||
bool replacePredRegPseudoSpillCode(MachineFunction &MF) const;
|
bool replacePredRegPseudoSpillCode(MachineFunction &MF) const;
|
||||||
|
@ -95,7 +99,7 @@ private:
|
||||||
void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB,
|
void findShrunkPrologEpilog(MachineFunction &MF, MachineBasicBlock *&PrologB,
|
||||||
MachineBasicBlock *&EpilogB) const;
|
MachineBasicBlock *&EpilogB) const;
|
||||||
|
|
||||||
bool shouldInlineCSR(llvm::MachineFunction&, const CSIVect&) const;
|
bool shouldInlineCSR(llvm::MachineFunction &MF, const CSIVect &CSI) const;
|
||||||
bool useSpillFunction(MachineFunction &MF, const CSIVect &CSI) const;
|
bool useSpillFunction(MachineFunction &MF, const CSIVect &CSI) const;
|
||||||
bool useRestoreFunction(MachineFunction &MF, const CSIVect &CSI) const;
|
bool useRestoreFunction(MachineFunction &MF, const CSIVect &CSI) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -84,6 +84,7 @@ SchedCustomRegistry("hexagon", "Run Hexagon's custom scheduler",
|
||||||
createVLIWMachineSched);
|
createVLIWMachineSched);
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
FunctionPass *createHexagonCallFrameInformation();
|
||||||
FunctionPass *createHexagonCFGOptimizer();
|
FunctionPass *createHexagonCFGOptimizer();
|
||||||
FunctionPass *createHexagonCommonGEP();
|
FunctionPass *createHexagonCommonGEP();
|
||||||
FunctionPass *createHexagonCopyToCombine();
|
FunctionPass *createHexagonCopyToCombine();
|
||||||
|
@ -273,4 +274,7 @@ void HexagonPassConfig::addPreEmitPass() {
|
||||||
|
|
||||||
addPass(createHexagonPacketizer(), false);
|
addPass(createHexagonPacketizer(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add CFI instructions if necessary.
|
||||||
|
addPass(createHexagonCallFrameInformation(), false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
; RUN: llc -march=hexagon -enable-misched=false < %s | FileCheck %s
|
||||||
|
; This testcase causes the scheduler to crash for some reason. Disable
|
||||||
|
; it for now.
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p:32:32-i64:64-a:0-v32:32-n16:32"
|
||||||
|
target triple = "hexagon-unknown--elf"
|
||||||
|
|
||||||
|
; Check that allocframe was packetized with the two adds.
|
||||||
|
; CHECK: foo:
|
||||||
|
; CHECK: {
|
||||||
|
; CHECK-DAG: allocframe
|
||||||
|
; CHECK-DAG: add
|
||||||
|
; CHECK-DAG: add
|
||||||
|
; CHECK: }
|
||||||
|
; CHECK: dealloc_return
|
||||||
|
; CHECK: }
|
||||||
|
|
||||||
|
; Function Attrs: nounwind
|
||||||
|
define i32 @foo(i32 %x, i32 %y) #0 {
|
||||||
|
entry:
|
||||||
|
tail call void @llvm.dbg.value(metadata i32 %x, i64 0, metadata !9, metadata !14), !dbg !15
|
||||||
|
tail call void @llvm.dbg.value(metadata i32 %y, i64 0, metadata !10, metadata !14), !dbg !16
|
||||||
|
%add = add nsw i32 %x, 1, !dbg !17
|
||||||
|
%add1 = add nsw i32 %y, 1, !dbg !18
|
||||||
|
%call = tail call i32 @bar(i32 %add, i32 %add1) #3, !dbg !19
|
||||||
|
%add2 = add nsw i32 %call, 1, !dbg !20
|
||||||
|
ret i32 %add2, !dbg !21
|
||||||
|
}
|
||||||
|
|
||||||
|
declare i32 @bar(i32, i32) #1
|
||||||
|
|
||||||
|
; Function Attrs: nounwind readnone
|
||||||
|
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
|
||||||
|
|
||||||
|
attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv4" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="hexagonv4" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||||
|
attributes #2 = { nounwind readnone }
|
||||||
|
attributes #3 = { nounwind }
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!11, !12}
|
||||||
|
!llvm.ident = !{!13}
|
||||||
|
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.8.0 (http://llvm.org/git/clang.git 15506a21305e212c406f980ed9b6b1bac785df56)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
|
||||||
|
!1 = !DIFile(filename: "cfi-late.c", directory: "/test")
|
||||||
|
!2 = !{}
|
||||||
|
!3 = !{!4}
|
||||||
|
!4 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, function: i32 (i32, i32)* @foo, variables: !8)
|
||||||
|
!5 = !DISubroutineType(types: !6)
|
||||||
|
!6 = !{!7, !7, !7}
|
||||||
|
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||||
|
!8 = !{!9, !10}
|
||||||
|
!9 = !DILocalVariable(name: "x", arg: 1, scope: !4, file: !1, line: 3, type: !7)
|
||||||
|
!10 = !DILocalVariable(name: "y", arg: 2, scope: !4, file: !1, line: 3, type: !7)
|
||||||
|
!11 = !{i32 2, !"Dwarf Version", i32 4}
|
||||||
|
!12 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!13 = !{!"clang version 3.8.0 (http://llvm.org/git/clang.git 15506a21305e212c406f980ed9b6b1bac785df56)"}
|
||||||
|
!14 = !DIExpression()
|
||||||
|
!15 = !DILocation(line: 3, column: 13, scope: !4)
|
||||||
|
!16 = !DILocation(line: 3, column: 20, scope: !4)
|
||||||
|
!17 = !DILocation(line: 4, column: 15, scope: !4)
|
||||||
|
!18 = !DILocation(line: 4, column: 20, scope: !4)
|
||||||
|
!19 = !DILocation(line: 4, column: 10, scope: !4)
|
||||||
|
!20 = !DILocation(line: 4, column: 24, scope: !4)
|
||||||
|
!21 = !DILocation(line: 4, column: 3, scope: !4)
|
|
@ -7,8 +7,7 @@ call void @bar()
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; CHECK: { call 0
|
||||||
; CHECK: { allocframe(#0) }
|
; CHECK: allocframe(#0)
|
||||||
; CHECK: { call 0 }
|
; CHECK: 00000000: R_HEX_B22_PCREL
|
||||||
; CHECK: 00000004: R_HEX_B22_PCREL
|
; CHECK: { dealloc_return }
|
||||||
; CHECK: { dealloc_return }
|
|
||||||
|
|
|
@ -7,4 +7,4 @@ define void @foo(i32 %a) {
|
||||||
call void @bar(i32 %b)
|
call void @bar(i32 %b)
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
; CHECK: 0x8 R_HEX_B22_PCREL bar 0x4
|
; CHECK: 0x4 R_HEX_B22_PCREL bar 0x4
|
||||||
|
|
Loading…
Reference in New Issue