Home | History | Annotate | Download | only in Blackfin
      1 //===- BlackfinISelDAGToDAG.cpp - A dag to dag inst selector for Blackfin -===//
      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 file defines an instruction selector for the Blackfin target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "Blackfin.h"
     15 #include "BlackfinTargetMachine.h"
     16 #include "BlackfinRegisterInfo.h"
     17 #include "llvm/Intrinsics.h"
     18 #include "llvm/CodeGen/SelectionDAGISel.h"
     19 #include "llvm/CodeGen/MachineRegisterInfo.h"
     20 #include "llvm/Support/Compiler.h"
     21 #include "llvm/Support/Debug.h"
     22 #include "llvm/Support/ErrorHandling.h"
     23 #include "llvm/Support/raw_ostream.h"
     24 
     25 using namespace llvm;
     26 
     27 //===----------------------------------------------------------------------===//
     28 // Instruction Selector Implementation
     29 //===----------------------------------------------------------------------===//
     30 
     31 //===----------------------------------------------------------------------===//
     32 /// BlackfinDAGToDAGISel - Blackfin specific code to select blackfin machine
     33 /// instructions for SelectionDAG operations.
     34 namespace {
     35   class BlackfinDAGToDAGISel : public SelectionDAGISel {
     36     /// Subtarget - Keep a pointer to the Blackfin Subtarget around so that we
     37     /// can make the right decision when generating code for different targets.
     38     //const BlackfinSubtarget &Subtarget;
     39   public:
     40     BlackfinDAGToDAGISel(BlackfinTargetMachine &TM, CodeGenOpt::Level OptLevel)
     41       : SelectionDAGISel(TM, OptLevel) {}
     42 
     43     virtual void PostprocessISelDAG();
     44 
     45     virtual const char *getPassName() const {
     46       return "Blackfin DAG->DAG Pattern Instruction Selection";
     47     }
     48 
     49     // Include the pieces autogenerated from the target description.
     50 #include "BlackfinGenDAGISel.inc"
     51 
     52   private:
     53     SDNode *Select(SDNode *N);
     54     bool SelectADDRspii(SDValue Addr, SDValue &Base, SDValue &Offset);
     55 
     56     // Walk the DAG after instruction selection, fixing register class issues.
     57     void FixRegisterClasses(SelectionDAG &DAG);
     58 
     59     const BlackfinInstrInfo &getInstrInfo() {
     60       return *static_cast<const BlackfinTargetMachine&>(TM).getInstrInfo();
     61     }
     62     const BlackfinRegisterInfo *getRegisterInfo() {
     63       return static_cast<const BlackfinTargetMachine&>(TM).getRegisterInfo();
     64     }
     65   };
     66 }  // end anonymous namespace
     67 
     68 FunctionPass *llvm::createBlackfinISelDag(BlackfinTargetMachine &TM,
     69                                           CodeGenOpt::Level OptLevel) {
     70   return new BlackfinDAGToDAGISel(TM, OptLevel);
     71 }
     72 
     73 void BlackfinDAGToDAGISel::PostprocessISelDAG() {
     74   FixRegisterClasses(*CurDAG);
     75 }
     76 
     77 SDNode *BlackfinDAGToDAGISel::Select(SDNode *N) {
     78   if (N->isMachineOpcode())
     79     return NULL;   // Already selected.
     80 
     81   switch (N->getOpcode()) {
     82   default: break;
     83   case ISD::FrameIndex: {
     84     // Selects to ADDpp FI, 0 which in turn will become ADDimm7 SP, imm or ADDpp
     85     // SP, Px
     86     int FI = cast<FrameIndexSDNode>(N)->getIndex();
     87     SDValue TFI = CurDAG->getTargetFrameIndex(FI, MVT::i32);
     88     return CurDAG->SelectNodeTo(N, BF::ADDpp, MVT::i32, TFI,
     89                                 CurDAG->getTargetConstant(0, MVT::i32));
     90   }
     91   }
     92 
     93   return SelectCode(N);
     94 }
     95 
     96 bool BlackfinDAGToDAGISel::SelectADDRspii(SDValue Addr,
     97                                           SDValue &Base,
     98                                           SDValue &Offset) {
     99   FrameIndexSDNode *FIN = 0;
    100   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
    101     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
    102     Offset = CurDAG->getTargetConstant(0, MVT::i32);
    103     return true;
    104   }
    105   if (Addr.getOpcode() == ISD::ADD) {
    106     ConstantSDNode *CN = 0;
    107     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) &&
    108         (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) &&
    109         (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
    110       // Constant positive word offset from frame index
    111       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
    112       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
    113       return true;
    114     }
    115   }
    116   return false;
    117 }
    118 
    119 static inline bool isCC(const TargetRegisterClass *RC) {
    120   return BF::AnyCCRegClass.hasSubClassEq(RC);
    121 }
    122 
    123 static inline bool isDCC(const TargetRegisterClass *RC) {
    124   return BF::DRegClass.hasSubClassEq(RC) || isCC(RC);
    125 }
    126 
    127 static void UpdateNodeOperand(SelectionDAG &DAG,
    128                               SDNode *N,
    129                               unsigned Num,
    130                               SDValue Val) {
    131   SmallVector<SDValue, 8> ops(N->op_begin(), N->op_end());
    132   ops[Num] = Val;
    133   SDNode *New = DAG.UpdateNodeOperands(N, ops.data(), ops.size());
    134   DAG.ReplaceAllUsesWith(N, New);
    135 }
    136 
    137 // After instruction selection, insert COPY_TO_REGCLASS nodes to help in
    138 // choosing the proper register classes.
    139 void BlackfinDAGToDAGISel::FixRegisterClasses(SelectionDAG &DAG) {
    140   const BlackfinInstrInfo &TII = getInstrInfo();
    141   const BlackfinRegisterInfo *TRI = getRegisterInfo();
    142   DAG.AssignTopologicalOrder();
    143   HandleSDNode Dummy(DAG.getRoot());
    144 
    145   for (SelectionDAG::allnodes_iterator NI = DAG.allnodes_begin();
    146        NI != DAG.allnodes_end(); ++NI) {
    147     if (NI->use_empty() || !NI->isMachineOpcode())
    148       continue;
    149     const MCInstrDesc &DefMCID = TII.get(NI->getMachineOpcode());
    150     for (SDNode::use_iterator UI = NI->use_begin(); !UI.atEnd(); ++UI) {
    151       if (!UI->isMachineOpcode())
    152         continue;
    153 
    154       if (UI.getUse().getResNo() >= DefMCID.getNumDefs())
    155         continue;
    156       const TargetRegisterClass *DefRC =
    157         TII.getRegClass(DefMCID, UI.getUse().getResNo(), TRI);
    158 
    159       const MCInstrDesc &UseMCID = TII.get(UI->getMachineOpcode());
    160       if (UseMCID.getNumDefs()+UI.getOperandNo() >= UseMCID.getNumOperands())
    161         continue;
    162       const TargetRegisterClass *UseRC =
    163         TII.getRegClass(UseMCID, UseMCID.getNumDefs()+UI.getOperandNo(), TRI);
    164       if (!DefRC || !UseRC)
    165         continue;
    166       // We cannot copy CC <-> !(CC/D)
    167       if ((isCC(DefRC) && !isDCC(UseRC)) || (isCC(UseRC) && !isDCC(DefRC))) {
    168         SDNode *Copy =
    169           DAG.getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
    170                              NI->getDebugLoc(),
    171                              MVT::i32,
    172                              UI.getUse().get(),
    173                              DAG.getTargetConstant(BF::DRegClassID, MVT::i32));
    174         UpdateNodeOperand(DAG, *UI, UI.getOperandNo(), SDValue(Copy, 0));
    175       }
    176     }
    177   }
    178   DAG.setRoot(Dummy.getValue());
    179 }
    180 
    181