Mercurial > hg > CbC > CbC_llvm
comparison lib/Target/Lanai/LanaiISelDAGToDAG.cpp @ 120:1172e4bd9c6f
update 4.0.0
author | mir3636 |
---|---|
date | Fri, 25 Nov 2016 19:14:25 +0900 |
parents | |
children | 803732b1fca8 |
comparison
equal
deleted
inserted
replaced
101:34baf5011add | 120:1172e4bd9c6f |
---|---|
1 //===-- LanaiISelDAGToDAG.cpp - A dag to dag inst selector for Lanai ------===// | |
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 Lanai target. | |
11 // | |
12 //===----------------------------------------------------------------------===// | |
13 | |
14 #include "Lanai.h" | |
15 #include "LanaiMachineFunctionInfo.h" | |
16 #include "LanaiRegisterInfo.h" | |
17 #include "LanaiSubtarget.h" | |
18 #include "LanaiTargetMachine.h" | |
19 #include "llvm/CodeGen/MachineConstantPool.h" | |
20 #include "llvm/CodeGen/MachineFrameInfo.h" | |
21 #include "llvm/CodeGen/MachineFunction.h" | |
22 #include "llvm/CodeGen/MachineInstrBuilder.h" | |
23 #include "llvm/CodeGen/MachineRegisterInfo.h" | |
24 #include "llvm/CodeGen/SelectionDAGISel.h" | |
25 #include "llvm/IR/CFG.h" | |
26 #include "llvm/IR/GlobalValue.h" | |
27 #include "llvm/IR/Instructions.h" | |
28 #include "llvm/IR/Intrinsics.h" | |
29 #include "llvm/IR/Type.h" | |
30 #include "llvm/Support/Debug.h" | |
31 #include "llvm/Support/ErrorHandling.h" | |
32 #include "llvm/Support/raw_ostream.h" | |
33 #include "llvm/Target/TargetMachine.h" | |
34 | |
35 using namespace llvm; | |
36 | |
37 #define DEBUG_TYPE "lanai-isel" | |
38 | |
39 //===----------------------------------------------------------------------===// | |
40 // Instruction Selector Implementation | |
41 //===----------------------------------------------------------------------===// | |
42 | |
43 //===----------------------------------------------------------------------===// | |
44 // LanaiDAGToDAGISel - Lanai specific code to select Lanai machine | |
45 // instructions for SelectionDAG operations. | |
46 //===----------------------------------------------------------------------===// | |
47 namespace { | |
48 | |
49 class LanaiDAGToDAGISel : public SelectionDAGISel { | |
50 public: | |
51 explicit LanaiDAGToDAGISel(LanaiTargetMachine &TargetMachine) | |
52 : SelectionDAGISel(TargetMachine) {} | |
53 | |
54 bool runOnMachineFunction(MachineFunction &MF) override { | |
55 return SelectionDAGISel::runOnMachineFunction(MF); | |
56 } | |
57 | |
58 // Pass Name | |
59 StringRef getPassName() const override { | |
60 return "Lanai DAG->DAG Pattern Instruction Selection"; | |
61 } | |
62 | |
63 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode, | |
64 std::vector<SDValue> &OutOps) override; | |
65 | |
66 private: | |
67 // Include the pieces autogenerated from the target description. | |
68 #include "LanaiGenDAGISel.inc" | |
69 | |
70 // Instruction Selection not handled by the auto-generated tablgen | |
71 void Select(SDNode *N) override; | |
72 | |
73 // Support functions for the opcodes of Instruction Selection | |
74 // not handled by the auto-generated tablgen | |
75 void selectFrameIndex(SDNode *N); | |
76 | |
77 // Complex Pattern for address selection. | |
78 bool selectAddrRi(SDValue Addr, SDValue &Base, SDValue &Offset, | |
79 SDValue &AluOp); | |
80 bool selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, SDValue &AluOp); | |
81 bool selectAddrSls(SDValue Addr, SDValue &Offset); | |
82 bool selectAddrSpls(SDValue Addr, SDValue &Base, SDValue &Offset, | |
83 SDValue &AluOp); | |
84 | |
85 // getI32Imm - Return a target constant with the specified value, of type i32. | |
86 inline SDValue getI32Imm(unsigned Imm, const SDLoc &DL) { | |
87 return CurDAG->getTargetConstant(Imm, DL, MVT::i32); | |
88 } | |
89 | |
90 private: | |
91 bool selectAddrRiSpls(SDValue Addr, SDValue &Base, SDValue &Offset, | |
92 SDValue &AluOp, bool RiMode); | |
93 }; | |
94 | |
95 bool canBeRepresentedAsSls(const ConstantSDNode &CN) { | |
96 // Fits in 21-bit signed immediate and two low-order bits are zero. | |
97 return isInt<21>(CN.getSExtValue()) && ((CN.getSExtValue() & 0x3) == 0); | |
98 } | |
99 | |
100 } // namespace | |
101 | |
102 // Helper functions for ComplexPattern used on LanaiInstrInfo | |
103 // Used on Lanai Load/Store instructions. | |
104 bool LanaiDAGToDAGISel::selectAddrSls(SDValue Addr, SDValue &Offset) { | |
105 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { | |
106 SDLoc DL(Addr); | |
107 // Loading from a constant address. | |
108 if (canBeRepresentedAsSls(*CN)) { | |
109 int32_t Imm = CN->getSExtValue(); | |
110 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); | |
111 return true; | |
112 } | |
113 } | |
114 if (Addr.getOpcode() == ISD::OR && | |
115 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) { | |
116 Offset = Addr.getOperand(1).getOperand(0); | |
117 return true; | |
118 } | |
119 return false; | |
120 } | |
121 | |
122 bool LanaiDAGToDAGISel::selectAddrRiSpls(SDValue Addr, SDValue &Base, | |
123 SDValue &Offset, SDValue &AluOp, | |
124 bool RiMode) { | |
125 SDLoc DL(Addr); | |
126 | |
127 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr)) { | |
128 if (RiMode) { | |
129 // Fits in 16-bit signed immediate. | |
130 if (isInt<16>(CN->getSExtValue())) { | |
131 int16_t Imm = CN->getSExtValue(); | |
132 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); | |
133 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); | |
134 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); | |
135 return true; | |
136 } | |
137 // Allow SLS to match if the constant doesn't fit in 16 bits but can be | |
138 // represented as an SLS. | |
139 if (canBeRepresentedAsSls(*CN)) | |
140 return false; | |
141 } else { | |
142 // Fits in 10-bit signed immediate. | |
143 if (isInt<10>(CN->getSExtValue())) { | |
144 int16_t Imm = CN->getSExtValue(); | |
145 Offset = CurDAG->getTargetConstant(Imm, DL, CN->getValueType(0)); | |
146 Base = CurDAG->getRegister(Lanai::R0, CN->getValueType(0)); | |
147 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); | |
148 return true; | |
149 } | |
150 } | |
151 } | |
152 | |
153 // if Address is FI, get the TargetFrameIndex. | |
154 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { | |
155 Base = CurDAG->getTargetFrameIndex( | |
156 FIN->getIndex(), | |
157 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); | |
158 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); | |
159 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); | |
160 return true; | |
161 } | |
162 | |
163 // Skip direct calls | |
164 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || | |
165 Addr.getOpcode() == ISD::TargetGlobalAddress)) | |
166 return false; | |
167 | |
168 // Address of the form imm + reg | |
169 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); | |
170 if (AluOperator == ISD::ADD) { | |
171 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); | |
172 // Addresses of the form FI+const | |
173 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) | |
174 if ((RiMode && isInt<16>(CN->getSExtValue())) || | |
175 (!RiMode && isInt<10>(CN->getSExtValue()))) { | |
176 // If the first operand is a FI, get the TargetFI Node | |
177 if (FrameIndexSDNode *FIN = | |
178 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { | |
179 Base = CurDAG->getTargetFrameIndex( | |
180 FIN->getIndex(), | |
181 getTargetLowering()->getPointerTy(CurDAG->getDataLayout())); | |
182 } else { | |
183 Base = Addr.getOperand(0); | |
184 } | |
185 | |
186 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i32); | |
187 return true; | |
188 } | |
189 } | |
190 | |
191 // Let SLS match SMALL instead of RI. | |
192 if (AluOperator == ISD::OR && RiMode && | |
193 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) | |
194 return false; | |
195 | |
196 Base = Addr; | |
197 Offset = CurDAG->getTargetConstant(0, DL, MVT::i32); | |
198 AluOp = CurDAG->getTargetConstant(LPAC::ADD, DL, MVT::i32); | |
199 return true; | |
200 } | |
201 | |
202 bool LanaiDAGToDAGISel::selectAddrRi(SDValue Addr, SDValue &Base, | |
203 SDValue &Offset, SDValue &AluOp) { | |
204 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/true); | |
205 } | |
206 | |
207 bool LanaiDAGToDAGISel::selectAddrSpls(SDValue Addr, SDValue &Base, | |
208 SDValue &Offset, SDValue &AluOp) { | |
209 return selectAddrRiSpls(Addr, Base, Offset, AluOp, /*RiMode=*/false); | |
210 } | |
211 | |
212 bool LanaiDAGToDAGISel::selectAddrRr(SDValue Addr, SDValue &R1, SDValue &R2, | |
213 SDValue &AluOp) { | |
214 // if Address is FI, get the TargetFrameIndex. | |
215 if (Addr.getOpcode() == ISD::FrameIndex) | |
216 return false; | |
217 | |
218 // Skip direct calls | |
219 if ((Addr.getOpcode() == ISD::TargetExternalSymbol || | |
220 Addr.getOpcode() == ISD::TargetGlobalAddress)) | |
221 return false; | |
222 | |
223 // Address of the form OP + OP | |
224 ISD::NodeType AluOperator = static_cast<ISD::NodeType>(Addr.getOpcode()); | |
225 LPAC::AluCode AluCode = LPAC::isdToLanaiAluCode(AluOperator); | |
226 if (AluCode != LPAC::UNKNOWN) { | |
227 // Skip addresses of the form FI OP const | |
228 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) | |
229 if (isInt<16>(CN->getSExtValue())) | |
230 return false; | |
231 | |
232 // Skip addresses with hi/lo operands | |
233 if (Addr.getOperand(0).getOpcode() == LanaiISD::HI || | |
234 Addr.getOperand(0).getOpcode() == LanaiISD::LO || | |
235 Addr.getOperand(0).getOpcode() == LanaiISD::SMALL || | |
236 Addr.getOperand(1).getOpcode() == LanaiISD::HI || | |
237 Addr.getOperand(1).getOpcode() == LanaiISD::LO || | |
238 Addr.getOperand(1).getOpcode() == LanaiISD::SMALL) | |
239 return false; | |
240 | |
241 // Addresses of the form register OP register | |
242 R1 = Addr.getOperand(0); | |
243 R2 = Addr.getOperand(1); | |
244 AluOp = CurDAG->getTargetConstant(AluCode, SDLoc(Addr), MVT::i32); | |
245 return true; | |
246 } | |
247 | |
248 // Skip addresses with zero offset | |
249 return false; | |
250 } | |
251 | |
252 bool LanaiDAGToDAGISel::SelectInlineAsmMemoryOperand( | |
253 const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) { | |
254 SDValue Op0, Op1, AluOp; | |
255 switch (ConstraintCode) { | |
256 default: | |
257 return true; | |
258 case InlineAsm::Constraint_m: // memory | |
259 if (!selectAddrRr(Op, Op0, Op1, AluOp) && | |
260 !selectAddrRi(Op, Op0, Op1, AluOp)) | |
261 return true; | |
262 break; | |
263 } | |
264 | |
265 OutOps.push_back(Op0); | |
266 OutOps.push_back(Op1); | |
267 OutOps.push_back(AluOp); | |
268 return false; | |
269 } | |
270 | |
271 // Select instructions not customized! Used for | |
272 // expanded, promoted and normal instructions | |
273 void LanaiDAGToDAGISel::Select(SDNode *Node) { | |
274 unsigned Opcode = Node->getOpcode(); | |
275 | |
276 // Dump information about the Node being selected | |
277 DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); | |
278 | |
279 // If we have a custom node, we already have selected! | |
280 if (Node->isMachineOpcode()) { | |
281 DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); | |
282 return; | |
283 } | |
284 | |
285 // Instruction Selection not handled by the auto-generated | |
286 // tablegen selection should be handled here. | |
287 switch (Opcode) { | |
288 case ISD::FrameIndex: | |
289 selectFrameIndex(Node); | |
290 return; | |
291 default: | |
292 break; | |
293 } | |
294 | |
295 // Select the default instruction | |
296 SelectCode(Node); | |
297 } | |
298 | |
299 void LanaiDAGToDAGISel::selectFrameIndex(SDNode *Node) { | |
300 SDLoc DL(Node); | |
301 SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i32); | |
302 int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex(); | |
303 EVT VT = Node->getValueType(0); | |
304 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); | |
305 unsigned Opc = Lanai::ADD_I_LO; | |
306 if (Node->hasOneUse()) { | |
307 CurDAG->SelectNodeTo(Node, Opc, VT, TFI, Imm); | |
308 return; | |
309 } | |
310 ReplaceNode(Node, CurDAG->getMachineNode(Opc, DL, VT, TFI, Imm)); | |
311 } | |
312 | |
313 // createLanaiISelDag - This pass converts a legalized DAG into a | |
314 // Lanai-specific DAG, ready for instruction scheduling. | |
315 FunctionPass *llvm::createLanaiISelDag(LanaiTargetMachine &TM) { | |
316 return new LanaiDAGToDAGISel(TM); | |
317 } |