1234285Sdim//===-- HexagonExpandPredSpillCode.cpp - Expand Predicate Spill Code ------===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// The Hexagon processor has no instructions that load or store predicate 10239462Sdim// registers directly. So, when these registers must be spilled a general 11239462Sdim// purpose register must be found and the value copied to/from it from/to 12239462Sdim// the predicate register. This code currently does not use the register 13234285Sdim// scavenger mechanism available in the allocator. There are two registers 14234285Sdim// reserved to allow spilling/restoring predicate registers. One is used to 15234285Sdim// hold the predicate value. The other is used when stack frame offsets are 16234285Sdim// too large. 17234285Sdim// 18234285Sdim//===----------------------------------------------------------------------===// 19234285Sdim 20249423Sdim#include "Hexagon.h" 21249423Sdim#include "HexagonMachineFunctionInfo.h" 22249423Sdim#include "HexagonSubtarget.h" 23234285Sdim#include "llvm/ADT/Statistic.h" 24234285Sdim#include "llvm/CodeGen/LatencyPriorityQueue.h" 25234285Sdim#include "llvm/CodeGen/MachineDominators.h" 26234285Sdim#include "llvm/CodeGen/MachineFunctionPass.h" 27234285Sdim#include "llvm/CodeGen/MachineInstrBuilder.h" 28234285Sdim#include "llvm/CodeGen/MachineLoopInfo.h" 29234285Sdim#include "llvm/CodeGen/MachineRegisterInfo.h" 30234285Sdim#include "llvm/CodeGen/Passes.h" 31234285Sdim#include "llvm/CodeGen/ScheduleHazardRecognizer.h" 32234285Sdim#include "llvm/CodeGen/SchedulerRegistry.h" 33234285Sdim#include "llvm/Support/Compiler.h" 34234285Sdim#include "llvm/Support/Debug.h" 35234285Sdim#include "llvm/Support/MathExtras.h" 36249423Sdim#include "llvm/Target/TargetInstrInfo.h" 37249423Sdim#include "llvm/Target/TargetMachine.h" 38249423Sdim#include "llvm/Target/TargetRegisterInfo.h" 39234285Sdim 40234285Sdimusing namespace llvm; 41234285Sdim 42234285Sdim 43251662Sdimnamespace llvm { 44288943Sdim FunctionPass *createHexagonExpandPredSpillCode(); 45251662Sdim void initializeHexagonExpandPredSpillCodePass(PassRegistry&); 46251662Sdim} 47251662Sdim 48251662Sdim 49234285Sdimnamespace { 50234285Sdim 51234285Sdimclass HexagonExpandPredSpillCode : public MachineFunctionPass { 52234285Sdim public: 53234285Sdim static char ID; 54288943Sdim HexagonExpandPredSpillCode() : MachineFunctionPass(ID) { 55251662Sdim PassRegistry &Registry = *PassRegistry::getPassRegistry(); 56251662Sdim initializeHexagonExpandPredSpillCodePass(Registry); 57251662Sdim } 58234285Sdim 59276479Sdim const char *getPassName() const override { 60234285Sdim return "Hexagon Expand Predicate Spill Code"; 61234285Sdim } 62276479Sdim bool runOnMachineFunction(MachineFunction &Fn) override; 63234285Sdim}; 64234285Sdim 65234285Sdim 66234285Sdimchar HexagonExpandPredSpillCode::ID = 0; 67234285Sdim 68234285Sdim 69234285Sdimbool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) { 70234285Sdim 71288943Sdim const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>(); 72288943Sdim const HexagonInstrInfo *TII = QST.getInstrInfo(); 73234285Sdim 74234285Sdim // Loop over all of the basic blocks. 75234285Sdim for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end(); 76234285Sdim MBBb != MBBe; ++MBBb) { 77296417Sdim MachineBasicBlock *MBB = &*MBBb; 78234285Sdim // Traverse the basic block. 79234285Sdim for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end(); 80234285Sdim ++MII) { 81234285Sdim MachineInstr *MI = MII; 82234285Sdim int Opc = MI->getOpcode(); 83288943Sdim if (Opc == Hexagon::S2_storerb_pci_pseudo || 84288943Sdim Opc == Hexagon::S2_storerh_pci_pseudo || 85288943Sdim Opc == Hexagon::S2_storeri_pci_pseudo || 86288943Sdim Opc == Hexagon::S2_storerd_pci_pseudo || 87288943Sdim Opc == Hexagon::S2_storerf_pci_pseudo) { 88288943Sdim unsigned Opcode; 89288943Sdim if (Opc == Hexagon::S2_storerd_pci_pseudo) 90288943Sdim Opcode = Hexagon::S2_storerd_pci; 91288943Sdim else if (Opc == Hexagon::S2_storeri_pci_pseudo) 92288943Sdim Opcode = Hexagon::S2_storeri_pci; 93288943Sdim else if (Opc == Hexagon::S2_storerh_pci_pseudo) 94288943Sdim Opcode = Hexagon::S2_storerh_pci; 95288943Sdim else if (Opc == Hexagon::S2_storerf_pci_pseudo) 96288943Sdim Opcode = Hexagon::S2_storerf_pci; 97288943Sdim else if (Opc == Hexagon::S2_storerb_pci_pseudo) 98288943Sdim Opcode = Hexagon::S2_storerb_pci; 99288943Sdim else 100288943Sdim llvm_unreachable("wrong Opc"); 101288943Sdim MachineOperand &Op0 = MI->getOperand(0); 102288943Sdim MachineOperand &Op1 = MI->getOperand(1); 103288943Sdim MachineOperand &Op2 = MI->getOperand(2); 104288943Sdim MachineOperand &Op3 = MI->getOperand(3); // Modifier value. 105288943Sdim MachineOperand &Op4 = MI->getOperand(4); 106288943Sdim // Emit a "C6 = Rn, C6 is the control register for M0". 107288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), 108288943Sdim Hexagon::C6)->addOperand(Op3); 109288943Sdim // Replace the pseude circ_ldd by the real circ_ldd. 110288943Sdim MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), 111288943Sdim TII->get(Opcode)); 112288943Sdim NewMI->addOperand(Op0); 113288943Sdim NewMI->addOperand(Op1); 114288943Sdim NewMI->addOperand(Op4); 115288943Sdim NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, 116288943Sdim false, /*isDef*/ 117288943Sdim false, /*isImpl*/ 118288943Sdim true /*isKill*/)); 119288943Sdim NewMI->addOperand(Op2); 120288943Sdim MII = MBB->erase(MI); 121288943Sdim --MII; 122288943Sdim } else if (Opc == Hexagon::L2_loadrd_pci_pseudo || 123288943Sdim Opc == Hexagon::L2_loadri_pci_pseudo || 124288943Sdim Opc == Hexagon::L2_loadrh_pci_pseudo || 125288943Sdim Opc == Hexagon::L2_loadruh_pci_pseudo|| 126288943Sdim Opc == Hexagon::L2_loadrb_pci_pseudo || 127288943Sdim Opc == Hexagon::L2_loadrub_pci_pseudo) { 128288943Sdim unsigned Opcode; 129288943Sdim if (Opc == Hexagon::L2_loadrd_pci_pseudo) 130288943Sdim Opcode = Hexagon::L2_loadrd_pci; 131288943Sdim else if (Opc == Hexagon::L2_loadri_pci_pseudo) 132288943Sdim Opcode = Hexagon::L2_loadri_pci; 133288943Sdim else if (Opc == Hexagon::L2_loadrh_pci_pseudo) 134288943Sdim Opcode = Hexagon::L2_loadrh_pci; 135288943Sdim else if (Opc == Hexagon::L2_loadruh_pci_pseudo) 136288943Sdim Opcode = Hexagon::L2_loadruh_pci; 137288943Sdim else if (Opc == Hexagon::L2_loadrb_pci_pseudo) 138288943Sdim Opcode = Hexagon::L2_loadrb_pci; 139288943Sdim else if (Opc == Hexagon::L2_loadrub_pci_pseudo) 140288943Sdim Opcode = Hexagon::L2_loadrub_pci; 141288943Sdim else 142288943Sdim llvm_unreachable("wrong Opc"); 143288943Sdim 144288943Sdim MachineOperand &Op0 = MI->getOperand(0); 145288943Sdim MachineOperand &Op1 = MI->getOperand(1); 146288943Sdim MachineOperand &Op2 = MI->getOperand(2); 147288943Sdim MachineOperand &Op4 = MI->getOperand(4); // Modifier value. 148288943Sdim MachineOperand &Op5 = MI->getOperand(5); 149288943Sdim // Emit a "C6 = Rn, C6 is the control register for M0". 150288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), 151288943Sdim Hexagon::C6)->addOperand(Op4); 152288943Sdim // Replace the pseude circ_ldd by the real circ_ldd. 153288943Sdim MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), 154288943Sdim TII->get(Opcode)); 155288943Sdim NewMI->addOperand(Op1); 156288943Sdim NewMI->addOperand(Op0); 157288943Sdim NewMI->addOperand(Op2); 158288943Sdim NewMI->addOperand(Op5); 159288943Sdim NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, 160288943Sdim false, /*isDef*/ 161288943Sdim false, /*isImpl*/ 162288943Sdim true /*isKill*/)); 163288943Sdim MII = MBB->erase(MI); 164288943Sdim --MII; 165288943Sdim } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo || 166288943Sdim Opc == Hexagon::L2_loadri_pbr_pseudo || 167288943Sdim Opc == Hexagon::L2_loadrh_pbr_pseudo || 168288943Sdim Opc == Hexagon::L2_loadruh_pbr_pseudo|| 169288943Sdim Opc == Hexagon::L2_loadrb_pbr_pseudo || 170288943Sdim Opc == Hexagon::L2_loadrub_pbr_pseudo) { 171288943Sdim unsigned Opcode; 172288943Sdim if (Opc == Hexagon::L2_loadrd_pbr_pseudo) 173288943Sdim Opcode = Hexagon::L2_loadrd_pbr; 174288943Sdim else if (Opc == Hexagon::L2_loadri_pbr_pseudo) 175288943Sdim Opcode = Hexagon::L2_loadri_pbr; 176288943Sdim else if (Opc == Hexagon::L2_loadrh_pbr_pseudo) 177288943Sdim Opcode = Hexagon::L2_loadrh_pbr; 178288943Sdim else if (Opc == Hexagon::L2_loadruh_pbr_pseudo) 179288943Sdim Opcode = Hexagon::L2_loadruh_pbr; 180288943Sdim else if (Opc == Hexagon::L2_loadrb_pbr_pseudo) 181288943Sdim Opcode = Hexagon::L2_loadrb_pbr; 182288943Sdim else if (Opc == Hexagon::L2_loadrub_pbr_pseudo) 183288943Sdim Opcode = Hexagon::L2_loadrub_pbr; 184288943Sdim else 185288943Sdim llvm_unreachable("wrong Opc"); 186288943Sdim MachineOperand &Op0 = MI->getOperand(0); 187288943Sdim MachineOperand &Op1 = MI->getOperand(1); 188288943Sdim MachineOperand &Op2 = MI->getOperand(2); 189288943Sdim MachineOperand &Op4 = MI->getOperand(4); // Modifier value. 190288943Sdim // Emit a "C6 = Rn, C6 is the control register for M0". 191288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), 192288943Sdim Hexagon::C6)->addOperand(Op4); 193288943Sdim // Replace the pseudo brev_ldd by the real brev_ldd. 194288943Sdim MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), 195288943Sdim TII->get(Opcode)); 196288943Sdim NewMI->addOperand(Op1); 197288943Sdim NewMI->addOperand(Op0); 198288943Sdim NewMI->addOperand(Op2); 199288943Sdim NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, 200288943Sdim false, /*isDef*/ 201288943Sdim false, /*isImpl*/ 202288943Sdim true /*isKill*/)); 203288943Sdim MII = MBB->erase(MI); 204288943Sdim --MII; 205288943Sdim } else if (Opc == Hexagon::S2_storerd_pbr_pseudo || 206288943Sdim Opc == Hexagon::S2_storeri_pbr_pseudo || 207288943Sdim Opc == Hexagon::S2_storerh_pbr_pseudo || 208288943Sdim Opc == Hexagon::S2_storerb_pbr_pseudo || 209288943Sdim Opc == Hexagon::S2_storerf_pbr_pseudo) { 210288943Sdim unsigned Opcode; 211288943Sdim if (Opc == Hexagon::S2_storerd_pbr_pseudo) 212288943Sdim Opcode = Hexagon::S2_storerd_pbr; 213288943Sdim else if (Opc == Hexagon::S2_storeri_pbr_pseudo) 214288943Sdim Opcode = Hexagon::S2_storeri_pbr; 215288943Sdim else if (Opc == Hexagon::S2_storerh_pbr_pseudo) 216288943Sdim Opcode = Hexagon::S2_storerh_pbr; 217288943Sdim else if (Opc == Hexagon::S2_storerf_pbr_pseudo) 218288943Sdim Opcode = Hexagon::S2_storerf_pbr; 219288943Sdim else if (Opc == Hexagon::S2_storerb_pbr_pseudo) 220288943Sdim Opcode = Hexagon::S2_storerb_pbr; 221288943Sdim else 222288943Sdim llvm_unreachable("wrong Opc"); 223288943Sdim MachineOperand &Op0 = MI->getOperand(0); 224288943Sdim MachineOperand &Op1 = MI->getOperand(1); 225288943Sdim MachineOperand &Op2 = MI->getOperand(2); 226288943Sdim MachineOperand &Op3 = MI->getOperand(3); // Modifier value. 227288943Sdim // Emit a "C6 = Rn, C6 is the control register for M0". 228288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr), 229288943Sdim Hexagon::C6)->addOperand(Op3); 230288943Sdim // Replace the pseudo brev_ldd by the real brev_ldd. 231288943Sdim MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(), 232288943Sdim TII->get(Opcode)); 233288943Sdim NewMI->addOperand(Op0); 234288943Sdim NewMI->addOperand(Op1); 235288943Sdim NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0, 236288943Sdim false, /*isDef*/ 237288943Sdim false, /*isImpl*/ 238288943Sdim true /*isKill*/)); 239288943Sdim NewMI->addOperand(Op2); 240288943Sdim MII = MBB->erase(MI); 241288943Sdim --MII; 242288943Sdim } else if (Opc == Hexagon::STriw_pred) { 243234285Sdim // STriw_pred [R30], ofst, SrcReg; 244234285Sdim unsigned FP = MI->getOperand(0).getReg(); 245288943Sdim assert(FP == QST.getRegisterInfo()->getFrameRegister() && 246288943Sdim "Not a Frame Pointer, Nor a Spill Slot"); 247234285Sdim assert(MI->getOperand(1).isImm() && "Not an offset"); 248234285Sdim int Offset = MI->getOperand(1).getImm(); 249234285Sdim int SrcReg = MI->getOperand(2).getReg(); 250234285Sdim assert(Hexagon::PredRegsRegClass.contains(SrcReg) && 251234285Sdim "Not a predicate register"); 252280031Sdim if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) { 253288943Sdim if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) { 254234285Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), 255234285Sdim TII->get(Hexagon::CONST32_Int_Real), 256234285Sdim HEXAGON_RESERVED_REG_1).addImm(Offset); 257280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), 258234285Sdim HEXAGON_RESERVED_REG_1) 259234285Sdim .addReg(FP).addReg(HEXAGON_RESERVED_REG_1); 260280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), 261234285Sdim HEXAGON_RESERVED_REG_2).addReg(SrcReg); 262234285Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), 263280031Sdim TII->get(Hexagon::S2_storeri_io)) 264234285Sdim .addReg(HEXAGON_RESERVED_REG_1) 265234285Sdim .addImm(0).addReg(HEXAGON_RESERVED_REG_2); 266234285Sdim } else { 267288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi), 268234285Sdim HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 269280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), 270234285Sdim HEXAGON_RESERVED_REG_2).addReg(SrcReg); 271239462Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), 272280031Sdim TII->get(Hexagon::S2_storeri_io)) 273234285Sdim .addReg(HEXAGON_RESERVED_REG_1) 274234285Sdim .addImm(0) 275234285Sdim .addReg(HEXAGON_RESERVED_REG_2); 276234285Sdim } 277234285Sdim } else { 278280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr), 279234285Sdim HEXAGON_RESERVED_REG_2).addReg(SrcReg); 280239462Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), 281280031Sdim TII->get(Hexagon::S2_storeri_io)). 282234285Sdim addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2); 283234285Sdim } 284234285Sdim MII = MBB->erase(MI); 285234285Sdim --MII; 286234285Sdim } else if (Opc == Hexagon::LDriw_pred) { 287234285Sdim // DstReg = LDriw_pred [R30], ofst. 288234285Sdim int DstReg = MI->getOperand(0).getReg(); 289234285Sdim assert(Hexagon::PredRegsRegClass.contains(DstReg) && 290234285Sdim "Not a predicate register"); 291234285Sdim unsigned FP = MI->getOperand(1).getReg(); 292288943Sdim assert(FP == QST.getRegisterInfo()->getFrameRegister() && 293288943Sdim "Not a Frame Pointer, Nor a Spill Slot"); 294234285Sdim assert(MI->getOperand(2).isImm() && "Not an offset"); 295234285Sdim int Offset = MI->getOperand(2).getImm(); 296280031Sdim if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) { 297288943Sdim if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) { 298234285Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), 299234285Sdim TII->get(Hexagon::CONST32_Int_Real), 300234285Sdim HEXAGON_RESERVED_REG_1).addImm(Offset); 301280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add), 302234285Sdim HEXAGON_RESERVED_REG_1) 303234285Sdim .addReg(FP) 304234285Sdim .addReg(HEXAGON_RESERVED_REG_1); 305280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), 306234285Sdim HEXAGON_RESERVED_REG_2) 307234285Sdim .addReg(HEXAGON_RESERVED_REG_1) 308234285Sdim .addImm(0); 309280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), 310234285Sdim DstReg).addReg(HEXAGON_RESERVED_REG_2); 311234285Sdim } else { 312288943Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi), 313234285Sdim HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset); 314280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), 315234285Sdim HEXAGON_RESERVED_REG_2) 316234285Sdim .addReg(HEXAGON_RESERVED_REG_1) 317234285Sdim .addImm(0); 318280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), 319234285Sdim DstReg).addReg(HEXAGON_RESERVED_REG_2); 320234285Sdim } 321234285Sdim } else { 322280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io), 323234285Sdim HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset); 324280031Sdim BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp), 325234285Sdim DstReg).addReg(HEXAGON_RESERVED_REG_2); 326234285Sdim } 327234285Sdim MII = MBB->erase(MI); 328234285Sdim --MII; 329234285Sdim } 330234285Sdim } 331234285Sdim } 332234285Sdim 333234285Sdim return true; 334234285Sdim} 335234285Sdim 336234285Sdim} 337234285Sdim 338234285Sdim//===----------------------------------------------------------------------===// 339234285Sdim// Public Constructor Functions 340234285Sdim//===----------------------------------------------------------------------===// 341234285Sdim 342251662Sdimstatic void initializePassOnce(PassRegistry &Registry) { 343251662Sdim const char *Name = "Hexagon Expand Predicate Spill Code"; 344251662Sdim PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred", 345251662Sdim &HexagonExpandPredSpillCode::ID, 346276479Sdim nullptr, false, false); 347251662Sdim Registry.registerPass(*PI, true); 348251662Sdim} 349251662Sdim 350251662Sdimvoid llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) { 351251662Sdim CALL_ONCE_INITIALIZATION(initializePassOnce) 352251662Sdim} 353251662Sdim 354251662SdimFunctionPass* 355288943Sdimllvm::createHexagonExpandPredSpillCode() { 356288943Sdim return new HexagonExpandPredSpillCode(); 357234285Sdim} 358