HexagonExpandPredSpillCode.cpp revision 239462
1//===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// The Hexagon processor has no instructions that load or store predicate 10// registers directly. So, when these registers must be spilled a general 11// purpose register must be found and the value copied to/from it from/to 12// the predicate register. This code currently does not use the register 13// scavenger mechanism available in the allocator. There are two registers 14// reserved to allow spilling/restoring predicate registers. One is used to 15// hold the predicate value. The other is used when stack frame offsets are 16// too large. 17// 18//===----------------------------------------------------------------------===// 19 20#include "HexagonTargetMachine.h" 21#include "HexagonSubtarget.h" 22#include "HexagonMachineFunctionInfo.h" 23#include "llvm/ADT/Statistic.h" 24#include "llvm/CodeGen/LatencyPriorityQueue.h" 25#include "llvm/CodeGen/MachineDominators.h" 26#include "llvm/CodeGen/MachineFunctionPass.h" 27#include "llvm/CodeGen/MachineInstrBuilder.h" 28#include "llvm/CodeGen/MachineLoopInfo.h" 29#include "llvm/CodeGen/MachineRegisterInfo.h" 30#include "llvm/CodeGen/Passes.h" 31#include "llvm/CodeGen/ScheduleHazardRecognizer.h" 32#include "llvm/CodeGen/SchedulerRegistry.h" 33#include "llvm/Target/TargetMachine.h" 34#include "llvm/Target/TargetInstrInfo.h" 35#include "llvm/Target/TargetRegisterInfo.h" 36#include "llvm/Support/Compiler.h" 37#include "llvm/Support/Debug.h" 38#include "llvm/Support/MathExtras.h" 39 40using namespace llvm; 41 42 43namespace { 44 45class HexagonExpandPredSpillCode : public MachineFunctionPass { 46 HexagonTargetMachine& QTM; 47 const HexagonSubtarget &QST; 48 49 public: 50 static char ID; 51 HexagonExpandPredSpillCode(HexagonTargetMachine& TM) : 52 MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} 53 54 const char *getPassName() const { 55 return "Hexagon Expand Predicate Spill Code"; 56 } 57 bool runOnMachineFunction(MachineFunction &Fn); 58}; 59 60 61char HexagonExpandPredSpillCode::ID = 0; 62 63 64bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { 65 66 const HexagonInstrInfo *TII = QTM.getInstrInfo(); 67 68 // Loop over all of the basic blocks. 69 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 70 MBBb != MBBe; ++MBBb) { 71 MachineBasicBlock* MBB = MBBb; 72 // Traverse the basic block. 73 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 74 ++MII) { 75 MachineInstr *MI = MII; 76 int Opc = MI->getOpcode(); 77 if (Opc == Hexagon::STriw_pred) { 78 // STriw_pred [R30], ofst, SrcReg; 79 unsigned FP = MI->getOperand(0).getReg(); 80 assert(FP == QTM.getRegisterInfo()->getFrameRegister() && 81 "Not a Frame Pointer, Nor a Spill Slot"); 82 assert(MI->getOperand(1).isImm() && "Not an offset"); 83 int Offset = MI->getOperand(1).getImm(); 84 int SrcReg = MI->getOperand(2).getReg(); 85 assert(Hexagon::PredRegsRegClass.contains(SrcReg) && 86 "Not a predicate register"); 87 if (!TII->isValidOffset(Hexagon::STriw_indexed, Offset)) { 88 if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { 89 BuildMI(*MBB, MII, MI->getDebugLoc(), 90 TII->get(Hexagon::CONST32_Int_Real), 91 HEXAGON_RESERVED_REG_1).addImm(Offset); 92 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), 93 HEXAGON_RESERVED_REG_1) 94 .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); 95 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 96 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 97 BuildMI(*MBB, MII, MI->getDebugLoc(), 98 TII->get(Hexagon::STriw_indexed)) 99 .addReg(HEXAGON_RESERVED_REG_1) 100 .addImm(0).addReg(HEXAGON_RESERVED_REG_2); 101 } else { 102 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), 103 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 104 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 105 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 106 BuildMI(*MBB, MII, MI->getDebugLoc(), 107 TII->get(Hexagon::STriw_indexed)) 108 .addReg(HEXAGON_RESERVED_REG_1) 109 .addImm(0) 110 .addReg(HEXAGON_RESERVED_REG_2); 111 } 112 } else { 113 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 114 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 115 BuildMI(*MBB, MII, MI->getDebugLoc(), 116 TII->get(Hexagon::STriw_indexed)). 117 addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); 118 } 119 MII = MBB->erase(MI); 120 --MII; 121 } else if (Opc == Hexagon::LDriw_pred) { 122 // DstReg = LDriw_pred [R30], ofst. 123 int DstReg = MI->getOperand(0).getReg(); 124 assert(Hexagon::PredRegsRegClass.contains(DstReg) && 125 "Not a predicate register"); 126 unsigned FP = MI->getOperand(1).getReg(); 127 assert(FP == QTM.getRegisterInfo()->getFrameRegister() && 128 "Not a Frame Pointer, Nor a Spill Slot"); 129 assert(MI->getOperand(2).isImm() && "Not an offset"); 130 int Offset = MI->getOperand(2).getImm(); 131 if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { 132 if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { 133 BuildMI(*MBB, MII, MI->getDebugLoc(), 134 TII->get(Hexagon::CONST32_Int_Real), 135 HEXAGON_RESERVED_REG_1).addImm(Offset); 136 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), 137 HEXAGON_RESERVED_REG_1) 138 .addReg(FP) 139 .addReg(HEXAGON_RESERVED_REG_1); 140 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 141 HEXAGON_RESERVED_REG_2) 142 .addReg(HEXAGON_RESERVED_REG_1) 143 .addImm(0); 144 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 145 DstReg).addReg(HEXAGON_RESERVED_REG_2); 146 } else { 147 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), 148 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 149 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 150 HEXAGON_RESERVED_REG_2) 151 .addReg(HEXAGON_RESERVED_REG_1) 152 .addImm(0); 153 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 154 DstReg).addReg(HEXAGON_RESERVED_REG_2); 155 } 156 } else { 157 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 158 HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); 159 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 160 DstReg).addReg(HEXAGON_RESERVED_REG_2); 161 } 162 MII = MBB->erase(MI); 163 --MII; 164 } 165 } 166 } 167 168 return true; 169} 170 171} 172 173//===----------------------------------------------------------------------===// 174// Public Constructor Functions 175//===----------------------------------------------------------------------===// 176 177FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { 178 return new HexagonExpandPredSpillCode(TM); 179} 180