Home | History | Annotate | Download | only in PTX
      1 //===-- PTXISelDAGToDAG.cpp - A dag to dag inst selector for PTX ----------===//
      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 PTX target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "PTX.h"
     15 #include "PTXTargetMachine.h"
     16 #include "llvm/CodeGen/SelectionDAGISel.h"
     17 #include "llvm/DerivedTypes.h"
     18 #include "llvm/Support/Debug.h"
     19 #include "llvm/Support/raw_ostream.h"
     20 
     21 using namespace llvm;
     22 
     23 namespace {
     24 // PTXDAGToDAGISel - PTX specific code to select PTX machine
     25 // instructions for SelectionDAG operations.
     26 class PTXDAGToDAGISel : public SelectionDAGISel {
     27   public:
     28     PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
     29 
     30     virtual const char *getPassName() const {
     31       return "PTX DAG->DAG Pattern Instruction Selection";
     32     }
     33 
     34     SDNode *Select(SDNode *Node);
     35 
     36     // Complex Pattern Selectors.
     37     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
     38     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
     39     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
     40 
     41     // Include the pieces auto'gened from the target description
     42 #include "PTXGenDAGISel.inc"
     43 
     44   private:
     45     // We need this only because we can't match intruction BRAdp
     46     // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
     47     SDNode *SelectBRCOND(SDNode *Node);
     48 
     49     bool isImm(const SDValue &operand);
     50     bool SelectImm(const SDValue &operand, SDValue &imm);
     51 
     52     const PTXSubtarget& getSubtarget() const;
     53 }; // class PTXDAGToDAGISel
     54 } // namespace
     55 
     56 // createPTXISelDag - This pass converts a legalized DAG into a
     57 // PTX-specific DAG, ready for instruction scheduling
     58 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
     59                                      CodeGenOpt::Level OptLevel) {
     60   return new PTXDAGToDAGISel(TM, OptLevel);
     61 }
     62 
     63 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
     64                                  CodeGenOpt::Level OptLevel)
     65   : SelectionDAGISel(TM, OptLevel) {}
     66 
     67 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
     68   switch (Node->getOpcode()) {
     69     case ISD::BRCOND:
     70       return SelectBRCOND(Node);
     71     default:
     72       return SelectCode(Node);
     73   }
     74 }
     75 
     76 SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
     77   assert(Node->getNumOperands() >= 3);
     78 
     79   SDValue Chain  = Node->getOperand(0);
     80   SDValue Pred   = Node->getOperand(1);
     81   SDValue Target = Node->getOperand(2); // branch target
     82   SDValue PredOp = CurDAG->getTargetConstant(PTX::PRED_NORMAL, MVT::i32);
     83   DebugLoc dl = Node->getDebugLoc();
     84 
     85   assert(Target.getOpcode()  == ISD::BasicBlock);
     86   assert(Pred.getValueType() == MVT::i1);
     87 
     88   // Emit BRAdp
     89   SDValue Ops[] = { Target, Pred, PredOp, Chain };
     90   return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
     91 }
     92 
     93 // Match memory operand of the form [reg+reg]
     94 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
     95   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
     96       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
     97     return false;
     98 
     99   assert(Addr.getValueType().isSimple() && "Type must be simple");
    100 
    101   R1 = Addr;
    102   R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    103 
    104   return true;
    105 }
    106 
    107 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
    108 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
    109                                    SDValue &Offset) {
    110   if (Addr.getOpcode() != ISD::ADD) {
    111     // let SelectADDRii handle the [imm] case
    112     if (isImm(Addr))
    113       return false;
    114     // it is [reg]
    115 
    116     assert(Addr.getValueType().isSimple() && "Type must be simple");
    117 
    118     Base = Addr;
    119     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    120 
    121     return true;
    122   }
    123 
    124   if (Addr.getNumOperands() < 2)
    125     return false;
    126 
    127   // let SelectADDRii handle the [imm+imm] case
    128   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
    129     return false;
    130 
    131   // try [reg+imm] and [imm+reg]
    132   for (int i = 0; i < 2; i ++)
    133     if (SelectImm(Addr.getOperand(1-i), Offset)) {
    134       Base = Addr.getOperand(i);
    135       return true;
    136     }
    137 
    138   // neither [reg+imm] nor [imm+reg]
    139   return false;
    140 }
    141 
    142 // Match memory operand of the form [imm+imm] and [imm]
    143 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
    144                                    SDValue &Offset) {
    145   // is [imm+imm]?
    146   if (Addr.getOpcode() == ISD::ADD) {
    147     return SelectImm(Addr.getOperand(0), Base) &&
    148            SelectImm(Addr.getOperand(1), Offset);
    149   }
    150 
    151   // is [imm]?
    152   if (SelectImm(Addr, Base)) {
    153     assert(Addr.getValueType().isSimple() && "Type must be simple");
    154 
    155     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    156 
    157     return true;
    158   }
    159 
    160   return false;
    161 }
    162 
    163 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
    164   return ConstantSDNode::classof(operand.getNode());
    165 }
    166 
    167 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
    168   SDNode *node = operand.getNode();
    169   if (!ConstantSDNode::classof(node))
    170     return false;
    171 
    172   ConstantSDNode *CN = cast<ConstantSDNode>(node);
    173   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
    174                                   operand.getValueType());
    175   return true;
    176 }
    177 
    178 const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
    179 {
    180   return TM.getSubtarget<PTXSubtarget>();
    181 }
    182 
    183