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 "Hexagon.h" 21#include "HexagonMachineFunctionInfo.h" 22#include "HexagonSubtarget.h" 23#include "HexagonTargetMachine.h" 24#include "llvm/ADT/Statistic.h" 25#include "llvm/CodeGen/LatencyPriorityQueue.h" 26#include "llvm/CodeGen/MachineDominators.h" 27#include "llvm/CodeGen/MachineFunctionPass.h" 28#include "llvm/CodeGen/MachineInstrBuilder.h" 29#include "llvm/CodeGen/MachineLoopInfo.h" 30#include "llvm/CodeGen/MachineRegisterInfo.h" 31#include "llvm/CodeGen/Passes.h" 32#include "llvm/CodeGen/ScheduleHazardRecognizer.h" 33#include "llvm/CodeGen/SchedulerRegistry.h" 34#include "llvm/Support/Compiler.h" 35#include "llvm/Support/Debug.h" 36#include "llvm/Support/MathExtras.h" 37#include "llvm/Target/TargetInstrInfo.h" 38#include "llvm/Target/TargetMachine.h" 39#include "llvm/Target/TargetRegisterInfo.h" 40 41using namespace llvm; 42 43 44namespace { 45 46class HexagonExpandPredSpillCode : public MachineFunctionPass { 47 HexagonTargetMachine& QTM; 48 const HexagonSubtarget &QST; 49 50 public: 51 static char ID; 52 HexagonExpandPredSpillCode(HexagonTargetMachine& TM) : 53 MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {} 54 55 const char *getPassName() const { 56 return "Hexagon Expand Predicate Spill Code"; 57 } 58 bool runOnMachineFunction(MachineFunction &Fn); 59}; 60 61 62char HexagonExpandPredSpillCode::ID = 0; 63 64 65bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { 66 67 const HexagonInstrInfo *TII = QTM.getInstrInfo(); 68 69 // Loop over all of the basic blocks. 70 for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 71 MBBb != MBBe; ++MBBb) { 72 MachineBasicBlock* MBB = MBBb; 73 // Traverse the basic block. 74 for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 75 ++MII) { 76 MachineInstr *MI = MII; 77 int Opc = MI->getOpcode(); 78 if (Opc == Hexagon::STriw_pred) { 79 // STriw_pred [R30], ofst, SrcReg; 80 unsigned FP = MI->getOperand(0).getReg(); 81 assert(FP == QTM.getRegisterInfo()->getFrameRegister() && 82 "Not a Frame Pointer, Nor a Spill Slot"); 83 assert(MI->getOperand(1).isImm() && "Not an offset"); 84 int Offset = MI->getOperand(1).getImm(); 85 int SrcReg = MI->getOperand(2).getReg(); 86 assert(Hexagon::PredRegsRegClass.contains(SrcReg) && 87 "Not a predicate register"); 88 if (!TII->isValidOffset(Hexagon::STriw_indexed, Offset)) { 89 if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { 90 BuildMI(*MBB, MII, MI->getDebugLoc(), 91 TII->get(Hexagon::CONST32_Int_Real), 92 HEXAGON_RESERVED_REG_1).addImm(Offset); 93 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), 94 HEXAGON_RESERVED_REG_1) 95 .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); 96 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 97 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 98 BuildMI(*MBB, MII, MI->getDebugLoc(), 99 TII->get(Hexagon::STriw_indexed)) 100 .addReg(HEXAGON_RESERVED_REG_1) 101 .addImm(0).addReg(HEXAGON_RESERVED_REG_2); 102 } else { 103 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), 104 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 105 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 106 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 107 BuildMI(*MBB, MII, MI->getDebugLoc(), 108 TII->get(Hexagon::STriw_indexed)) 109 .addReg(HEXAGON_RESERVED_REG_1) 110 .addImm(0) 111 .addReg(HEXAGON_RESERVED_REG_2); 112 } 113 } else { 114 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 115 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 116 BuildMI(*MBB, MII, MI->getDebugLoc(), 117 TII->get(Hexagon::STriw_indexed)). 118 addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); 119 } 120 MII = MBB->erase(MI); 121 --MII; 122 } else if (Opc == Hexagon::LDriw_pred) { 123 // DstReg = LDriw_pred [R30], ofst. 124 int DstReg = MI->getOperand(0).getReg(); 125 assert(Hexagon::PredRegsRegClass.contains(DstReg) && 126 "Not a predicate register"); 127 unsigned FP = MI->getOperand(1).getReg(); 128 assert(FP == QTM.getRegisterInfo()->getFrameRegister() && 129 "Not a Frame Pointer, Nor a Spill Slot"); 130 assert(MI->getOperand(2).isImm() && "Not an offset"); 131 int Offset = MI->getOperand(2).getImm(); 132 if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { 133 if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { 134 BuildMI(*MBB, MII, MI->getDebugLoc(), 135 TII->get(Hexagon::CONST32_Int_Real), 136 HEXAGON_RESERVED_REG_1).addImm(Offset); 137 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), 138 HEXAGON_RESERVED_REG_1) 139 .addReg(FP) 140 .addReg(HEXAGON_RESERVED_REG_1); 141 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 142 HEXAGON_RESERVED_REG_2) 143 .addReg(HEXAGON_RESERVED_REG_1) 144 .addImm(0); 145 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 146 DstReg).addReg(HEXAGON_RESERVED_REG_2); 147 } else { 148 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), 149 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 150 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 151 HEXAGON_RESERVED_REG_2) 152 .addReg(HEXAGON_RESERVED_REG_1) 153 .addImm(0); 154 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 155 DstReg).addReg(HEXAGON_RESERVED_REG_2); 156 } 157 } else { 158 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 159 HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); 160 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 161 DstReg).addReg(HEXAGON_RESERVED_REG_2); 162 } 163 MII = MBB->erase(MI); 164 --MII; 165 } 166 } 167 } 168 169 return true; 170} 171 172} 173 174//===----------------------------------------------------------------------===// 175// Public Constructor Functions 176//===----------------------------------------------------------------------===// 177 178FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { 179 return new HexagonExpandPredSpillCode(TM); 180} 181