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, 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)) 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(), TII->get(Hexagon::STriw)) 107 .addReg(HEXAGON_RESERVED_REG_1) 108 .addImm(0) 109 .addReg(HEXAGON_RESERVED_REG_2); 110 } 111 } else { 112 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd), 113 HEXAGON_RESERVED_REG_2).addReg(SrcReg); 114 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)). 115 addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); 116 } 117 MII = MBB->erase(MI); 118 --MII; 119 } else if (Opc == Hexagon::LDriw_pred) { 120 // DstReg = LDriw_pred [R30], ofst. 121 int DstReg = MI->getOperand(0).getReg(); 122 assert(Hexagon::PredRegsRegClass.contains(DstReg) && 123 "Not a predicate register"); 124 unsigned FP = MI->getOperand(1).getReg(); 125 assert(FP == QTM.getRegisterInfo()->getFrameRegister() && 126 "Not a Frame Pointer, Nor a Spill Slot"); 127 assert(MI->getOperand(2).isImm() && "Not an offset"); 128 int Offset = MI->getOperand(2).getImm(); 129 if (!TII->isValidOffset(Hexagon::LDriw, Offset)) { 130 if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) { 131 BuildMI(*MBB, MII, MI->getDebugLoc(), 132 TII->get(Hexagon::CONST32_Int_Real), 133 HEXAGON_RESERVED_REG_1).addImm(Offset); 134 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_rr), 135 HEXAGON_RESERVED_REG_1) 136 .addReg(FP) 137 .addReg(HEXAGON_RESERVED_REG_1); 138 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 139 HEXAGON_RESERVED_REG_2) 140 .addReg(HEXAGON_RESERVED_REG_1) 141 .addImm(0); 142 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 143 DstReg).addReg(HEXAGON_RESERVED_REG_2); 144 } else { 145 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::ADD_ri), 146 HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 147 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 148 HEXAGON_RESERVED_REG_2) 149 .addReg(HEXAGON_RESERVED_REG_1) 150 .addImm(0); 151 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 152 DstReg).addReg(HEXAGON_RESERVED_REG_2); 153 } 154 } else { 155 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::LDriw), 156 HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); 157 BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_PdRs), 158 DstReg).addReg(HEXAGON_RESERVED_REG_2); 159 } 160 MII = MBB->erase(MI); 161 --MII; 162 } 163 } 164 } 165 166 return true; 167} 168 169} 170 171//===----------------------------------------------------------------------===// 172// Public Constructor Functions 173//===----------------------------------------------------------------------===// 174 175FunctionPass *llvm::createHexagonExpandPredSpillCode(HexagonTargetMachine &TM) { 176 return new HexagonExpandPredSpillCode(TM); 177} 178