Home | History | Annotate | Download | only in Lanai
      1 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===//
      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 Lanai target.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "Lanai.h"
     15 #include "LanaiMachineFunctionInfo.h"
     16 #include "LanaiRegisterInfo.h"
     17 #include "LanaiSubtarget.h"
     18 #include "LanaiTargetMachine.h"
     19 #include "llvm/CodeGen/MachineConstantPool.h"
     20 #include "llvm/CodeGen/MachineFrameInfo.h"
     21 #include "llvm/CodeGen/MachineFunction.h"
     22 #include "llvm/CodeGen/MachineInstrBuilder.h"
     23 #include "llvm/CodeGen/MachineRegisterInfo.h"
     24 #include "llvm/CodeGen/SelectionDAGISel.h"
     25 #include "llvm/IR/CFG.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/Debug.h"
     31 #include "llvm/Support/ErrorHandling.h"
     32 #include "llvm/Support/raw_ostream.h"
     33 #include "llvm/Target/TargetMachine.h"
     34 
     35 using namespace llvm;
     36 
     37 #define DEBUG_TYPE "lanai-isel"
     38 
     39 //===----------------------------------------------------------------------===//
     40 // Instruction Selector Implementation
     41 //===----------------------------------------------------------------------===//
     42 
     43 //===----------------------------------------------------------------------===//
     44 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine
     45 // instructions for SelectionDAG operations.
     46 //===----------------------------------------------------------------------===//
     47 namespace {
     48 
     49 class LanaiDAGToDAGISel : public SelectionDAGISel {
     50 public:
     51   explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine)
     52       : SelectionDAGISel(TargetMachine) {}
     53 
     54   bool runOnMachineFunction(MachineFunction &MF) override {
     55     return SelectionDAGISel::runOnMachineFunction(MF);
     56   }
     57 
     58   // Pass Name
     59   const char *getPassName() const override {
     60     return "Lanai DAG->DAG Pattern Instruction Selection";
     61   }
     62 
     63   bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
     64                                     std::vector<SDValue> &OutOps) override;
     65 
     66 private:
     67 // Include the pieces autogenerated from the target description.
     68 #include "LanaiGenDAGISel.inc"
     69 
     70   // Instruction Selection not handled by the auto-generated tablgen
     71   void Select(SDNode *N) override;
     72 
     73   // Support functions for the opcodes of Instruction Selection
     74   // not handled by the auto-generated tablgen
     75   void selectFrameIndex(SDNode *N);
     76 
     77   // Complex Pattern for address selection.
     78   bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset,
     79                     SDValue &AluOp);
     80   bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp);
     81   bool selectAddrSls(SDValue Addr, SDValue &Offset);
     82   bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
     83                       SDValue &AluOp);
     84 
     85   // getI32Imm - Return a target constant with the specified value, of type i32.
     86   inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) {
     87     return CurDAG->getTargetConstant(Imm, DL, MVT::i32);
     88   }
     89 
     90 private:
     91   bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset,
     92                         SDValue &AluOp, bool RiMode);
     93 };
     94 
     95 bool canBeRepresentedAsSls(const ConstantSDNode &CN) {
     96   // Fits in 21-bit signed immediate and two low-order bits are zero.
     97   return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0);
     98 }
     99 
    100 } // namespace
    101 
    102 // Helper functions for ComplexPattern used on LanaiInstrInfo
    103 // Used on Lanai Load/Store instructions.
    104 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) {
    105   if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
    106     SDLoc DL(Addr);
    107     // Loading from a constant address.
    108     if (canBeRepresentedAsSls(*CN)) {
    109       int32_t Imm = CN->getSExtValue();
    110       Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
    111       return true;
    112     }
    113   }
    114   if (Addr.getOpcode() == ISD::OR &&
    115       Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) {
    116     Offset = Addr.getOperand(1).getOperand(0);
    117     return true;
    118   }
    119   return false;
    120 }
    121 
    122 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base,
    123                                          SDValue &Offset, SDValue &AluOp,
    124                                          bool RiMode) {
    125   SDLoc DL(Addr);
    126 
    127   if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) {
    128     if (RiMode) {
    129       // Fits in 16-bit signed immediate.
    130       if (isInt<16>(CN->getSExtValue())) {
    131         int16_t Imm = CN->getSExtValue();
    132         Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
    133         Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
    134         AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
    135         return true;
    136       }
    137       // Allow SLS to match if the constant doesn't fit in 16 bits but can be
    138       // represented as an SLS.
    139       if (canBeRepresentedAsSls(*CN))
    140         return false;
    141     } else {
    142       // Fits in 10-bit signed immediate.
    143       if (isInt<10>(CN->getSExtValue())) {
    144         int16_t Imm = CN->getSExtValue();
    145         Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0));
    146         Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0));
    147         AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
    148         return true;
    149       }
    150     }
    151   }
    152 
    153   // if Address is FI, get the TargetFrameIndex.
    154   if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
    155     Base = CurDAG->getTargetFrameIndex(
    156         FIN->getIndex(),
    157         getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
    158     Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
    159     AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
    160     return true;
    161   }
    162 
    163   // Skip direct calls
    164   if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
    165        Addr.getOpcode() == ISD::TargetGlobalAddress))
    166     return false;
    167 
    168   // Address of the form imm + reg
    169   ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
    170   if (AluOperator == ISD::ADD) {
    171     AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
    172     // Addresses of the form FI+const
    173     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
    174       if ((RiMode && isInt<16>(CN->getSExtValue())) ||
    175           (!RiMode && isInt<10>(CN->getSExtValue()))) {
    176         // If the first operand is a FI, get the TargetFI Node
    177         if (FrameIndexSDNode *FIN =
    178                 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
    179           Base = CurDAG->getTargetFrameIndex(
    180               FIN->getIndex(),
    181               getTargetLowering()->getPointerTy(CurDAG->getDataLayout()));
    182         } else {
    183           Base = Addr.getOperand(0);
    184         }
    185 
    186         Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32);
    187         return true;
    188       }
    189   }
    190 
    191   // Let SLS match SMALL instead of RI.
    192   if (AluOperator == ISD::OR && RiMode &&
    193       Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
    194     return false;
    195 
    196   Base = Addr;
    197   Offset = CurDAG->getTargetConstant(0, DL, MVT::i32);
    198   AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32);
    199   return true;
    200 }
    201 
    202 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base,
    203                                      SDValue &Offset, SDValue &AluOp) {
    204   return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RImode=*/true);
    205 }
    206 
    207 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base,
    208                                        SDValue &Offset, SDValue &AluOp) {
    209   return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false);
    210 }
    211 
    212 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2,
    213                                      SDValue &AluOp) {
    214   // if Address is FI, get the TargetFrameIndex.
    215   if (Addr.getOpcode() == ISD::FrameIndex)
    216     return false;
    217 
    218   // Skip direct calls
    219   if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
    220        Addr.getOpcode() == ISD::TargetGlobalAddress))
    221     return false;
    222 
    223   // Address of the form OP + OP
    224   ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode());
    225   LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator);
    226   if (AluCode != LPAC::UNKNOWN) {
    227     // Skip addresses of the form FI OP const
    228     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
    229       if (isInt<16>(CN->getSExtValue()))
    230         return false;
    231 
    232     // Skip addresses with hi/lo operands
    233     if (Addr.getOperand(0).getOpcode() == LanaiISD::HI ||
    234         Addr.getOperand(0).getOpcode() == LanaiISD::LO ||
    235         Addr.getOperand(0).getOpcode() == LanaiISD::SMALL ||
    236         Addr.getOperand(1).getOpcode() == LanaiISD::HI ||
    237         Addr.getOperand(1).getOpcode() == LanaiISD::LO ||
    238         Addr.getOperand(1).getOpcode() == LanaiISD::SMALL)
    239       return false;
    240 
    241     // Addresses of the form register OP register
    242     R1 = Addr.getOperand(0);
    243     R2 = Addr.getOperand(1);
    244     AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32);
    245     return true;
    246   }
    247 
    248   // Skip addresses with zero offset
    249   return false;
    250 }
    251 
    252 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand(
    253     const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
    254   SDValue Op0, Op1, AluOp;
    255   switch (ConstraintCode) {
    256   default:
    257     return true;
    258   case InlineAsm::Constraint_m: // memory
    259     if (!selectAddrRr(Op, Op0, Op1, AluOp) &&
    260         !selectAddrRi(Op, Op0, Op1, AluOp))
    261       return true;
    262     break;
    263   }
    264 
    265   OutOps.push_back(Op0);
    266   OutOps.push_back(Op1);
    267   OutOps.push_back(AluOp);
    268   return false;
    269 }
    270 
    271 // Select instructions not customized! Used for
    272 // expanded, promoted and normal instructions
    273 void LanaiDAGToDAGISel::Select(SDNode *Node) {
    274   unsigned Opcode = Node->getOpcode();
    275 
    276   // Dump information about the Node being selected
    277   DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");
    278 
    279   // If we have a custom node, we already have selected!
    280   if (Node->isMachineOpcode()) {
    281     DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
    282     return;
    283   }
    284 
    285   // Instruction Selection not handled by the auto-generated
    286   // tablegen selection should be handled here.
    287   switch (Opcode) {
    288   case ISD::FrameIndex:
    289     selectFrameIndex(Node);
    290     return;
    291   default:
    292     break;
    293   }
    294 
    295   // Select the default instruction
    296   SelectCode(Node);
    297 }
    298 
    299 void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) {
    300   SDLoc DL(Node);
    301   SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32);
    302   int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
    303   EVT VT = Node->getValueType(0);
    304   SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
    305   unsigned Opc = Lanai::ADD_I_LO;
    306   if (Node->hasOneUse()) {
    307     CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm);
    308     return;
    309   }
    310   ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm));
    311 }
    312 
    313 // createLanaiISelDag - This pass converts a legalized DAG into a
    314 // Lanai-specific DAG, ready for instruction scheduling.
    315 FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) {
    316   return new LanaiDAGToDAGISel(TM);
    317 }
    318