Home | History | Annotate | Download | only in Hexagon
      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 "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/Support/Compiler.h"
     34 #include "llvm/Support/Debug.h"
     35 #include "llvm/Support/MathExtras.h"
     36 #include "llvm/Target/TargetInstrInfo.h"
     37 #include "llvm/Target/TargetMachine.h"
     38 #include "llvm/Target/TargetRegisterInfo.h"
     39 
     40 using namespace llvm;
     41 
     42 
     43 namespace llvm {
     44   void initializeHexagonExpandPredSpillCodePass(PassRegistry&);
     45 }
     46 
     47 
     48 namespace {
     49 
     50 class HexagonExpandPredSpillCode : public MachineFunctionPass {
     51  public:
     52     static char ID;
     53     HexagonExpandPredSpillCode() : MachineFunctionPass(ID) {
     54       PassRegistry &Registry = *PassRegistry::getPassRegistry();
     55       initializeHexagonExpandPredSpillCodePass(Registry);
     56     }
     57 
     58     const char *getPassName() const override {
     59       return "Hexagon Expand Predicate Spill Code";
     60     }
     61     bool runOnMachineFunction(MachineFunction &Fn) override;
     62 };
     63 
     64 
     65 char HexagonExpandPredSpillCode::ID = 0;
     66 
     67 
     68 bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
     69 
     70   const HexagonSubtarget &QST = Fn.getSubtarget<HexagonSubtarget>();
     71   const HexagonInstrInfo *TII = QST.getInstrInfo();
     72 
     73   // Loop over all of the basic blocks.
     74   for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
     75        MBBb != MBBe; ++MBBb) {
     76     MachineBasicBlock* MBB = MBBb;
     77     // Traverse the basic block.
     78     for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
     79          ++MII) {
     80       MachineInstr *MI = MII;
     81       int Opc = MI->getOpcode();
     82       if (Opc == Hexagon::S2_storerb_pci_pseudo ||
     83           Opc == Hexagon::S2_storerh_pci_pseudo ||
     84           Opc == Hexagon::S2_storeri_pci_pseudo ||
     85           Opc == Hexagon::S2_storerd_pci_pseudo ||
     86           Opc == Hexagon::S2_storerf_pci_pseudo) {
     87         unsigned Opcode;
     88         if (Opc == Hexagon::S2_storerd_pci_pseudo)
     89           Opcode = Hexagon::S2_storerd_pci;
     90         else if (Opc == Hexagon::S2_storeri_pci_pseudo)
     91           Opcode = Hexagon::S2_storeri_pci;
     92         else if (Opc == Hexagon::S2_storerh_pci_pseudo)
     93           Opcode = Hexagon::S2_storerh_pci;
     94         else if (Opc == Hexagon::S2_storerf_pci_pseudo)
     95           Opcode = Hexagon::S2_storerf_pci;
     96         else if (Opc == Hexagon::S2_storerb_pci_pseudo)
     97           Opcode = Hexagon::S2_storerb_pci;
     98         else
     99           llvm_unreachable("wrong Opc");
    100         MachineOperand &Op0 = MI->getOperand(0);
    101         MachineOperand &Op1 = MI->getOperand(1);
    102         MachineOperand &Op2 = MI->getOperand(2);
    103         MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
    104         MachineOperand &Op4 = MI->getOperand(4);
    105         // Emit a "C6 = Rn, C6 is the control register for M0".
    106         BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
    107                 Hexagon::C6)->addOperand(Op3);
    108         // Replace the pseude circ_ldd by the real circ_ldd.
    109         MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
    110                                       TII->get(Opcode));
    111         NewMI->addOperand(Op0);
    112         NewMI->addOperand(Op1);
    113         NewMI->addOperand(Op4);
    114         NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
    115                                                     false, /*isDef*/
    116                                                     false, /*isImpl*/
    117                                                     true   /*isKill*/));
    118         NewMI->addOperand(Op2);
    119         MII = MBB->erase(MI);
    120         --MII;
    121       } else if (Opc == Hexagon::L2_loadrd_pci_pseudo ||
    122                  Opc == Hexagon::L2_loadri_pci_pseudo ||
    123                  Opc == Hexagon::L2_loadrh_pci_pseudo ||
    124                  Opc == Hexagon::L2_loadruh_pci_pseudo||
    125                  Opc == Hexagon::L2_loadrb_pci_pseudo ||
    126                  Opc == Hexagon::L2_loadrub_pci_pseudo) {
    127         unsigned Opcode;
    128         if (Opc == Hexagon::L2_loadrd_pci_pseudo)
    129           Opcode = Hexagon::L2_loadrd_pci;
    130         else if (Opc == Hexagon::L2_loadri_pci_pseudo)
    131           Opcode = Hexagon::L2_loadri_pci;
    132         else if (Opc == Hexagon::L2_loadrh_pci_pseudo)
    133           Opcode = Hexagon::L2_loadrh_pci;
    134         else if (Opc == Hexagon::L2_loadruh_pci_pseudo)
    135           Opcode = Hexagon::L2_loadruh_pci;
    136         else if (Opc == Hexagon::L2_loadrb_pci_pseudo)
    137           Opcode = Hexagon::L2_loadrb_pci;
    138         else if (Opc == Hexagon::L2_loadrub_pci_pseudo)
    139           Opcode = Hexagon::L2_loadrub_pci;
    140         else
    141           llvm_unreachable("wrong Opc");
    142 
    143         MachineOperand &Op0 = MI->getOperand(0);
    144         MachineOperand &Op1 = MI->getOperand(1);
    145         MachineOperand &Op2 = MI->getOperand(2);
    146         MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
    147         MachineOperand &Op5 = MI->getOperand(5);
    148         // Emit a "C6 = Rn, C6 is the control register for M0".
    149         BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
    150                 Hexagon::C6)->addOperand(Op4);
    151         // Replace the pseude circ_ldd by the real circ_ldd.
    152         MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
    153                                       TII->get(Opcode));
    154         NewMI->addOperand(Op1);
    155         NewMI->addOperand(Op0);
    156         NewMI->addOperand(Op2);
    157         NewMI->addOperand(Op5);
    158         NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
    159                                                     false, /*isDef*/
    160                                                     false, /*isImpl*/
    161                                                     true   /*isKill*/));
    162         MII = MBB->erase(MI);
    163         --MII;
    164       } else if (Opc == Hexagon::L2_loadrd_pbr_pseudo ||
    165                  Opc == Hexagon::L2_loadri_pbr_pseudo ||
    166                  Opc == Hexagon::L2_loadrh_pbr_pseudo ||
    167                  Opc == Hexagon::L2_loadruh_pbr_pseudo||
    168                  Opc == Hexagon::L2_loadrb_pbr_pseudo ||
    169                  Opc == Hexagon::L2_loadrub_pbr_pseudo) {
    170         unsigned Opcode;
    171         if (Opc == Hexagon::L2_loadrd_pbr_pseudo)
    172           Opcode = Hexagon::L2_loadrd_pbr;
    173         else if (Opc == Hexagon::L2_loadri_pbr_pseudo)
    174           Opcode = Hexagon::L2_loadri_pbr;
    175         else if (Opc == Hexagon::L2_loadrh_pbr_pseudo)
    176           Opcode = Hexagon::L2_loadrh_pbr;
    177         else if (Opc == Hexagon::L2_loadruh_pbr_pseudo)
    178           Opcode = Hexagon::L2_loadruh_pbr;
    179         else if (Opc == Hexagon::L2_loadrb_pbr_pseudo)
    180           Opcode = Hexagon::L2_loadrb_pbr;
    181         else if (Opc == Hexagon::L2_loadrub_pbr_pseudo)
    182           Opcode = Hexagon::L2_loadrub_pbr;
    183         else
    184           llvm_unreachable("wrong Opc");
    185         MachineOperand &Op0 = MI->getOperand(0);
    186         MachineOperand &Op1 = MI->getOperand(1);
    187         MachineOperand &Op2 = MI->getOperand(2);
    188         MachineOperand &Op4 = MI->getOperand(4); // Modifier value.
    189         // Emit a "C6 = Rn, C6 is the control register for M0".
    190         BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
    191                 Hexagon::C6)->addOperand(Op4);
    192         // Replace the pseudo brev_ldd by the real brev_ldd.
    193         MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
    194                                       TII->get(Opcode));
    195         NewMI->addOperand(Op1);
    196         NewMI->addOperand(Op0);
    197         NewMI->addOperand(Op2);
    198         NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
    199                                                     false, /*isDef*/
    200                                                     false, /*isImpl*/
    201                                                     true   /*isKill*/));
    202         MII = MBB->erase(MI);
    203         --MII;
    204       } else if (Opc == Hexagon::S2_storerd_pbr_pseudo ||
    205                  Opc == Hexagon::S2_storeri_pbr_pseudo ||
    206                  Opc == Hexagon::S2_storerh_pbr_pseudo ||
    207                  Opc == Hexagon::S2_storerb_pbr_pseudo ||
    208                  Opc == Hexagon::S2_storerf_pbr_pseudo) {
    209         unsigned Opcode;
    210         if (Opc == Hexagon::S2_storerd_pbr_pseudo)
    211           Opcode = Hexagon::S2_storerd_pbr;
    212         else if (Opc == Hexagon::S2_storeri_pbr_pseudo)
    213           Opcode = Hexagon::S2_storeri_pbr;
    214         else if (Opc == Hexagon::S2_storerh_pbr_pseudo)
    215           Opcode = Hexagon::S2_storerh_pbr;
    216         else if (Opc == Hexagon::S2_storerf_pbr_pseudo)
    217           Opcode = Hexagon::S2_storerf_pbr;
    218         else if (Opc == Hexagon::S2_storerb_pbr_pseudo)
    219           Opcode = Hexagon::S2_storerb_pbr;
    220         else
    221           llvm_unreachable("wrong Opc");
    222         MachineOperand &Op0 = MI->getOperand(0);
    223         MachineOperand &Op1 = MI->getOperand(1);
    224         MachineOperand &Op2 = MI->getOperand(2);
    225         MachineOperand &Op3 = MI->getOperand(3); // Modifier value.
    226         // Emit a "C6 = Rn, C6 is the control register for M0".
    227         BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_tfrrcr),
    228                 Hexagon::C6)->addOperand(Op3);
    229         // Replace the pseudo brev_ldd by the real brev_ldd.
    230         MachineInstr *NewMI = BuildMI(*MBB, MII, MI->getDebugLoc(),
    231                                       TII->get(Opcode));
    232         NewMI->addOperand(Op0);
    233         NewMI->addOperand(Op1);
    234         NewMI->addOperand(MachineOperand::CreateReg(Hexagon::M0,
    235                                                     false, /*isDef*/
    236                                                     false, /*isImpl*/
    237                                                     true   /*isKill*/));
    238         NewMI->addOperand(Op2);
    239         MII = MBB->erase(MI);
    240         --MII;
    241       } else if (Opc == Hexagon::STriw_pred) {
    242         // STriw_pred [R30], ofst, SrcReg;
    243         unsigned FP = MI->getOperand(0).getReg();
    244         assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
    245                "Not a Frame Pointer, Nor a Spill Slot");
    246         assert(MI->getOperand(1).isImm() && "Not an offset");
    247         int Offset = MI->getOperand(1).getImm();
    248         int SrcReg = MI->getOperand(2).getReg();
    249         assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
    250                "Not a predicate register");
    251         if (!TII->isValidOffset(Hexagon::S2_storeri_io, Offset)) {
    252           if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
    253             BuildMI(*MBB, MII, MI->getDebugLoc(),
    254                     TII->get(Hexagon::CONST32_Int_Real),
    255                       HEXAGON_RESERVED_REG_1).addImm(Offset);
    256             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
    257                     HEXAGON_RESERVED_REG_1)
    258               .addReg(FP).addReg(HEXAGON_RESERVED_REG_1);
    259             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
    260                       HEXAGON_RESERVED_REG_2).addReg(SrcReg);
    261             BuildMI(*MBB, MII, MI->getDebugLoc(),
    262                     TII->get(Hexagon::S2_storeri_io))
    263               .addReg(HEXAGON_RESERVED_REG_1)
    264               .addImm(0).addReg(HEXAGON_RESERVED_REG_2);
    265           } else {
    266             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
    267                       HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
    268             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
    269                       HEXAGON_RESERVED_REG_2).addReg(SrcReg);
    270             BuildMI(*MBB, MII, MI->getDebugLoc(),
    271                           TII->get(Hexagon::S2_storeri_io))
    272               .addReg(HEXAGON_RESERVED_REG_1)
    273               .addImm(0)
    274               .addReg(HEXAGON_RESERVED_REG_2);
    275           }
    276         } else {
    277           BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrpr),
    278                     HEXAGON_RESERVED_REG_2).addReg(SrcReg);
    279           BuildMI(*MBB, MII, MI->getDebugLoc(),
    280                         TII->get(Hexagon::S2_storeri_io)).
    281                     addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
    282         }
    283         MII = MBB->erase(MI);
    284         --MII;
    285       } else if (Opc == Hexagon::LDriw_pred) {
    286         // DstReg = LDriw_pred [R30], ofst.
    287         int DstReg = MI->getOperand(0).getReg();
    288         assert(Hexagon::PredRegsRegClass.contains(DstReg) &&
    289                "Not a predicate register");
    290         unsigned FP = MI->getOperand(1).getReg();
    291         assert(FP == QST.getRegisterInfo()->getFrameRegister() &&
    292                "Not a Frame Pointer, Nor a Spill Slot");
    293         assert(MI->getOperand(2).isImm() && "Not an offset");
    294         int Offset = MI->getOperand(2).getImm();
    295         if (!TII->isValidOffset(Hexagon::L2_loadri_io, Offset)) {
    296           if (!TII->isValidOffset(Hexagon::A2_addi, Offset)) {
    297             BuildMI(*MBB, MII, MI->getDebugLoc(),
    298                     TII->get(Hexagon::CONST32_Int_Real),
    299                       HEXAGON_RESERVED_REG_1).addImm(Offset);
    300             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_add),
    301                     HEXAGON_RESERVED_REG_1)
    302               .addReg(FP)
    303               .addReg(HEXAGON_RESERVED_REG_1);
    304             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
    305                       HEXAGON_RESERVED_REG_2)
    306               .addReg(HEXAGON_RESERVED_REG_1)
    307               .addImm(0);
    308             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
    309                       DstReg).addReg(HEXAGON_RESERVED_REG_2);
    310           } else {
    311             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::A2_addi),
    312                       HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
    313             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
    314                       HEXAGON_RESERVED_REG_2)
    315               .addReg(HEXAGON_RESERVED_REG_1)
    316               .addImm(0);
    317             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
    318                       DstReg).addReg(HEXAGON_RESERVED_REG_2);
    319           }
    320         } else {
    321           BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::L2_loadri_io),
    322                     HEXAGON_RESERVED_REG_2).addReg(FP).addImm(Offset);
    323           BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::C2_tfrrp),
    324                     DstReg).addReg(HEXAGON_RESERVED_REG_2);
    325         }
    326         MII = MBB->erase(MI);
    327         --MII;
    328       }
    329     }
    330   }
    331 
    332   return true;
    333 }
    334 
    335 }
    336 
    337 //===----------------------------------------------------------------------===//
    338 //                         Public Constructor Functions
    339 //===----------------------------------------------------------------------===//
    340 
    341 static void initializePassOnce(PassRegistry &Registry) {
    342   const char *Name = "Hexagon Expand Predicate Spill Code";
    343   PassInfo *PI = new PassInfo(Name, "hexagon-spill-pred",
    344                               &HexagonExpandPredSpillCode::ID,
    345                               nullptr, false, false);
    346   Registry.registerPass(*PI, true);
    347 }
    348 
    349 void llvm::initializeHexagonExpandPredSpillCodePass(PassRegistry &Registry) {
    350   CALL_ONCE_INITIALIZATION(initializePassOnce)
    351 }
    352 
    353 FunctionPass*
    354 llvm::createHexagonExpandPredSpillCode() {
    355   return new HexagonExpandPredSpillCode();
    356 }
    357