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