Home | History | Annotate | Download | only in Hexagon
      1 //===-- HexagonSplitTFRCondSets.cpp - split TFR condsets into xfers -------===//
      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 //===----------------------------------------------------------------------===//
     10 // This pass tries to provide opportunities for better optimization of muxes.
     11 // The default code generated for something like: flag = (a == b) ? 1 : 3;
     12 // would be:
     13 //
     14 //   {p0 = cmp.eq(r0,r1)}
     15 //   {r3 = mux(p0,#1,#3)}
     16 //
     17 // This requires two packets.  If we use .new predicated immediate transfers,
     18 // then we can do this in a single packet, e.g.:
     19 //
     20 //   {p0 = cmp.eq(r0,r1)
     21 //    if (p0.new) r3 = #1
     22 //    if (!p0.new) r3 = #3}
     23 //
     24 // Note that the conditional assignments are not generated in .new form here.
     25 // We assume opptimisically that they will be formed later.
     26 //
     27 //===----------------------------------------------------------------------===//
     28 
     29 #include "Hexagon.h"
     30 #include "HexagonMachineFunctionInfo.h"
     31 #include "HexagonSubtarget.h"
     32 #include "HexagonTargetMachine.h"
     33 #include "llvm/CodeGen/LatencyPriorityQueue.h"
     34 #include "llvm/CodeGen/MachineDominators.h"
     35 #include "llvm/CodeGen/MachineFunctionPass.h"
     36 #include "llvm/CodeGen/MachineInstrBuilder.h"
     37 #include "llvm/CodeGen/MachineLoopInfo.h"
     38 #include "llvm/CodeGen/MachineRegisterInfo.h"
     39 #include "llvm/CodeGen/Passes.h"
     40 #include "llvm/CodeGen/ScheduleHazardRecognizer.h"
     41 #include "llvm/CodeGen/SchedulerRegistry.h"
     42 #include "llvm/Support/Compiler.h"
     43 #include "llvm/Support/Debug.h"
     44 #include "llvm/Support/MathExtras.h"
     45 #include "llvm/Target/TargetInstrInfo.h"
     46 #include "llvm/Target/TargetMachine.h"
     47 #include "llvm/Target/TargetRegisterInfo.h"
     48 
     49 using namespace llvm;
     50 
     51 #define DEBUG_TYPE "xfer"
     52 
     53 namespace llvm {
     54   void initializeHexagonSplitTFRCondSetsPass(PassRegistry&);
     55 }
     56 
     57 
     58 namespace {
     59 
     60 class HexagonSplitTFRCondSets : public MachineFunctionPass {
     61     const HexagonTargetMachine &QTM;
     62     const HexagonSubtarget &QST;
     63 
     64  public:
     65     static char ID;
     66     HexagonSplitTFRCondSets(const HexagonTargetMachine& TM) :
     67       MachineFunctionPass(ID), QTM(TM), QST(*TM.getSubtargetImpl()) {
     68       initializeHexagonSplitTFRCondSetsPass(*PassRegistry::getPassRegistry());
     69     }
     70 
     71     const char *getPassName() const override {
     72       return "Hexagon Split TFRCondSets";
     73     }
     74     bool runOnMachineFunction(MachineFunction &Fn) override;
     75 };
     76 
     77 
     78 char HexagonSplitTFRCondSets::ID = 0;
     79 
     80 
     81 bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) {
     82 
     83   const TargetInstrInfo *TII = QTM.getInstrInfo();
     84 
     85   // Loop over all of the basic blocks.
     86   for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
     87        MBBb != MBBe; ++MBBb) {
     88     MachineBasicBlock* MBB = MBBb;
     89     // Traverse the basic block.
     90     for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
     91          ++MII) {
     92       MachineInstr *MI = MII;
     93       int Opc1, Opc2;
     94       switch(MI->getOpcode()) {
     95         case Hexagon::TFR_condset_rr:
     96         case Hexagon::TFR_condset_rr_f:
     97         case Hexagon::TFR_condset_rr64_f: {
     98           int DestReg = MI->getOperand(0).getReg();
     99           int SrcReg1 = MI->getOperand(2).getReg();
    100           int SrcReg2 = MI->getOperand(3).getReg();
    101 
    102           if (MI->getOpcode() == Hexagon::TFR_condset_rr ||
    103               MI->getOpcode() == Hexagon::TFR_condset_rr_f) {
    104             Opc1 = Hexagon::TFR_cPt;
    105             Opc2 = Hexagon::TFR_cNotPt;
    106           }
    107           else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) {
    108             Opc1 = Hexagon::TFR64_cPt;
    109             Opc2 = Hexagon::TFR64_cNotPt;
    110           }
    111 
    112           // Minor optimization: do not emit the predicated copy if the source
    113           // and the destination is the same register.
    114           if (DestReg != SrcReg1) {
    115             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc1),
    116                     DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
    117           }
    118           if (DestReg != SrcReg2) {
    119             BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc2),
    120                     DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
    121           }
    122           MII = MBB->erase(MI);
    123           --MII;
    124           break;
    125         }
    126         case Hexagon::TFR_condset_ri:
    127         case Hexagon::TFR_condset_ri_f: {
    128           int DestReg = MI->getOperand(0).getReg();
    129           int SrcReg1 = MI->getOperand(2).getReg();
    130 
    131           //  Do not emit the predicated copy if the source and the destination
    132           // is the same register.
    133           if (DestReg != SrcReg1) {
    134             BuildMI(*MBB, MII, MI->getDebugLoc(),
    135               TII->get(Hexagon::TFR_cPt), DestReg).
    136               addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
    137           }
    138           if (MI->getOpcode() ==  Hexagon::TFR_condset_ri ) {
    139             BuildMI(*MBB, MII, MI->getDebugLoc(),
    140               TII->get(Hexagon::TFRI_cNotPt), DestReg).
    141               addReg(MI->getOperand(1).getReg()).
    142               addImm(MI->getOperand(3).getImm());
    143           } else if (MI->getOpcode() ==  Hexagon::TFR_condset_ri_f ) {
    144             BuildMI(*MBB, MII, MI->getDebugLoc(),
    145               TII->get(Hexagon::TFRI_cNotPt_f), DestReg).
    146               addReg(MI->getOperand(1).getReg()).
    147               addFPImm(MI->getOperand(3).getFPImm());
    148           }
    149 
    150           MII = MBB->erase(MI);
    151           --MII;
    152           break;
    153         }
    154         case Hexagon::TFR_condset_ir:
    155         case Hexagon::TFR_condset_ir_f: {
    156           int DestReg = MI->getOperand(0).getReg();
    157           int SrcReg2 = MI->getOperand(3).getReg();
    158 
    159           if (MI->getOpcode() ==  Hexagon::TFR_condset_ir ) {
    160             BuildMI(*MBB, MII, MI->getDebugLoc(),
    161               TII->get(Hexagon::TFRI_cPt), DestReg).
    162               addReg(MI->getOperand(1).getReg()).
    163               addImm(MI->getOperand(2).getImm());
    164           } else if (MI->getOpcode() ==  Hexagon::TFR_condset_ir_f ) {
    165             BuildMI(*MBB, MII, MI->getDebugLoc(),
    166               TII->get(Hexagon::TFRI_cPt_f), DestReg).
    167               addReg(MI->getOperand(1).getReg()).
    168               addFPImm(MI->getOperand(2).getFPImm());
    169           }
    170 
    171           // Do not emit the predicated copy if the source and
    172           // the destination is the same register.
    173           if (DestReg != SrcReg2) {
    174             BuildMI(*MBB, MII, MI->getDebugLoc(),
    175               TII->get(Hexagon::TFR_cNotPt), DestReg).
    176               addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
    177           }
    178           MII = MBB->erase(MI);
    179           --MII;
    180           break;
    181         }
    182         case Hexagon::TFR_condset_ii:
    183         case Hexagon::TFR_condset_ii_f: {
    184           int DestReg = MI->getOperand(0).getReg();
    185           int SrcReg1 = MI->getOperand(1).getReg();
    186 
    187           if (MI->getOpcode() ==  Hexagon::TFR_condset_ii ) {
    188             int Immed1 = MI->getOperand(2).getImm();
    189             int Immed2 = MI->getOperand(3).getImm();
    190             BuildMI(*MBB, MII, MI->getDebugLoc(),
    191                     TII->get(Hexagon::TFRI_cPt),
    192                     DestReg).addReg(SrcReg1).addImm(Immed1);
    193             BuildMI(*MBB, MII, MI->getDebugLoc(),
    194                     TII->get(Hexagon::TFRI_cNotPt),
    195                     DestReg).addReg(SrcReg1).addImm(Immed2);
    196           } else if (MI->getOpcode() ==  Hexagon::TFR_condset_ii_f ) {
    197             BuildMI(*MBB, MII, MI->getDebugLoc(),
    198                     TII->get(Hexagon::TFRI_cPt_f), DestReg).
    199                     addReg(SrcReg1).
    200                     addFPImm(MI->getOperand(2).getFPImm());
    201             BuildMI(*MBB, MII, MI->getDebugLoc(),
    202                     TII->get(Hexagon::TFRI_cNotPt_f), DestReg).
    203                     addReg(SrcReg1).
    204                     addFPImm(MI->getOperand(3).getFPImm());
    205           }
    206           MII = MBB->erase(MI);
    207           --MII;
    208           break;
    209         }
    210       }
    211     }
    212   }
    213   return true;
    214 }
    215 
    216 }
    217 
    218 //===----------------------------------------------------------------------===//
    219 //                         Public Constructor Functions
    220 //===----------------------------------------------------------------------===//
    221 
    222 static void initializePassOnce(PassRegistry &Registry) {
    223   const char *Name = "Hexagon Split TFRCondSets";
    224   PassInfo *PI = new PassInfo(Name, "hexagon-split-tfr",
    225                               &HexagonSplitTFRCondSets::ID, nullptr, false,
    226                               false);
    227   Registry.registerPass(*PI, true);
    228 }
    229 
    230 void llvm::initializeHexagonSplitTFRCondSetsPass(PassRegistry &Registry) {
    231   CALL_ONCE_INITIALIZATION(initializePassOnce)
    232 }
    233 
    234 FunctionPass*
    235 llvm::createHexagonSplitTFRCondSets(const HexagonTargetMachine &TM) {
    236   return new HexagonSplitTFRCondSets(TM);
    237 }
    238