diff options
Diffstat (limited to 'lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp')
-rw-r--r-- | lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp new file mode 100644 index 0000000000..cb73ae0039 --- /dev/null +++ b/lib/Target/Hexagon/HexagonExpandPredSpillCode.cpp @@ -0,0 +1,184 @@ +//===--- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===//// +// The Hexagon processor has no instructions that load or store predicate +// registers directly. So, when these registers must be spilled a general +// purpose register must be found and the value copied to/from it from/to +// the predicate register. This code currently does not use the register +// scavenger mechanism available in the allocator. There are two registers +// reserved to allow spilling/restoring predicate registers. One is used to +// hold the predicate value. The other is used when stack frame offsets are +// too large. +// +//===----------------------------------------------------------------------===// + + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/LatencyPriorityQueue.h" +#include "llvm/CodeGen/SchedulerRegistry.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/ScheduleHazardRecognizer.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "HexagonTargetMachine.h" +#include "HexagonSubtarget.h" +#include "HexagonMachineFunctionInfo.h" +#include <map> +#include <iostream> + +#include "llvm/Support/CommandLine.h" + + +using namespace llvm; + + +namespace { + +class HexagonExpandPredSpillCode : public MachineFunctionPass { + HexagonTargetMachine& QTM; + const HexagonSubtarget &QST; + + public: + static char ID; + HexagonExpandPredSpillCode(HexagonTargetMachine& TM) : + MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} + + const char *getPassName() const { + return "Hexagon Expand Predicate Spill Code"; + } + bool runOnMachineFunction(MachineFunction &Fn); +}; + + +char HexagonExpandPredSpillCode::ID = 0; + + +bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { + + const HexagonInstrInfo *TII = QTM.getInstrInfo(); + const HexagonRegisterInfo *RegInfo = QTM.getRegisterInfo(); + + // Loop over all of the basic blocks. + for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); + MBBb != MBBe; ++MBBb) { + MachineBasicBlock* MBB = MBBb; + // Traverse the basic block. + for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); + ++MII) { + MachineInstr *MI = MII; + int Opc = MI->getOpcode(); + if (Opc == Hexagon::STriw_pred) { + // STriw_pred [R30], ofst, SrcReg; + unsigned FP = MI->getOperand(0).getReg(); + assert(FP == RegInfo->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); + assert(MI->getOperand(1).isImm() && "Not an offset"); + int Offset = MI->getOperand(1).getImm(); + int SrcReg = MI->getOperand(2).getReg(); + assert(Hexagon::PredRegsRegClass.contains(SrcReg) && + "Not a predicate register"); + if (!TII->isValidOffset(Hexagon::STriw, Offset)) { + if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::CONST32_Int_Real), + HEXAGON_RESERVED_REG_1).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + HEXAGON_RESERVED_REG_1) + .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::STriw)) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0).addReg(HEXAGON_RESERVED_REG_2); + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), + HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0) + .addReg(HEXAGON_RESERVED_REG_2); + } + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), + HEXAGON_RESERVED_REG_2).addReg(SrcReg); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)). + addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); + } + MII = MBB->erase(MI); + --MII; + } else if (Opc == Hexagon::LDriw_pred) { + // DstReg = LDriw_pred [R30], ofst. + int DstReg = MI->getOperand(0).getReg(); + assert(Hexagon::PredRegsRegClass.contains(DstReg) && + "Not a predicate register"); + unsigned FP = MI->getOperand(1).getReg(); + assert(FP == RegInfo->getFrameRegister() && + "Not a Frame Pointer, Nor a Spill Slot"); + assert(MI->getOperand(2).isImm() && "Not an offset"); + int Offset = MI->getOperand(2).getImm(); + if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { + if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { + BuildMI(*MBB, MII, MI->getDebugLoc(), + TII->get(Hexagon::CONST32_Int_Real), + HEXAGON_RESERVED_REG_1).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), + HEXAGON_RESERVED_REG_1) + .addReg(FP) + .addReg(HEXAGON_RESERVED_REG_1); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), + HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2) + .addReg(HEXAGON_RESERVED_REG_1) + .addImm(0); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } + } else { + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), + HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); + BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), + DstReg).addReg(HEXAGON_RESERVED_REG_2); + } + MII = MBB->erase(MI); + --MII; + } + } + } + + return true; +} + +} + +//===----------------------------------------------------------------------===// +// Public Constructor Functions +//===----------------------------------------------------------------------===// + +FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { + return new HexagonExpandPredSpillCode(TM); +} |