Home | History | Annotate | Download | only in MBlaze
      1 //===-- MBlazeISelDAGToDAG.cpp - A dag to dag inst selector for MBlaze ----===//
      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 MBlaze target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #define DEBUG_TYPE "mblaze-isel"
     15 #include "MBlaze.h"
     16 #include "MBlazeMachineFunction.h"
     17 #include "MBlazeRegisterInfo.h"
     18 #include "MBlazeSubtarget.h"
     19 #include "MBlazeTargetMachine.h"
     20 #include "llvm/CodeGen/MachineConstantPool.h"
     21 #include "llvm/CodeGen/MachineFrameInfo.h"
     22 #include "llvm/CodeGen/MachineFunction.h"
     23 #include "llvm/CodeGen/MachineInstrBuilder.h"
     24 #include "llvm/CodeGen/MachineRegisterInfo.h"
     25 #include "llvm/CodeGen/SelectionDAGISel.h"
     26 #include "llvm/IR/GlobalValue.h"
     27 #include "llvm/IR/Instructions.h"
     28 #include "llvm/IR/Intrinsics.h"
     29 #include "llvm/IR/Type.h"
     30 #include "llvm/Support/CFG.h"
     31 #include "llvm/Support/Debug.h"
     32 #include "llvm/Support/ErrorHandling.h"
     33 #include "llvm/Support/raw_ostream.h"
     34 #include "llvm/Target/TargetMachine.h"
     35 using namespace llvm;
     36 
     37 //===----------------------------------------------------------------------===//
     38 // Instruction Selector Implementation
     39 //===----------------------------------------------------------------------===//
     40 
     41 //===----------------------------------------------------------------------===//
     42 // MBlazeDAGToDAGISel - MBlaze specific code to select MBlaze machine
     43 // instructions for SelectionDAG operations.
     44 //===----------------------------------------------------------------------===//
     45 namespace {
     46 
     47 class MBlazeDAGToDAGISel : public SelectionDAGISel {
     48 
     49   /// TM - Keep a reference to MBlazeTargetMachine.
     50   MBlazeTargetMachine &TM;
     51 
     52   /// Subtarget - Keep a pointer to the MBlazeSubtarget around so that we can
     53   /// make the right decision when generating code for different targets.
     54   const MBlazeSubtarget &Subtarget;
     55 
     56 public:
     57   explicit MBlazeDAGToDAGISel(MBlazeTargetMachine &tm) :
     58   SelectionDAGISel(tm),
     59   TM(tm), Subtarget(tm.getSubtarget<MBlazeSubtarget>()) {}
     60 
     61   // Pass Name
     62   virtual const char *getPassName() const {
     63     return "MBlaze DAG->DAG Pattern Instruction Selection";
     64   }
     65 private:
     66   // Include the pieces autogenerated from the target description.
     67   #include "MBlazeGenDAGISel.inc"
     68 
     69   /// getTargetMachine - Return a reference to the TargetMachine, casted
     70   /// to the target-specific type.
     71   const MBlazeTargetMachine &getTargetMachine() {
     72     return static_cast<const MBlazeTargetMachine &>(TM);
     73   }
     74 
     75   /// getInstrInfo - Return a reference to the TargetInstrInfo, casted
     76   /// to the target-specific type.
     77   const MBlazeInstrInfo *getInstrInfo() {
     78     return getTargetMachine().getInstrInfo();
     79   }
     80 
     81   SDNode *getGlobalBaseReg();
     82   SDNode *Select(SDNode *N);
     83 
     84   // Address Selection
     85   bool SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index);
     86   bool SelectAddrRegImm(SDValue N, SDValue &Disp, SDValue &Base);
     87 
     88   // getI32Imm - Return a target constant with the specified value, of type i32.
     89   inline SDValue getI32Imm(unsigned Imm) {
     90     return CurDAG->getTargetConstant(Imm, MVT::i32);
     91   }
     92 };
     93 
     94 }
     95 
     96 /// isIntS32Immediate - This method tests to see if the node is either a 32-bit
     97 /// or 64-bit immediate, and if the value can be accurately represented as a
     98 /// sign extension from a 32-bit value.  If so, this returns true and the
     99 /// immediate.
    100 static bool isIntS32Immediate(SDNode *N, int32_t &Imm) {
    101   unsigned Opc = N->getOpcode();
    102   if (Opc != ISD::Constant)
    103     return false;
    104 
    105   Imm = (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
    106   if (N->getValueType(0) == MVT::i32)
    107     return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue();
    108   else
    109     return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue();
    110 }
    111 
    112 static bool isIntS32Immediate(SDValue Op, int32_t &Imm) {
    113   return isIntS32Immediate(Op.getNode(), Imm);
    114 }
    115 
    116 
    117 /// SelectAddressRegReg - Given the specified addressed, check to see if it
    118 /// can be represented as an indexed [r+r] operation.  Returns false if it
    119 /// can be more efficiently represented with [r+imm].
    120 bool MBlazeDAGToDAGISel::
    121 SelectAddrRegReg(SDValue N, SDValue &Base, SDValue &Index) {
    122   if (N.getOpcode() == ISD::FrameIndex) return false;
    123   if (N.getOpcode() == ISD::TargetExternalSymbol ||
    124       N.getOpcode() == ISD::TargetGlobalAddress)
    125     return false;  // direct calls.
    126 
    127   int32_t imm = 0;
    128   if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
    129     if (isIntS32Immediate(N.getOperand(1), imm))
    130       return false;    // r+i
    131 
    132     if (N.getOperand(0).getOpcode() == ISD::TargetJumpTable ||
    133         N.getOperand(1).getOpcode() == ISD::TargetJumpTable)
    134       return false; // jump tables.
    135 
    136     Base = N.getOperand(0);
    137     Index = N.getOperand(1);
    138     return true;
    139   }
    140 
    141   return false;
    142 }
    143 
    144 /// Returns true if the address N can be represented by a base register plus
    145 /// a signed 32-bit displacement [r+imm], and if it is not better
    146 /// represented as reg+reg.
    147 bool MBlazeDAGToDAGISel::
    148 SelectAddrRegImm(SDValue N, SDValue &Base, SDValue &Disp) {
    149   // If this can be more profitably realized as r+r, fail.
    150   if (SelectAddrRegReg(N, Base, Disp))
    151     return false;
    152 
    153   if (N.getOpcode() == ISD::ADD || N.getOpcode() == ISD::OR) {
    154     int32_t imm = 0;
    155     if (isIntS32Immediate(N.getOperand(1), imm)) {
    156       Disp = CurDAG->getTargetConstant(imm, MVT::i32);
    157       if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) {
    158         Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
    159       } else {
    160         Base = N.getOperand(0);
    161       }
    162       return true; // [r+i]
    163     }
    164   } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) {
    165     // Loading from a constant address.
    166     uint32_t Imm = CN->getZExtValue();
    167     Disp = CurDAG->getTargetConstant(Imm, CN->getValueType(0));
    168     Base = CurDAG->getRegister(MBlaze::R0, CN->getValueType(0));
    169     return true;
    170   }
    171 
    172   Disp = CurDAG->getTargetConstant(0, TM.getTargetLowering()->getPointerTy());
    173   if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N))
    174     Base = CurDAG->getTargetFrameIndex(FI->getIndex(), N.getValueType());
    175   else
    176     Base = N;
    177   return true;      // [r+0]
    178 }
    179 
    180 /// getGlobalBaseReg - Output the instructions required to put the
    181 /// GOT address into a register.
    182 SDNode *MBlazeDAGToDAGISel::getGlobalBaseReg() {
    183   unsigned GlobalBaseReg = getInstrInfo()->getGlobalBaseReg(MF);
    184   return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
    185 }
    186 
    187 /// Select instructions not customized! Used for
    188 /// expanded, promoted and normal instructions
    189 SDNode* MBlazeDAGToDAGISel::Select(SDNode *Node) {
    190   unsigned Opcode = Node->getOpcode();
    191   DebugLoc dl = Node->getDebugLoc();
    192 
    193   // If we have a custom node, we already have selected!
    194   if (Node->isMachineOpcode())
    195     return NULL;
    196 
    197   ///
    198   // Instruction Selection not handled by the auto-generated
    199   // tablegen selection should be handled here.
    200   ///
    201   switch (Opcode) {
    202     default: break;
    203 
    204     // Get target GOT address.
    205     case ISD::GLOBAL_OFFSET_TABLE:
    206       return getGlobalBaseReg();
    207 
    208     case ISD::FrameIndex: {
    209         SDValue imm = CurDAG->getTargetConstant(0, MVT::i32);
    210         int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
    211         EVT VT = Node->getValueType(0);
    212         SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
    213         unsigned Opc = MBlaze::ADDIK;
    214         if (Node->hasOneUse())
    215           return CurDAG->SelectNodeTo(Node, Opc, VT, TFI, imm);
    216         return CurDAG->getMachineNode(Opc, dl, VT, TFI, imm);
    217     }
    218 
    219 
    220     /// Handle direct and indirect calls when using PIC. On PIC, when
    221     /// GOT is smaller than about 64k (small code) the GA target is
    222     /// loaded with only one instruction. Otherwise GA's target must
    223     /// be loaded with 3 instructions.
    224     case MBlazeISD::JmpLink: {
    225       if (TM.getRelocationModel() == Reloc::PIC_) {
    226         SDValue Chain  = Node->getOperand(0);
    227         SDValue Callee = Node->getOperand(1);
    228         SDValue R20Reg = CurDAG->getRegister(MBlaze::R20, MVT::i32);
    229         SDValue InFlag(0, 0);
    230 
    231         if ((isa<GlobalAddressSDNode>(Callee)) ||
    232             (isa<ExternalSymbolSDNode>(Callee)))
    233         {
    234           /// Direct call for global addresses and external symbols
    235           SDValue GPReg = CurDAG->getRegister(MBlaze::R15, MVT::i32);
    236 
    237           // Use load to get GOT target
    238           SDValue Ops[] = { Callee, GPReg, Chain };
    239           SDValue Load = SDValue(CurDAG->getMachineNode(MBlaze::LW, dl,
    240                                  MVT::i32, MVT::Other, Ops, 3), 0);
    241           Chain = Load.getValue(1);
    242 
    243           // Call target must be on T9
    244           Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Load, InFlag);
    245         } else
    246           /// Indirect call
    247           Chain = CurDAG->getCopyToReg(Chain, dl, R20Reg, Callee, InFlag);
    248 
    249         // Emit Jump and Link Register
    250         SDNode *ResNode = CurDAG->getMachineNode(MBlaze::BRLID, dl, MVT::Other,
    251                                                  MVT::Glue, R20Reg, Chain);
    252         Chain  = SDValue(ResNode, 0);
    253         InFlag = SDValue(ResNode, 1);
    254         ReplaceUses(SDValue(Node, 0), Chain);
    255         ReplaceUses(SDValue(Node, 1), InFlag);
    256         return ResNode;
    257       }
    258     }
    259   }
    260 
    261   // Select the default instruction
    262   SDNode *ResNode = SelectCode(Node);
    263 
    264   DEBUG(errs() << "=> ");
    265   if (ResNode == NULL || ResNode == Node)
    266     DEBUG(Node->dump(CurDAG));
    267   else
    268     DEBUG(ResNode->dump(CurDAG));
    269   DEBUG(errs() << "\n");
    270   return ResNode;
    271 }
    272 
    273 /// createMBlazeISelDag - This pass converts a legalized DAG into a
    274 /// MBlaze-specific DAG, ready for instruction scheduling.
    275 FunctionPass *llvm::createMBlazeISelDag(MBlazeTargetMachine &TM) {
    276   return new MBlazeDAGToDAGISel(TM);
    277 }
    278