summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp95
-rw-r--r--llvm/lib/Target/Hexagon/HexagonFrameLowering.h2
-rw-r--r--llvm/lib/Target/Hexagon/HexagonSubtarget.h1
3 files changed, 91 insertions, 7 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
index 4d6235a9fe5..df9fdceb5d5 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.cpp
@@ -292,6 +292,26 @@ namespace {
return false;
}
+ /// Returns the "return" instruction from this block, or nullptr if there
+ /// isn't any.
+ MachineInstr *getReturn(MachineBasicBlock &MBB) {
+ for (auto &I : MBB)
+ if (I.isReturn())
+ return &I;
+ return nullptr;
+ }
+
+ bool isRestoreCall(unsigned Opc) {
+ switch (Opc) {
+ case Hexagon::RESTORE_DEALLOC_RET_JMP_V4:
+ case Hexagon::RESTORE_DEALLOC_RET_JMP_V4_PIC:
+ case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4:
+ case Hexagon::RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC:
+ return true;
+ }
+ return false;
+ }
+
inline bool isOptNone(const MachineFunction &MF) {
return MF.getFunction()->hasFnAttribute(Attribute::OptimizeNone) ||
MF.getTarget().getOptLevel() == CodeGenOpt::None;
@@ -445,6 +465,28 @@ void HexagonFrameLowering::emitPrologue(MachineFunction &MF,
for (auto &B : MF)
if (B.isReturnBlock())
insertEpilogueInBlock(B);
+
+ for (auto &B : MF) {
+ if (B.empty())
+ continue;
+ MachineInstr *RetI = getReturn(B);
+ if (!RetI || isRestoreCall(RetI->getOpcode()))
+ continue;
+ for (auto &R : CSI)
+ RetI->addOperand(MachineOperand::CreateReg(R.getReg(), false, true));
+ }
+ }
+
+ if (EpilogB) {
+ // If there is an epilog block, it may not have a return instruction.
+ // In such case, we need to add the callee-saved registers as live-ins
+ // in all blocks on all paths from the epilog to any return block.
+ unsigned MaxBN = 0;
+ for (auto &B : MF)
+ if (B.getNumber() >= 0)
+ MaxBN = std::max(MaxBN, unsigned(B.getNumber()));
+ BitVector DoneT(MaxBN+1), DoneF(MaxBN+1), Path(MaxBN+1);
+ updateExitPaths(*EpilogB, EpilogB, DoneT, DoneF, Path);
}
}
@@ -544,13 +586,7 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
auto &HRI = *HST.getRegisterInfo();
unsigned SP = HRI.getStackRegister();
- MachineInstr *RetI = nullptr;
- for (auto &I : MBB) {
- if (!I.isReturn())
- continue;
- RetI = &I;
- break;
- }
+ MachineInstr *RetI = getReturn(MBB);
unsigned RetOpc = RetI ? RetI->getOpcode() : 0;
MachineBasicBlock::iterator InsertPt = MBB.getFirstTerminator();
@@ -614,6 +650,51 @@ void HexagonFrameLowering::insertEpilogueInBlock(MachineBasicBlock &MBB) const {
}
+bool HexagonFrameLowering::updateExitPaths(MachineBasicBlock &MBB,
+ MachineBasicBlock *RestoreB, BitVector &DoneT, BitVector &DoneF,
+ BitVector &Path) const {
+ assert(MBB.getNumber() >= 0);
+ unsigned BN = MBB.getNumber();
+ if (Path[BN] || DoneF[BN])
+ return false;
+ if (DoneT[BN])
+ return true;
+
+ auto &CSI = MBB.getParent()->getFrameInfo()->getCalleeSavedInfo();
+
+ Path[BN] = true;
+ bool ReachedExit = false;
+ for (auto &SB : MBB.successors())
+ ReachedExit |= updateExitPaths(*SB, RestoreB, DoneT, DoneF, Path);
+
+ if (!MBB.empty() && MBB.back().isReturn()) {
+ // Add implicit uses of all callee-saved registers to the reached
+ // return instructions. This is to prevent the anti-dependency breaker
+ // from renaming these registers.
+ MachineInstr &RetI = MBB.back();
+ if (!isRestoreCall(RetI.getOpcode()))
+ for (auto &R : CSI)
+ RetI.addOperand(MachineOperand::CreateReg(R.getReg(), false, true));
+ ReachedExit = true;
+ }
+
+ // We don't want to add unnecessary live-ins to the restore block: since
+ // the callee-saved registers are being defined in it, the entry of the
+ // restore block cannot be on the path from the definitions to any exit.
+ if (ReachedExit && &MBB != RestoreB) {
+ for (auto &R : CSI)
+ if (!MBB.isLiveIn(R.getReg()))
+ MBB.addLiveIn(R.getReg());
+ DoneT[BN] = true;
+ }
+ if (!ReachedExit)
+ DoneF[BN] = true;
+
+ Path[BN] = false;
+ return ReachedExit;
+}
+
+
namespace {
bool IsAllocFrame(MachineBasicBlock::const_iterator It) {
if (!It->isBundle())
diff --git a/llvm/lib/Target/Hexagon/HexagonFrameLowering.h b/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
index 3c3f03915d9..3e76214559b 100644
--- a/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
+++ b/llvm/lib/Target/Hexagon/HexagonFrameLowering.h
@@ -91,6 +91,8 @@ private:
const HexagonRegisterInfo &HRI, bool &PrologueStubs) const;
bool insertCSRRestoresInBlock(MachineBasicBlock &MBB, const CSIVect &CSI,
const HexagonRegisterInfo &HRI) const;
+ bool updateExitPaths(MachineBasicBlock &MBB, MachineBasicBlock *RestoreB,
+ BitVector &DoneT, BitVector &DoneF, BitVector &Path) const;
void insertCFIInstructionsAt(MachineBasicBlock &MBB,
MachineBasicBlock::iterator At) const;
diff --git a/llvm/lib/Target/Hexagon/HexagonSubtarget.h b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
index 9d5a4a81503..d3ff482b1d4 100644
--- a/llvm/lib/Target/Hexagon/HexagonSubtarget.h
+++ b/llvm/lib/Target/Hexagon/HexagonSubtarget.h
@@ -106,6 +106,7 @@ public:
bool enableMachineSchedDefaultSched() const override { return false; }
AntiDepBreakMode getAntiDepBreakMode() const override { return ANTIDEP_ALL; }
+ bool enablePostRAScheduler() const override { return true; }
const std::string &getCPUString () const { return CPUString; }
OpenPOWER on IntegriCloud