SparcISelDAGToDAG.cpp revision 52a261b3c1391c5fec399ddeb3fc6ee9541e8790
13306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===-- SparcISelDAGToDAG.cpp - A dag to dag inst selector for Sparc ------===//
23306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//
33306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//                     The LLVM Compiler Infrastructure
43306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//
53306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong// This file is distributed under the University of Illinois Open Source
63306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong// License. See LICENSE.TXT for details.
73306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//
83306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===----------------------------------------------------------------------===//
93306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//
103306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong// This file defines an instruction selector for the SPARC target.
113306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//
123306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===----------------------------------------------------------------------===//
133306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
143306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "SparcTargetMachine.h"
153306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/Intrinsics.h"
163306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/CodeGen/SelectionDAGISel.h"
173306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/Support/Compiler.h"
183306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/Support/Debug.h"
193306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/Support/ErrorHandling.h"
203306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "llvm/Support/raw_ostream.h"
213306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongusing namespace llvm;
223306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
233306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===----------------------------------------------------------------------===//
243306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong// Instruction Selector Implementation
253306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===----------------------------------------------------------------------===//
263306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
273306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong//===--------------------------------------------------------------------===//
283306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong/// SparcDAGToDAGISel - SPARC specific code to select SPARC machine
293306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong/// instructions for SelectionDAG operations.
303306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong///
313306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongnamespace {
323306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongclass SparcDAGToDAGISel : public SelectionDAGISel {
333306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  /// Subtarget - Keep a pointer to the Sparc Subtarget around so that we can
343306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  /// make the right decision when generating code for different targets.
353306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  const SparcSubtarget &Subtarget;
363306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  SparcTargetMachine& TM;
373306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongpublic:
383306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  explicit SparcDAGToDAGISel(SparcTargetMachine &tm)
393306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    : SelectionDAGISel(tm),
403306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Subtarget(tm.getSubtarget<SparcSubtarget>()),
413306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      TM(tm) {
423306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
433306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
443306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  SDNode *Select(SDNode *N);
453306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
463306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  // Complex Pattern Selectors.
473306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  bool SelectADDRrr(SDValue N, SDValue &R1, SDValue &R2);
483306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  bool SelectADDRri(SDValue N, SDValue &Base, SDValue &Offset);
493306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
503306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
513306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  /// inline asm expressions.
523306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
533306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                            char ConstraintCode,
543306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                            std::vector<SDValue> &OutOps);
553306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
563306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  virtual const char *getPassName() const {
573306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return "SPARC DAG->DAG Pattern Instruction Selection";
583306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
593306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
603306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  // Include the pieces autogenerated from the target description.
613306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong#include "SparcGenDAGISel.inc"
623306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
633306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongprivate:
643306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  SDNode* getGlobalBaseReg();
653306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong};
663306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong}  // end anonymous namespace
673306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
683306cfee3bf38ab207a0504e49c2d492bb73ffbfJames DongSDNode* SparcDAGToDAGISel::getGlobalBaseReg() {
693306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  unsigned GlobalBaseReg = TM.getInstrInfo()->getGlobalBaseReg(MF);
703306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  return CurDAG->getRegister(GlobalBaseReg, TLI.getPointerTy()).getNode();
713306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong}
723306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
733306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongbool SparcDAGToDAGISel::SelectADDRri(SDValue Addr,
743306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                     SDValue &Base, SDValue &Offset) {
753306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
763306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
773306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    Offset = CurDAG->getTargetConstant(0, MVT::i32);
783306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return true;
793306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
803306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
813306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Addr.getOpcode() == ISD::TargetGlobalAddress)
823306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return false;  // direct calls.
833306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
843306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (Addr.getOpcode() == ISD::ADD) {
853306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
863306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      if (isInt<13>(CN->getSExtValue())) {
873306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        if (FrameIndexSDNode *FIN =
883306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
893306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong          // Constant offset from frame ref.
903306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong          Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
913306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        } else {
923306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong          Base = Addr.getOperand(0);
933306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        }
943306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        Offset = CurDAG->getTargetConstant(CN->getZExtValue(), MVT::i32);
953306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        return true;
963306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      }
973306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    }
983306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (Addr.getOperand(0).getOpcode() == SPISD::Lo) {
993306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Base = Addr.getOperand(1);
1003306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Offset = Addr.getOperand(0).getOperand(0);
1013306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      return true;
1023306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    }
1033306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (Addr.getOperand(1).getOpcode() == SPISD::Lo) {
1043306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Base = Addr.getOperand(0);
1053306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Offset = Addr.getOperand(1).getOperand(0);
1063306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      return true;
1073306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    }
1083306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
1093306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  Base = Addr;
1103306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  Offset = CurDAG->getTargetConstant(0, MVT::i32);
1113306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  return true;
1123306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong}
1133306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1143306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dongbool SparcDAGToDAGISel::SelectADDRrr(SDValue Addr, SDValue &R1, SDValue &R2) {
1153306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (Addr.getOpcode() == ISD::FrameIndex) return false;
1163306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
1173306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      Addr.getOpcode() == ISD::TargetGlobalAddress)
1183306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return false;  // direct calls.
1193306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1203306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (Addr.getOpcode() == ISD::ADD) {
1213306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
1223306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      if (isInt<13>(CN->getSExtValue()))
1233306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        return false;  // Let the reg+imm pattern catch this!
1243306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (Addr.getOperand(0).getOpcode() == SPISD::Lo ||
1253306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong        Addr.getOperand(1).getOpcode() == SPISD::Lo)
1263306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      return false;  // Let the reg+imm pattern catch this!
1273306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    R1 = Addr.getOperand(0);
1283306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    R2 = Addr.getOperand(1);
1293306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return true;
1303306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
1313306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1323306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  R1 = Addr;
1333306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  R2 = CurDAG->getRegister(SP::G0, MVT::i32);
1343306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  return true;
1353306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong}
1363306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1373306cfee3bf38ab207a0504e49c2d492bb73ffbfJames DongSDNode *SparcDAGToDAGISel::Select(SDNode *N) {
1383306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  DebugLoc dl = N->getDebugLoc();
1393306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  if (N->isMachineOpcode())
1403306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return NULL;   // Already selected.
1413306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1423306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  switch (N->getOpcode()) {
1433306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  default: break;
1443306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  case SPISD::GLOBAL_BASE_REG:
1453306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return getGlobalBaseReg();
1463306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1473306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  case ISD::SDIV:
1483306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  case ISD::UDIV: {
1493306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    // FIXME: should use a custom expander to expose the SRA to the dag.
1503306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    SDValue DivLHS = N->getOperand(0);
1513306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    SDValue DivRHS = N->getOperand(1);
1523306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1533306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    // Set the Y register to the high-part.
1543306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    SDValue TopPart;
1553306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    if (N->getOpcode() == ISD::SDIV) {
1563306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      TopPart = SDValue(CurDAG->getMachineNode(SP::SRAri, dl, MVT::i32, DivLHS,
1573306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                   CurDAG->getTargetConstant(31, MVT::i32)), 0);
1583306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    } else {
1593306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong      TopPart = CurDAG->getRegister(SP::G0, MVT::i32);
1603306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    }
1613306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    TopPart = SDValue(CurDAG->getMachineNode(SP::WRYrr, dl, MVT::Flag, TopPart,
1623306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                     CurDAG->getRegister(SP::G0, MVT::i32)), 0);
1633306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong
1643306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    // FIXME: Handle div by immediate.
1653306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    unsigned Opcode = N->getOpcode() == ISD::SDIV ? SP::SDIVrr : SP::UDIVrr;
1663306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    return CurDAG->SelectNodeTo(N, Opcode, MVT::i32, DivLHS, DivRHS,
1673306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong                                TopPart);
1683306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  }
1693306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  case ISD::MULHU:
1703306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong  case ISD::MULHS: {
1713306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    // FIXME: Handle mul by immediate.
1723306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    SDValue MulLHS = N->getOperand(0);
1733306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    SDValue MulRHS = N->getOperand(1);
1743306cfee3bf38ab207a0504e49c2d492bb73ffbfJames Dong    unsigned Opcode = N->getOpcode() == ISD::MULHU ? SP::UMULrr : SP::SMULrr;
175    SDNode *Mul = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Flag,
176                                         MulLHS, MulRHS);
177    // The high part is in the Y register.
178    return CurDAG->SelectNodeTo(N, SP::RDY, MVT::i32, SDValue(Mul, 1));
179    return NULL;
180  }
181  }
182
183  return SelectCode(N);
184}
185
186
187/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
188/// inline asm expressions.
189bool
190SparcDAGToDAGISel::SelectInlineAsmMemoryOperand(const SDValue &Op,
191                                                char ConstraintCode,
192                                                std::vector<SDValue> &OutOps) {
193  SDValue Op0, Op1;
194  switch (ConstraintCode) {
195  default: return true;
196  case 'm':   // memory
197   if (!SelectADDRrr(Op, Op0, Op1))
198     SelectADDRri(Op, Op0, Op1);
199   break;
200  }
201
202  OutOps.push_back(Op0);
203  OutOps.push_back(Op1);
204  return false;
205}
206
207/// createSparcISelDag - This pass converts a legalized DAG into a
208/// SPARC-specific DAG, ready for instruction scheduling.
209///
210FunctionPass *llvm::createSparcISelDag(SparcTargetMachine &TM) {
211  return new SparcDAGToDAGISel(TM);
212}
213