XCoreISelDAGToDAG.cpp revision 193323
150397Sobrien//===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
2169689Skan//
3132718Skan//                     The LLVM Compiler Infrastructure
450397Sobrien//
550397Sobrien// This file is distributed under the University of Illinois Open Source
6132718Skan// License. See LICENSE.TXT for details.
750397Sobrien//
8132718Skan//===----------------------------------------------------------------------===//
950397Sobrien//
1050397Sobrien// This file defines an instruction selector for the XCore target.
1150397Sobrien//
1250397Sobrien//===----------------------------------------------------------------------===//
13132718Skan
1450397Sobrien#include "XCore.h"
1550397Sobrien#include "XCoreISelLowering.h"
1650397Sobrien#include "XCoreTargetMachine.h"
1750397Sobrien#include "llvm/DerivedTypes.h"
1850397Sobrien#include "llvm/Function.h"
19132718Skan#include "llvm/Intrinsics.h"
20169689Skan#include "llvm/CallingConv.h"
21169689Skan#include "llvm/Constants.h"
2250397Sobrien#include "llvm/CodeGen/MachineFrameInfo.h"
23132718Skan#include "llvm/CodeGen/MachineFunction.h"
24132718Skan#include "llvm/CodeGen/MachineInstrBuilder.h"
25132718Skan#include "llvm/CodeGen/MachineRegisterInfo.h"
26169689Skan#include "llvm/CodeGen/SelectionDAG.h"
27169689Skan#include "llvm/CodeGen/SelectionDAGISel.h"
28169689Skan#include "llvm/Target/TargetLowering.h"
29169689Skan#include "llvm/Support/Compiler.h"
30169689Skan#include "llvm/Support/Debug.h"
31169689Skan#include <queue>
32169689Skan#include <set>
33169689Skanusing namespace llvm;
34132718Skan
35132718Skan/// XCoreDAGToDAGISel - XCore specific code to select XCore machine
3650397Sobrien/// instructions for SelectionDAG operations.
3790075Sobrien///
3850397Sobriennamespace {
3950397Sobrien  class XCoreDAGToDAGISel : public SelectionDAGISel {
4050397Sobrien    XCoreTargetLowering &Lowering;
4150397Sobrien    const XCoreSubtarget &Subtarget;
4250397Sobrien
4350397Sobrien  public:
4450397Sobrien    XCoreDAGToDAGISel(XCoreTargetMachine &TM)
4550397Sobrien      : SelectionDAGISel(TM),
4690075Sobrien        Lowering(*TM.getTargetLowering()),
4750397Sobrien        Subtarget(*TM.getSubtargetImpl()) { }
4850397Sobrien
49169689Skan    SDNode *Select(SDValue Op);
5050397Sobrien
51132718Skan    /// getI32Imm - Return a target constant with the specified value, of type
52132718Skan    /// i32.
5390075Sobrien    inline SDValue getI32Imm(unsigned Imm) {
5490075Sobrien      return CurDAG->getTargetConstant(Imm, MVT::i32);
55132718Skan    }
56132718Skan
5790075Sobrien    // Complex Pattern Selectors.
5850397Sobrien    bool SelectADDRspii(SDValue Op, SDValue Addr, SDValue &Base,
5950397Sobrien                        SDValue &Offset);
6050397Sobrien    bool SelectADDRdpii(SDValue Op, SDValue Addr, SDValue &Base,
6150397Sobrien                        SDValue &Offset);
6250397Sobrien    bool SelectADDRcpii(SDValue Op, SDValue Addr, SDValue &Base,
6350397Sobrien                        SDValue &Offset);
6450397Sobrien
6550397Sobrien    virtual void InstructionSelect();
6650397Sobrien
6796263Sobrien    virtual const char *getPassName() const {
68132718Skan      return "XCore DAG->DAG Pattern Instruction Selection";
6950397Sobrien    }
7090075Sobrien
7150397Sobrien    // Include the pieces autogenerated from the target description.
7250397Sobrien  #include "XCoreGenDAGISel.inc"
7350397Sobrien  };
7450397Sobrien}  // end anonymous namespace
7550397Sobrien
7650397Sobrien/// createXCoreISelDag - This pass converts a legalized DAG into a
7750397Sobrien/// XCore-specific DAG, ready for instruction scheduling.
7850397Sobrien///
7990075SobrienFunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
8090075Sobrien  return new XCoreDAGToDAGISel(TM);
8190075Sobrien}
8290075Sobrien
8350397Sobrienbool XCoreDAGToDAGISel::SelectADDRspii(SDValue Op, SDValue Addr,
8450397Sobrien                                  SDValue &Base, SDValue &Offset) {
8550397Sobrien  FrameIndexSDNode *FIN = 0;
8650397Sobrien  if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
8750397Sobrien    Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
8850397Sobrien    Offset = CurDAG->getTargetConstant(0, MVT::i32);
8950397Sobrien    return true;
9050397Sobrien  }
9150397Sobrien  if (Addr.getOpcode() == ISD::ADD) {
9250397Sobrien    ConstantSDNode *CN = 0;
9390075Sobrien    if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
9450397Sobrien      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
9550397Sobrien      && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
9690075Sobrien      // Constant positive word offset from frame index
9790075Sobrien      Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
9850397Sobrien      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
9950397Sobrien      return true;
100169689Skan    }
10150397Sobrien  }
10250397Sobrien  return false;
10350397Sobrien}
104117395Skan
105117395Skanbool XCoreDAGToDAGISel::SelectADDRdpii(SDValue Op, SDValue Addr,
106117395Skan                                  SDValue &Base, SDValue &Offset) {
10750397Sobrien  if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
10850397Sobrien    Base = Addr.getOperand(0);
10950397Sobrien    Offset = CurDAG->getTargetConstant(0, MVT::i32);
11050397Sobrien    return true;
11150397Sobrien  }
11250397Sobrien  if (Addr.getOpcode() == ISD::ADD) {
11350397Sobrien    ConstantSDNode *CN = 0;
11450397Sobrien    if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
11550397Sobrien      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
11650397Sobrien      && (CN->getSExtValue() % 4 == 0)) {
11750397Sobrien      // Constant word offset from a object in the data region
11850397Sobrien      Base = Addr.getOperand(0).getOperand(0);
11950397Sobrien      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
12050397Sobrien      return true;
12150397Sobrien    }
12290075Sobrien  }
12350397Sobrien  return false;
124169689Skan}
125169689Skan
126169689Skanbool XCoreDAGToDAGISel::SelectADDRcpii(SDValue Op, SDValue Addr,
127169689Skan                                  SDValue &Base, SDValue &Offset) {
128169689Skan  if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
129169689Skan    Base = Addr.getOperand(0);
130169689Skan    Offset = CurDAG->getTargetConstant(0, MVT::i32);
131169689Skan    return true;
132169689Skan  }
133169689Skan  if (Addr.getOpcode() == ISD::ADD) {
134169689Skan    ConstantSDNode *CN = 0;
13550397Sobrien    if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
13650397Sobrien      && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
13790075Sobrien      && (CN->getSExtValue() % 4 == 0)) {
13850397Sobrien      // Constant word offset from a object in the data region
13950397Sobrien      Base = Addr.getOperand(0).getOperand(0);
14050397Sobrien      Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
14150397Sobrien      return true;
142169689Skan    }
14350397Sobrien  }
14450397Sobrien  return false;
14550397Sobrien}
14690075Sobrien
14750397Sobrien/// InstructionSelect - This callback is invoked by
14850397Sobrien/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
149132718Skanvoid XCoreDAGToDAGISel::
150132718SkanInstructionSelect() {
15150397Sobrien  DEBUG(BB->dump());
15250397Sobrien
15350397Sobrien  // Select target instructions for the DAG.
15450397Sobrien  SelectRoot(*CurDAG);
15550397Sobrien
15650397Sobrien  CurDAG->RemoveDeadNodes();
15750397Sobrien}
15850397Sobrien
15950397SobrienSDNode *XCoreDAGToDAGISel::Select(SDValue Op) {
16050397Sobrien  SDNode *N = Op.getNode();
16150397Sobrien  DebugLoc dl = N->getDebugLoc();
16250397Sobrien  MVT NVT = N->getValueType(0);
16350397Sobrien  if (NVT == MVT::i32) {
16450397Sobrien    switch (N->getOpcode()) {
16550397Sobrien      default: break;
16690075Sobrien      case ISD::Constant: {
16750397Sobrien        if (Predicate_immMskBitp(N)) {
16896263Sobrien          SDValue MskSize = Transform_msksize_xform(N);
16996263Sobrien          return CurDAG->getTargetNode(XCore::MKMSK_rus, dl, MVT::i32, MskSize);
17096263Sobrien        }
17150397Sobrien        else if (! Predicate_immU16(N)) {
17250397Sobrien          unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
17350397Sobrien          SDValue CPIdx =
17450397Sobrien            CurDAG->getTargetConstantPool(ConstantInt::get(Type::Int32Ty, Val),
17550397Sobrien                                          TLI.getPointerTy());
17650397Sobrien          return CurDAG->getTargetNode(XCore::LDWCP_lru6, dl, MVT::i32,
17750397Sobrien                                       MVT::Other, CPIdx,
17890075Sobrien                                       CurDAG->getEntryNode());
17950397Sobrien        }
18050397Sobrien        break;
181117395Skan      }
182117395Skan      case ISD::SMUL_LOHI: {
18390075Sobrien        // FIXME fold addition into the macc instruction
18490075Sobrien        if (!Subtarget.isXS1A()) {
18590075Sobrien          SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
18690075Sobrien                                  CurDAG->getTargetConstant(0, MVT::i32)), 0);
18790075Sobrien          SDValue Ops[] = { Zero, Zero, Op.getOperand(0), Op.getOperand(1) };
18890075Sobrien          SDNode *ResNode = CurDAG->getTargetNode(XCore::MACCS_l4r, dl,
18990075Sobrien                                                  MVT::i32, MVT::i32, Ops, 4);
19090075Sobrien          ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
19150397Sobrien          ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
19290075Sobrien          return NULL;
193132718Skan        }
194132718Skan        break;
195132718Skan      }
196169689Skan      case ISD::UMUL_LOHI: {
19790075Sobrien        // FIXME fold addition into the macc / lmul instruction
19890075Sobrien        SDValue Zero(CurDAG->getTargetNode(XCore::LDC_ru6, dl, MVT::i32,
19950397Sobrien                                  CurDAG->getTargetConstant(0, MVT::i32)), 0);
200132718Skan        SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
201132718Skan                            Zero, Zero };
202132718Skan        SDNode *ResNode = CurDAG->getTargetNode(XCore::LMUL_l6r, dl, MVT::i32,
203132718Skan                                                MVT::i32, Ops, 4);
204132718Skan        ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
205132718Skan        ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
206132718Skan        return NULL;
20796263Sobrien      }
20896263Sobrien      case XCoreISD::LADD: {
20996263Sobrien        if (!Subtarget.isXS1A()) {
21096263Sobrien          SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
21196263Sobrien                              Op.getOperand(2) };
21296263Sobrien          return CurDAG->getTargetNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
21396263Sobrien                                       Ops, 3);
214169689Skan        }
215132718Skan        break;
216169689Skan      }
217132718Skan      case XCoreISD::LSUB: {
218169689Skan        if (!Subtarget.isXS1A()) {
219132718Skan          SDValue Ops[] = { Op.getOperand(0), Op.getOperand(1),
220122180Skan                              Op.getOperand(2) };
221122180Skan          return CurDAG->getTargetNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
222122180Skan                                       Ops, 3);
223122180Skan        }
224169689Skan        break;
225169689Skan      }
226169689Skan      // Other cases are autogenerated.
227169689Skan    }
22896263Sobrien  }
229169689Skan  return SelectCode(Op);
230169689Skan}
231169689Skan