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 "PTXMachineFunctionInfo.h"
     16 #include "PTXTargetMachine.h"
     17 #include "llvm/ADT/StringExtras.h"
     18 #include "llvm/CodeGen/SelectionDAGISel.h"
     19 #include "llvm/DerivedTypes.h"
     20 #include "llvm/Support/Debug.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 using namespace llvm;
     24 
     25 namespace {
     26 // PTXDAGToDAGISel - PTX specific code to select PTX machine
     27 // instructions for SelectionDAG operations.
     28 class PTXDAGToDAGISel : public SelectionDAGISel {
     29   public:
     30     PTXDAGToDAGISel(PTXTargetMachine &TM, CodeGenOpt::Level OptLevel);
     31 
     32     virtual const char *getPassName() const {
     33       return "PTX DAG->DAG Pattern Instruction Selection";
     34     }
     35 
     36     SDNode *Select(SDNode *Node);
     37 
     38     // Complex Pattern Selectors.
     39     bool SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2);
     40     bool SelectADDRri(SDValue &Addr, SDValue &Base, SDValue &Offset);
     41     bool SelectADDRii(SDValue &Addr, SDValue &Base, SDValue &Offset);
     42     bool SelectADDRlocal(SDValue &Addr, SDValue &Base, SDValue &Offset);
     43 
     44     // Include the pieces auto'gened from the target description
     45 #include "PTXGenDAGISel.inc"
     46 
     47   private:
     48     // We need this only because we can't match intruction BRAdp
     49     // pattern (PTXbrcond bb:$d, ...) in PTXInstrInfo.td
     50     SDNode *SelectBRCOND(SDNode *Node);
     51 
     52     SDNode *SelectREADPARAM(SDNode *Node);
     53     SDNode *SelectWRITEPARAM(SDNode *Node);
     54     SDNode *SelectFrameIndex(SDNode *Node);
     55 
     56     bool isImm(const SDValue &operand);
     57     bool SelectImm(const SDValue &operand, SDValue &imm);
     58 
     59     const PTXSubtarget& getSubtarget() const;
     60 }; // class PTXDAGToDAGISel
     61 } // namespace
     62 
     63 // createPTXISelDag - This pass converts a legalized DAG into a
     64 // PTX-specific DAG, ready for instruction scheduling
     65 FunctionPass *llvm::createPTXISelDag(PTXTargetMachine &TM,
     66                                      CodeGenOpt::Level OptLevel) {
     67   return new PTXDAGToDAGISel(TM, OptLevel);
     68 }
     69 
     70 PTXDAGToDAGISel::PTXDAGToDAGISel(PTXTargetMachine &TM,
     71                                  CodeGenOpt::Level OptLevel)
     72   : SelectionDAGISel(TM, OptLevel) {}
     73 
     74 SDNode *PTXDAGToDAGISel::Select(SDNode *Node) {
     75   switch (Node->getOpcode()) {
     76     case ISD::BRCOND:
     77       return SelectBRCOND(Node);
     78     case PTXISD::READ_PARAM:
     79       return SelectREADPARAM(Node);
     80     case PTXISD::WRITE_PARAM:
     81       return SelectWRITEPARAM(Node);
     82     case ISD::FrameIndex:
     83       return SelectFrameIndex(Node);
     84     default:
     85       return SelectCode(Node);
     86   }
     87 }
     88 
     89 SDNode *PTXDAGToDAGISel::SelectBRCOND(SDNode *Node) {
     90   assert(Node->getNumOperands() >= 3);
     91 
     92   SDValue Chain  = Node->getOperand(0);
     93   SDValue Pred   = Node->getOperand(1);
     94   SDValue Target = Node->getOperand(2); // branch target
     95   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::Normal, MVT::i32);
     96   DebugLoc dl = Node->getDebugLoc();
     97 
     98   assert(Target.getOpcode()  == ISD::BasicBlock);
     99   assert(Pred.getValueType() == MVT::i1);
    100 
    101   // Emit BRAdp
    102   SDValue Ops[] = { Target, Pred, PredOp, Chain };
    103   return CurDAG->getMachineNode(PTX::BRAdp, dl, MVT::Other, Ops, 4);
    104 }
    105 
    106 SDNode *PTXDAGToDAGISel::SelectREADPARAM(SDNode *Node) {
    107   SDValue Chain = Node->getOperand(0);
    108   SDValue Index = Node->getOperand(1);
    109 
    110   int OpCode;
    111 
    112   // Get the type of parameter we are reading
    113   EVT VT = Node->getValueType(0);
    114   assert(VT.isSimple() && "READ_PARAM only implemented for MVT types");
    115 
    116   MVT Type = VT.getSimpleVT();
    117 
    118   if (Type == MVT::i1)
    119     OpCode = PTX::READPARAMPRED;
    120   else if (Type == MVT::i16)
    121     OpCode = PTX::READPARAMI16;
    122   else if (Type == MVT::i32)
    123     OpCode = PTX::READPARAMI32;
    124   else if (Type == MVT::i64)
    125     OpCode = PTX::READPARAMI64;
    126   else if (Type == MVT::f32)
    127     OpCode = PTX::READPARAMF32;
    128   else {
    129     assert(Type == MVT::f64 && "Unexpected type!");
    130     OpCode = PTX::READPARAMF64;
    131   }
    132 
    133   SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
    134   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
    135   DebugLoc dl = Node->getDebugLoc();
    136 
    137   SDValue Ops[] = { Index, Pred, PredOp, Chain };
    138   return CurDAG->getMachineNode(OpCode, dl, VT, Ops, 4);
    139 }
    140 
    141 SDNode *PTXDAGToDAGISel::SelectWRITEPARAM(SDNode *Node) {
    142 
    143   SDValue Chain = Node->getOperand(0);
    144   SDValue Value = Node->getOperand(1);
    145 
    146   int OpCode;
    147 
    148   //Node->dumpr(CurDAG);
    149 
    150   // Get the type of parameter we are writing
    151   EVT VT = Value->getValueType(0);
    152   assert(VT.isSimple() && "WRITE_PARAM only implemented for MVT types");
    153 
    154   MVT Type = VT.getSimpleVT();
    155 
    156   if (Type == MVT::i1)
    157     OpCode = PTX::WRITEPARAMPRED;
    158   else if (Type == MVT::i16)
    159     OpCode = PTX::WRITEPARAMI16;
    160   else if (Type == MVT::i32)
    161     OpCode = PTX::WRITEPARAMI32;
    162   else if (Type == MVT::i64)
    163     OpCode = PTX::WRITEPARAMI64;
    164   else if (Type == MVT::f32)
    165     OpCode = PTX::WRITEPARAMF32;
    166   else if (Type == MVT::f64)
    167     OpCode = PTX::WRITEPARAMF64;
    168   else
    169     llvm_unreachable("Invalid type in SelectWRITEPARAM");
    170 
    171   SDValue Pred = CurDAG->getRegister(PTX::NoRegister, MVT::i1);
    172   SDValue PredOp = CurDAG->getTargetConstant(PTXPredicate::None, MVT::i32);
    173   DebugLoc dl = Node->getDebugLoc();
    174 
    175   SDValue Ops[] = { Value, Pred, PredOp, Chain };
    176   SDNode* Ret = CurDAG->getMachineNode(OpCode, dl, MVT::Other, Ops, 4);
    177 
    178   //dbgs() << "SelectWRITEPARAM produced:\n\t";
    179   //Ret->dumpr(CurDAG);
    180 
    181   return Ret;
    182 }
    183 
    184 SDNode *PTXDAGToDAGISel::SelectFrameIndex(SDNode *Node) {
    185   int FI = cast<FrameIndexSDNode>(Node)->getIndex();
    186   //dbgs() << "Selecting FrameIndex at index " << FI << "\n";
    187   //SDValue TFI = CurDAG->getTargetFrameIndex(FI, Node->getValueType(0));
    188 
    189   PTXMachineFunctionInfo *MFI = MF->getInfo<PTXMachineFunctionInfo>();
    190 
    191   SDValue FrameSymbol = CurDAG->getTargetExternalSymbol(MFI->getFrameSymbol(FI),
    192                                                         Node->getValueType(0));
    193 
    194   return FrameSymbol.getNode();
    195 }
    196 
    197 // Match memory operand of the form [reg+reg]
    198 bool PTXDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, SDValue &R2) {
    199   if (Addr.getOpcode() != ISD::ADD || Addr.getNumOperands() < 2 ||
    200       isImm(Addr.getOperand(0)) || isImm(Addr.getOperand(1)))
    201     return false;
    202 
    203   assert(Addr.getValueType().isSimple() && "Type must be simple");
    204 
    205   R1 = Addr;
    206   R2 = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    207 
    208   return true;
    209 }
    210 
    211 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
    212 bool PTXDAGToDAGISel::SelectADDRri(SDValue &Addr, SDValue &Base,
    213                                    SDValue &Offset) {
    214   // FrameIndex addresses are handled separately
    215   //errs() << "SelectADDRri: ";
    216   //Addr.getNode()->dumpr();
    217   if (isa<FrameIndexSDNode>(Addr)) {
    218     //errs() << "Failure\n";
    219     return false;
    220   }
    221 
    222   if (CurDAG->isBaseWithConstantOffset(Addr)) {
    223     Base = Addr.getOperand(0);
    224     if (isa<FrameIndexSDNode>(Base)) {
    225       //errs() << "Failure\n";
    226       return false;
    227     }
    228     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
    229     Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
    230     //errs() << "Success\n";
    231     return true;
    232   }
    233 
    234   /*if (Addr.getNumOperands() == 1) {
    235     Base = Addr;
    236     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    237     errs() << "Success\n";
    238     return true;
    239   }*/
    240 
    241   //errs() << "SelectADDRri fails on: ";
    242   //Addr.getNode()->dumpr();
    243 
    244   if (isImm(Addr)) {
    245     //errs() << "Failure\n";
    246     return false;
    247   }
    248 
    249   Base = Addr;
    250   Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    251 
    252   //errs() << "Success\n";
    253   return true;
    254 
    255   /*if (Addr.getOpcode() != ISD::ADD) {
    256     // let SelectADDRii handle the [imm] case
    257     if (isImm(Addr))
    258       return false;
    259     // it is [reg]
    260 
    261     assert(Addr.getValueType().isSimple() && "Type must be simple");
    262     Base = Addr;
    263     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    264 
    265     return true;
    266   }
    267 
    268   if (Addr.getNumOperands() < 2)
    269     return false;
    270 
    271   // let SelectADDRii handle the [imm+imm] case
    272   if (isImm(Addr.getOperand(0)) && isImm(Addr.getOperand(1)))
    273     return false;
    274 
    275   // try [reg+imm] and [imm+reg]
    276   for (int i = 0; i < 2; i ++)
    277     if (SelectImm(Addr.getOperand(1-i), Offset)) {
    278       Base = Addr.getOperand(i);
    279       return true;
    280     }
    281 
    282   // neither [reg+imm] nor [imm+reg]
    283   return false;*/
    284 }
    285 
    286 // Match memory operand of the form [imm+imm] and [imm]
    287 bool PTXDAGToDAGISel::SelectADDRii(SDValue &Addr, SDValue &Base,
    288                                    SDValue &Offset) {
    289   // is [imm+imm]?
    290   if (Addr.getOpcode() == ISD::ADD) {
    291     return SelectImm(Addr.getOperand(0), Base) &&
    292            SelectImm(Addr.getOperand(1), Offset);
    293   }
    294 
    295   // is [imm]?
    296   if (SelectImm(Addr, Base)) {
    297     assert(Addr.getValueType().isSimple() && "Type must be simple");
    298 
    299     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    300 
    301     return true;
    302   }
    303 
    304   return false;
    305 }
    306 
    307 // Match memory operand of the form [reg], [imm+reg], and [reg+imm]
    308 bool PTXDAGToDAGISel::SelectADDRlocal(SDValue &Addr, SDValue &Base,
    309                                       SDValue &Offset) {
    310   //errs() << "SelectADDRlocal: ";
    311   //Addr.getNode()->dumpr();
    312   if (isa<FrameIndexSDNode>(Addr)) {
    313     Base = Addr;
    314     Offset = CurDAG->getTargetConstant(0, Addr.getValueType().getSimpleVT());
    315     //errs() << "Success\n";
    316     return true;
    317   }
    318 
    319   if (CurDAG->isBaseWithConstantOffset(Addr)) {
    320     Base = Addr.getOperand(0);
    321     if (!isa<FrameIndexSDNode>(Base)) {
    322       //errs() << "Failure\n";
    323       return false;
    324     }
    325     ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
    326     Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
    327     //errs() << "Offset: ";
    328     //Offset.getNode()->dumpr();
    329     //errs() << "Success\n";
    330     return true;
    331   }
    332 
    333   //errs() << "Failure\n";
    334   return false;
    335 }
    336 
    337 bool PTXDAGToDAGISel::isImm(const SDValue &operand) {
    338   return ConstantSDNode::classof(operand.getNode());
    339 }
    340 
    341 bool PTXDAGToDAGISel::SelectImm(const SDValue &operand, SDValue &imm) {
    342   SDNode *node = operand.getNode();
    343   if (!ConstantSDNode::classof(node))
    344     return false;
    345 
    346   ConstantSDNode *CN = cast<ConstantSDNode>(node);
    347   imm = CurDAG->getTargetConstant(*CN->getConstantIntValue(),
    348                                   operand.getValueType());
    349   return true;
    350 }
    351 
    352 const PTXSubtarget& PTXDAGToDAGISel::getSubtarget() const
    353 {
    354   return TM.getSubtarget<PTXSubtarget>();
    355 }
    356 
    357