Sink InstructionSelect() out of each target into SDISel, and rename it
[oota-llvm.git] / lib / Target / XCore / XCoreISelDAGToDAG.cpp
1 //===-- XCoreISelDAGToDAG.cpp - A dag to dag inst selector for XCore ------===//
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 XCore target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "XCore.h"
15 #include "XCoreISelLowering.h"
16 #include "XCoreTargetMachine.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/Function.h"
19 #include "llvm/Intrinsics.h"
20 #include "llvm/CallingConv.h"
21 #include "llvm/Constants.h"
22 #include "llvm/LLVMContext.h"
23 #include "llvm/CodeGen/MachineFrameInfo.h"
24 #include "llvm/CodeGen/MachineFunction.h"
25 #include "llvm/CodeGen/MachineInstrBuilder.h"
26 #include "llvm/CodeGen/MachineRegisterInfo.h"
27 #include "llvm/CodeGen/SelectionDAG.h"
28 #include "llvm/CodeGen/SelectionDAGISel.h"
29 #include "llvm/Target/TargetLowering.h"
30 #include "llvm/Support/Compiler.h"
31 #include "llvm/Support/Debug.h"
32 #include "llvm/Support/ErrorHandling.h"
33 #include "llvm/Support/raw_ostream.h"
34 #include <queue>
35 #include <set>
36 using namespace llvm;
37
38 /// XCoreDAGToDAGISel - XCore specific code to select XCore machine
39 /// instructions for SelectionDAG operations.
40 ///
41 namespace {
42   class XCoreDAGToDAGISel : public SelectionDAGISel {
43     XCoreTargetLowering &Lowering;
44     const XCoreSubtarget &Subtarget;
45
46   public:
47     XCoreDAGToDAGISel(XCoreTargetMachine &TM)
48       : SelectionDAGISel(TM),
49         Lowering(*TM.getTargetLowering()), 
50         Subtarget(*TM.getSubtargetImpl()) { }
51
52     SDNode *Select(SDNode *N);
53     
54     /// getI32Imm - Return a target constant with the specified value, of type
55     /// i32.
56     inline SDValue getI32Imm(unsigned Imm) {
57       return CurDAG->getTargetConstant(Imm, MVT::i32);
58     }
59
60     // Complex Pattern Selectors.
61     bool SelectADDRspii(SDNode *Op, SDValue Addr, SDValue &Base,
62                         SDValue &Offset);
63     bool SelectADDRdpii(SDNode *Op, SDValue Addr, SDValue &Base,
64                         SDValue &Offset);
65     bool SelectADDRcpii(SDNode *Op, SDValue Addr, SDValue &Base,
66                         SDValue &Offset);
67     
68     virtual const char *getPassName() const {
69       return "XCore DAG->DAG Pattern Instruction Selection";
70     } 
71     
72     // Include the pieces autogenerated from the target description.
73   #include "XCoreGenDAGISel.inc"
74   };
75 }  // end anonymous namespace
76
77 /// createXCoreISelDag - This pass converts a legalized DAG into a 
78 /// XCore-specific DAG, ready for instruction scheduling.
79 ///
80 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
81   return new XCoreDAGToDAGISel(TM);
82 }
83
84 bool XCoreDAGToDAGISel::SelectADDRspii(SDNode *Op, SDValue Addr,
85                                   SDValue &Base, SDValue &Offset) {
86   FrameIndexSDNode *FIN = 0;
87   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
88     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
89     Offset = CurDAG->getTargetConstant(0, MVT::i32);
90     return true;
91   }
92   if (Addr.getOpcode() == ISD::ADD) {
93     ConstantSDNode *CN = 0;
94     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
95       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
96       && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
97       // Constant positive word offset from frame index
98       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
99       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
100       return true;
101     }
102   }
103   return false;
104 }
105
106 bool XCoreDAGToDAGISel::SelectADDRdpii(SDNode *Op, SDValue Addr,
107                                   SDValue &Base, SDValue &Offset) {
108   if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
109     Base = Addr.getOperand(0);
110     Offset = CurDAG->getTargetConstant(0, MVT::i32);
111     return true;
112   }
113   if (Addr.getOpcode() == ISD::ADD) {
114     ConstantSDNode *CN = 0;
115     if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
116       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
117       && (CN->getSExtValue() % 4 == 0)) {
118       // Constant word offset from a object in the data region
119       Base = Addr.getOperand(0).getOperand(0);
120       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
121       return true;
122     }
123   }
124   return false;
125 }
126
127 bool XCoreDAGToDAGISel::SelectADDRcpii(SDNode *Op, SDValue Addr,
128                                   SDValue &Base, SDValue &Offset) {
129   if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
130     Base = Addr.getOperand(0);
131     Offset = CurDAG->getTargetConstant(0, MVT::i32);
132     return true;
133   }
134   if (Addr.getOpcode() == ISD::ADD) {
135     ConstantSDNode *CN = 0;
136     if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
137       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
138       && (CN->getSExtValue() % 4 == 0)) {
139       // Constant word offset from a object in the data region
140       Base = Addr.getOperand(0).getOperand(0);
141       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
142       return true;
143     }
144   }
145   return false;
146 }
147
148 SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
149   DebugLoc dl = N->getDebugLoc();
150   EVT NVT = N->getValueType(0);
151   if (NVT == MVT::i32) {
152     switch (N->getOpcode()) {
153       default: break;
154       case ISD::Constant: {
155         if (Predicate_immMskBitp(N)) {
156           // Transformation function: get the size of a mask
157           int64_t MaskVal = cast<ConstantSDNode>(N)->getZExtValue();
158           assert(isMask_32(MaskVal));
159           // Look for the first non-zero bit
160           SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(MaskVal));
161           return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
162                                         MVT::i32, MskSize);
163         }
164         else if (! Predicate_immU16(N)) {
165           unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
166           SDValue CPIdx =
167             CurDAG->getTargetConstantPool(ConstantInt::get(
168                                   Type::getInt32Ty(*CurDAG->getContext()), Val),
169                                           TLI.getPointerTy());
170           return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 
171                                         MVT::Other, CPIdx, 
172                                         CurDAG->getEntryNode());
173         }
174         break;
175       }
176       case ISD::SMUL_LOHI: {
177         // FIXME fold addition into the macc instruction
178         SDValue Zero(CurDAG->getMachineNode(XCore::LDC_ru6, dl, MVT::i32,
179                                 CurDAG->getTargetConstant(0, MVT::i32)), 0);
180         SDValue Ops[] = { Zero, Zero, N->getOperand(0), N->getOperand(1) };
181         SDNode *ResNode = CurDAG->getMachineNode(XCore::MACCS_l4r, dl,
182                                                  MVT::i32, MVT::i32, Ops, 4);
183         ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
184         ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
185         return NULL;
186       }
187       case ISD::UMUL_LOHI: {
188         // FIXME fold addition into the macc / lmul instruction
189         SDValue Zero(CurDAG->getMachineNode(XCore::LDC_ru6, dl, MVT::i32,
190                                   CurDAG->getTargetConstant(0, MVT::i32)), 0);
191         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
192                             Zero, Zero };
193         SDNode *ResNode = CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32,
194                                                  MVT::i32, Ops, 4);
195         ReplaceUses(SDValue(N, 0), SDValue(ResNode, 1));
196         ReplaceUses(SDValue(N, 1), SDValue(ResNode, 0));
197         return NULL;
198       }
199       case XCoreISD::LADD: {
200         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
201                             N->getOperand(2) };
202         return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
203                                       Ops, 3);
204       }
205       case XCoreISD::LSUB: {
206         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
207                             N->getOperand(2) };
208         return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
209                                       Ops, 3);
210       }
211       // Other cases are autogenerated.
212     }
213   }
214   return SelectCode(N);
215 }