]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/Target/XCore/XCoreISelDAGToDAG.cpp
Update LLVM to r103004.
[FreeBSD/FreeBSD.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 "XCoreTargetMachine.h"
16 #include "llvm/DerivedTypes.h"
17 #include "llvm/Function.h"
18 #include "llvm/Intrinsics.h"
19 #include "llvm/CallingConv.h"
20 #include "llvm/Constants.h"
21 #include "llvm/LLVMContext.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     const 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(SDNode *N);
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(SDNode *Op, SDValue Addr, SDValue &Base,
61                         SDValue &Offset);
62     bool SelectADDRdpii(SDNode *Op, SDValue Addr, SDValue &Base,
63                         SDValue &Offset);
64     bool SelectADDRcpii(SDNode *Op, SDValue Addr, SDValue &Base,
65                         SDValue &Offset);
66     
67     virtual const char *getPassName() const {
68       return "XCore DAG->DAG Pattern Instruction Selection";
69     } 
70     
71     // Include the pieces autogenerated from the target description.
72   #include "XCoreGenDAGISel.inc"
73   };
74 }  // end anonymous namespace
75
76 /// createXCoreISelDag - This pass converts a legalized DAG into a 
77 /// XCore-specific DAG, ready for instruction scheduling.
78 ///
79 FunctionPass *llvm::createXCoreISelDag(XCoreTargetMachine &TM) {
80   return new XCoreDAGToDAGISel(TM);
81 }
82
83 bool XCoreDAGToDAGISel::SelectADDRspii(SDNode *Op, SDValue Addr,
84                                   SDValue &Base, SDValue &Offset) {
85   FrameIndexSDNode *FIN = 0;
86   if ((FIN = dyn_cast<FrameIndexSDNode>(Addr))) {
87     Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
88     Offset = CurDAG->getTargetConstant(0, MVT::i32);
89     return true;
90   }
91   if (Addr.getOpcode() == ISD::ADD) {
92     ConstantSDNode *CN = 0;
93     if ((FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
94       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
95       && (CN->getSExtValue() % 4 == 0 && CN->getSExtValue() >= 0)) {
96       // Constant positive word offset from frame index
97       Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32);
98       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
99       return true;
100     }
101   }
102   return false;
103 }
104
105 bool XCoreDAGToDAGISel::SelectADDRdpii(SDNode *Op, SDValue Addr,
106                                   SDValue &Base, SDValue &Offset) {
107   if (Addr.getOpcode() == XCoreISD::DPRelativeWrapper) {
108     Base = Addr.getOperand(0);
109     Offset = CurDAG->getTargetConstant(0, MVT::i32);
110     return true;
111   }
112   if (Addr.getOpcode() == ISD::ADD) {
113     ConstantSDNode *CN = 0;
114     if ((Addr.getOperand(0).getOpcode() == XCoreISD::DPRelativeWrapper)
115       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
116       && (CN->getSExtValue() % 4 == 0)) {
117       // Constant word offset from a object in the data region
118       Base = Addr.getOperand(0).getOperand(0);
119       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
120       return true;
121     }
122   }
123   return false;
124 }
125
126 bool XCoreDAGToDAGISel::SelectADDRcpii(SDNode *Op, SDValue Addr,
127                                   SDValue &Base, SDValue &Offset) {
128   if (Addr.getOpcode() == XCoreISD::CPRelativeWrapper) {
129     Base = Addr.getOperand(0);
130     Offset = CurDAG->getTargetConstant(0, MVT::i32);
131     return true;
132   }
133   if (Addr.getOpcode() == ISD::ADD) {
134     ConstantSDNode *CN = 0;
135     if ((Addr.getOperand(0).getOpcode() == XCoreISD::CPRelativeWrapper)
136       && (CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
137       && (CN->getSExtValue() % 4 == 0)) {
138       // Constant word offset from a object in the data region
139       Base = Addr.getOperand(0).getOperand(0);
140       Offset = CurDAG->getTargetConstant(CN->getSExtValue(), MVT::i32);
141       return true;
142     }
143   }
144   return false;
145 }
146
147 SDNode *XCoreDAGToDAGISel::Select(SDNode *N) {
148   DebugLoc dl = N->getDebugLoc();
149   EVT NVT = N->getValueType(0);
150   if (NVT == MVT::i32) {
151     switch (N->getOpcode()) {
152       default: break;
153       case ISD::Constant: {
154         if (Predicate_immMskBitp(N)) {
155           // Transformation function: get the size of a mask
156           int64_t MaskVal = cast<ConstantSDNode>(N)->getZExtValue();
157           assert(isMask_32(MaskVal));
158           // Look for the first non-zero bit
159           SDValue MskSize = getI32Imm(32 - CountLeadingZeros_32(MaskVal));
160           return CurDAG->getMachineNode(XCore::MKMSK_rus, dl,
161                                         MVT::i32, MskSize);
162         }
163         else if (! Predicate_immU16(N)) {
164           unsigned Val = cast<ConstantSDNode>(N)->getZExtValue();
165           SDValue CPIdx =
166             CurDAG->getTargetConstantPool(ConstantInt::get(
167                                   Type::getInt32Ty(*CurDAG->getContext()), Val),
168                                           TLI.getPointerTy());
169           return CurDAG->getMachineNode(XCore::LDWCP_lru6, dl, MVT::i32, 
170                                         MVT::Other, CPIdx, 
171                                         CurDAG->getEntryNode());
172         }
173         break;
174       }
175       case XCoreISD::LADD: {
176         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
177                             N->getOperand(2) };
178         return CurDAG->getMachineNode(XCore::LADD_l5r, dl, MVT::i32, MVT::i32,
179                                       Ops, 3);
180       }
181       case XCoreISD::LSUB: {
182         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
183                             N->getOperand(2) };
184         return CurDAG->getMachineNode(XCore::LSUB_l5r, dl, MVT::i32, MVT::i32,
185                                       Ops, 3);
186       }
187       case XCoreISD::MACCU: {
188         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
189                           N->getOperand(2), N->getOperand(3) };
190         return CurDAG->getMachineNode(XCore::MACCU_l4r, dl, MVT::i32, MVT::i32,
191                                       Ops, 4);
192       }
193       case XCoreISD::MACCS: {
194         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
195                           N->getOperand(2), N->getOperand(3) };
196         return CurDAG->getMachineNode(XCore::MACCS_l4r, dl, MVT::i32, MVT::i32,
197                                       Ops, 4);
198       }
199       case XCoreISD::LMUL: {
200         SDValue Ops[] = { N->getOperand(0), N->getOperand(1),
201                           N->getOperand(2), N->getOperand(3) };
202         return CurDAG->getMachineNode(XCore::LMUL_l6r, dl, MVT::i32, MVT::i32,
203                                       Ops, 4);
204       }
205       // Other cases are autogenerated.
206     }
207   }
208   return SelectCode(N);
209 }