1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | #define DEBUG_TYPE"hexagon-isel" "hexagon-isel" |
15 | #include "Hexagon.h" |
16 | #include "HexagonISelLowering.h" |
17 | #include "HexagonTargetMachine.h" |
18 | #include "llvm/ADT/DenseMap.h" |
19 | #include "llvm/IR/Intrinsics.h" |
20 | #include "llvm/CodeGen/SelectionDAGISel.h" |
21 | #include "llvm/Support/CommandLine.h" |
22 | #include "llvm/Support/Compiler.h" |
23 | #include "llvm/Support/Debug.h" |
24 | using namespace llvm; |
25 | |
26 | static |
27 | cl::opt<unsigned> |
28 | MaxNumOfUsesForConstExtenders("ga-max-num-uses-for-constant-extenders", |
29 | cl::Hidden, cl::init(2), |
30 | cl::desc("Maximum number of uses of a global address such that we still us a" |
31 | "constant extended instruction")); |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | namespace llvm { |
38 | void initializeHexagonDAGToDAGISelPass(PassRegistry&); |
39 | } |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | namespace { |
46 | class HexagonDAGToDAGISel : public SelectionDAGISel { |
47 | |
48 | |
49 | const HexagonSubtarget &Subtarget; |
50 | |
51 | |
52 | HexagonTargetMachine& TM; |
53 | const HexagonInstrInfo *TII; |
54 | DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap; |
55 | public: |
56 | explicit HexagonDAGToDAGISel(HexagonTargetMachine &targetmachine, |
57 | CodeGenOpt::Level OptLevel) |
58 | : SelectionDAGISel(targetmachine, OptLevel), |
59 | Subtarget(targetmachine.getSubtarget<HexagonSubtarget>()), |
60 | TM(targetmachine), |
61 | TII(static_cast<const HexagonInstrInfo*>(TM.getInstrInfo())) { |
62 | initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry()); |
63 | } |
64 | bool hasNumUsesBelowThresGA(SDNode *N) const; |
65 | |
66 | SDNode *Select(SDNode *N); |
67 | |
68 | |
69 | inline bool foldGlobalAddress(SDValue &N, SDValue &R); |
70 | inline bool foldGlobalAddressGP(SDValue &N, SDValue &R); |
71 | bool foldGlobalAddressImpl(SDValue &N, SDValue &R, bool ShouldLookForGP); |
72 | bool SelectADDRri(SDValue& N, SDValue &R1, SDValue &R2); |
73 | bool SelectADDRriS11_0(SDValue& N, SDValue &R1, SDValue &R2); |
74 | bool SelectADDRriS11_1(SDValue& N, SDValue &R1, SDValue &R2); |
75 | bool SelectADDRriS11_2(SDValue& N, SDValue &R1, SDValue &R2); |
76 | bool SelectMEMriS11_2(SDValue& Addr, SDValue &Base, SDValue &Offset); |
77 | bool SelectADDRriS11_3(SDValue& N, SDValue &R1, SDValue &R2); |
78 | bool SelectADDRrr(SDValue &Addr, SDValue &Base, SDValue &Offset); |
79 | bool SelectADDRriU6_0(SDValue& N, SDValue &R1, SDValue &R2); |
80 | bool SelectADDRriU6_1(SDValue& N, SDValue &R1, SDValue &R2); |
81 | bool SelectADDRriU6_2(SDValue& N, SDValue &R1, SDValue &R2); |
82 | |
83 | virtual const char *getPassName() const { |
84 | return "Hexagon DAG->DAG Pattern Instruction Selection"; |
85 | } |
86 | |
87 | |
88 | |
89 | virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, |
90 | char ConstraintCode, |
91 | std::vector<SDValue> &OutOps); |
92 | bool SelectAddr(SDNode *Op, SDValue Addr, SDValue &Base, SDValue &Offset); |
93 | |
94 | SDNode *SelectLoad(SDNode *N); |
95 | SDNode *SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl); |
96 | SDNode *SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl); |
97 | SDNode *SelectIndexedLoadZeroExtend64(LoadSDNode *LD, unsigned Opcode, |
98 | DebugLoc dl); |
99 | SDNode *SelectIndexedLoadSignExtend64(LoadSDNode *LD, unsigned Opcode, |
100 | DebugLoc dl); |
101 | SDNode *SelectBaseOffsetStore(StoreSDNode *ST, DebugLoc dl); |
102 | SDNode *SelectIndexedStore(StoreSDNode *ST, DebugLoc dl); |
103 | SDNode *SelectStore(SDNode *N); |
104 | SDNode *SelectSHL(SDNode *N); |
105 | SDNode *SelectSelect(SDNode *N); |
106 | SDNode *SelectTruncate(SDNode *N); |
107 | SDNode *SelectMul(SDNode *N); |
108 | SDNode *SelectZeroExtend(SDNode *N); |
109 | SDNode *SelectIntrinsicWOChain(SDNode *N); |
110 | SDNode *SelectIntrinsicWChain(SDNode *N); |
111 | SDNode *SelectConstant(SDNode *N); |
112 | SDNode *SelectConstantFP(SDNode *N); |
113 | SDNode *SelectAdd(SDNode *N); |
114 | bool isConstExtProfitable(SDNode *N) const; |
115 | |
116 | |
117 | |
118 | inline SDValue XformU7ToU7M1Imm(signed Imm) { |
119 | assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op")((void)0); |
120 | return CurDAG->getTargetConstant(Imm - 1, MVT::i8); |
121 | } |
122 | |
123 | |
124 | #include "HexagonGenDAGISel.inc" |
125 | }; |
126 | } |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM, |
133 | CodeGenOpt::Level OptLevel) { |
134 | return new HexagonDAGToDAGISel(TM, OptLevel); |
135 | } |
136 | |
137 | static void initializePassOnce(PassRegistry &Registry) { |
138 | const char *Name = "Hexagon DAG->DAG Pattern Instruction Selection"; |
139 | PassInfo *PI = new PassInfo(Name, "hexagon-isel", |
| |
140 | &SelectionDAGISel::ID, 0, false, false); |
141 | Registry.registerPass(*PI, true); |
142 | } |
| 3 | | Memory is never released; potential leak of memory pointed to by 'PI' |
|
143 | |
144 | void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) { |
145 | CALL_ONCE_INITIALIZATION(initializePassOnce)static volatile sys::cas_flag initialized = 0; sys::cas_flag old_val = sys::CompareAndSwap(&initialized, 1, 0); if (old_val == 0) { initializePassOnce(Registry); sys::MemoryFence(); ; ; initialized = 2; ; } else { sys::cas_flag tmp = initialized; sys::MemoryFence (); while (tmp != 2) { tmp = initialized; sys::MemoryFence(); } } ; |
| 1 | Within the expansion of the macro 'CALL_ONCE_INITIALIZATION':
| |
a | Assuming 'old_val' is equal to 0 |
b | Calling 'initializePassOnce' |
|
146 | } |
147 | |
148 | |
149 | static bool IsS11_0_Offset(SDNode * S) { |
150 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
151 | |
152 | |
153 | |
154 | int64_t v = (int64_t)N->getSExtValue(); |
155 | return isInt<11>(v); |
156 | } |
157 | |
158 | |
159 | static bool IsS11_1_Offset(SDNode * S) { |
160 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
161 | |
162 | |
163 | |
164 | int64_t v = (int64_t)N->getSExtValue(); |
165 | return isShiftedInt<11,1>(v); |
166 | } |
167 | |
168 | |
169 | static bool IsS11_2_Offset(SDNode * S) { |
170 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
171 | |
172 | |
173 | |
174 | int64_t v = (int64_t)N->getSExtValue(); |
175 | return isShiftedInt<11,2>(v); |
176 | } |
177 | |
178 | |
179 | static bool IsS11_3_Offset(SDNode * S) { |
180 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
181 | |
182 | |
183 | |
184 | int64_t v = (int64_t)N->getSExtValue(); |
185 | return isShiftedInt<11,3>(v); |
186 | } |
187 | |
188 | |
189 | static bool IsU6_0_Offset(SDNode * S) { |
190 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
191 | |
192 | |
193 | |
194 | int64_t v = (int64_t)N->getSExtValue(); |
195 | return isUInt<6>(v); |
196 | } |
197 | |
198 | |
199 | static bool IsU6_1_Offset(SDNode * S) { |
200 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
201 | |
202 | |
203 | |
204 | int64_t v = (int64_t)N->getSExtValue(); |
205 | return isShiftedUInt<6,1>(v); |
206 | } |
207 | |
208 | |
209 | static bool IsU6_2_Offset(SDNode * S) { |
210 | ConstantSDNode *N = cast<ConstantSDNode>(S); |
211 | |
212 | |
213 | |
214 | int64_t v = (int64_t)N->getSExtValue(); |
215 | return isShiftedUInt<6,2>(v); |
216 | } |
217 | |
218 | |
219 | |
220 | static unsigned doesIntrinsicReturnPredicate(unsigned ID) |
221 | { |
222 | switch (ID) { |
223 | default: |
224 | return 0; |
225 | case Intrinsic::hexagon_C2_cmpeq: |
226 | case Intrinsic::hexagon_C2_cmpgt: |
227 | case Intrinsic::hexagon_C2_cmpgtu: |
228 | case Intrinsic::hexagon_C2_cmpgtup: |
229 | case Intrinsic::hexagon_C2_cmpgtp: |
230 | case Intrinsic::hexagon_C2_cmpeqp: |
231 | case Intrinsic::hexagon_C2_bitsset: |
232 | case Intrinsic::hexagon_C2_bitsclr: |
233 | case Intrinsic::hexagon_C2_cmpeqi: |
234 | case Intrinsic::hexagon_C2_cmpgti: |
235 | case Intrinsic::hexagon_C2_cmpgtui: |
236 | case Intrinsic::hexagon_C2_cmpgei: |
237 | case Intrinsic::hexagon_C2_cmpgeui: |
238 | case Intrinsic::hexagon_C2_cmplt: |
239 | case Intrinsic::hexagon_C2_cmpltu: |
240 | case Intrinsic::hexagon_C2_bitsclri: |
241 | case Intrinsic::hexagon_C2_and: |
242 | case Intrinsic::hexagon_C2_or: |
243 | case Intrinsic::hexagon_C2_xor: |
244 | case Intrinsic::hexagon_C2_andn: |
245 | case Intrinsic::hexagon_C2_not: |
246 | case Intrinsic::hexagon_C2_orn: |
247 | case Intrinsic::hexagon_C2_pxfer_map: |
248 | case Intrinsic::hexagon_C2_any8: |
249 | case Intrinsic::hexagon_C2_all8: |
250 | case Intrinsic::hexagon_A2_vcmpbeq: |
251 | case Intrinsic::hexagon_A2_vcmpbgtu: |
252 | case Intrinsic::hexagon_A2_vcmpheq: |
253 | case Intrinsic::hexagon_A2_vcmphgt: |
254 | case Intrinsic::hexagon_A2_vcmphgtu: |
255 | case Intrinsic::hexagon_A2_vcmpweq: |
256 | case Intrinsic::hexagon_A2_vcmpwgt: |
257 | case Intrinsic::hexagon_A2_vcmpwgtu: |
258 | case Intrinsic::hexagon_C2_tfrrp: |
259 | case Intrinsic::hexagon_S2_tstbit_i: |
260 | case Intrinsic::hexagon_S2_tstbit_r: |
261 | return 1; |
262 | } |
263 | } |
264 | |
265 | |
266 | |
267 | static unsigned doesIntrinsicContainPredicate(unsigned ID) |
268 | { |
269 | switch (ID) { |
270 | default: |
271 | return 0; |
272 | case Intrinsic::hexagon_C2_tfrpr: |
273 | return Hexagon::TFR_RsPd; |
274 | case Intrinsic::hexagon_C2_and: |
275 | return Hexagon::AND_pp; |
276 | case Intrinsic::hexagon_C2_xor: |
277 | return Hexagon::XOR_pp; |
278 | case Intrinsic::hexagon_C2_or: |
279 | return Hexagon::OR_pp; |
280 | case Intrinsic::hexagon_C2_not: |
281 | return Hexagon::NOT_p; |
282 | case Intrinsic::hexagon_C2_any8: |
283 | return Hexagon::ANY_pp; |
284 | case Intrinsic::hexagon_C2_all8: |
285 | return Hexagon::ALL_pp; |
286 | case Intrinsic::hexagon_C2_vitpack: |
287 | return Hexagon::VITPACK_pp; |
288 | case Intrinsic::hexagon_C2_mask: |
289 | return Hexagon::MASK_p; |
290 | case Intrinsic::hexagon_C2_mux: |
291 | return Hexagon::MUX_rr; |
292 | |
293 | |
294 | |
295 | case Intrinsic::hexagon_C2_muxir: |
296 | return Hexagon::MUX_ri; |
297 | |
298 | |
299 | |
300 | case Intrinsic::hexagon_C2_muxri: |
301 | return Hexagon::MUX_ir; |
302 | |
303 | case Intrinsic::hexagon_C2_muxii: |
304 | return Hexagon::MUX_ii; |
305 | case Intrinsic::hexagon_C2_vmux: |
306 | return Hexagon::VMUX_prr64; |
307 | case Intrinsic::hexagon_S2_valignrb: |
308 | return Hexagon::VALIGN_rrp; |
309 | case Intrinsic::hexagon_S2_vsplicerb: |
310 | return Hexagon::VSPLICE_rrp; |
311 | } |
312 | } |
313 | |
314 | |
315 | static bool OffsetFitsS11(EVT MemType, int64_t Offset) { |
316 | if (MemType == MVT::i64 && isShiftedInt<11,3>(Offset)) { |
317 | return true; |
318 | } |
319 | if (MemType == MVT::i32 && isShiftedInt<11,2>(Offset)) { |
320 | return true; |
321 | } |
322 | if (MemType == MVT::i16 && isShiftedInt<11,1>(Offset)) { |
323 | return true; |
324 | } |
325 | if (MemType == MVT::i8 && isInt<11>(Offset)) { |
326 | return true; |
327 | } |
328 | return false; |
329 | } |
330 | |
331 | |
332 | |
333 | |
334 | |
335 | |
336 | |
337 | SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) { |
338 | SDValue Chain = LD->getChain(); |
339 | SDNode* Const32 = LD->getBasePtr().getNode(); |
340 | unsigned Opcode = 0; |
341 | |
342 | if (Const32->getOpcode() == HexagonISD::CONST32 && |
343 | ISD::isNormalLoad(LD)) { |
344 | SDValue Base = Const32->getOperand(0); |
345 | EVT LoadedVT = LD->getMemoryVT(); |
346 | int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); |
347 | if (Offset != 0 && OffsetFitsS11(LoadedVT, Offset)) { |
348 | MVT PointerTy = TLI.getPointerTy(); |
349 | const GlobalValue* GV = |
350 | cast<GlobalAddressSDNode>(Base)->getGlobal(); |
351 | SDValue TargAddr = |
352 | CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); |
353 | SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, |
354 | dl, PointerTy, |
355 | TargAddr); |
356 | |
357 | if (LoadedVT == MVT::i64) Opcode = Hexagon::LDrid_indexed; |
358 | else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed; |
359 | else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed; |
360 | else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed; |
361 | else llvm_unreachable("unknown memory type")__builtin_unreachable(); |
362 | |
363 | |
364 | SDValue TargetConstOff = CurDAG->getTargetConstant(Offset, PointerTy); |
365 | SDNode* Result = CurDAG->getMachineNode(Opcode, dl, |
366 | LD->getValueType(0), |
367 | MVT::Other, |
368 | SDValue(NewBase,0), |
369 | TargetConstOff, |
370 | Chain); |
371 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
372 | MemOp[0] = LD->getMemOperand(); |
373 | cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); |
374 | ReplaceUses(LD, Result); |
375 | return Result; |
376 | } |
377 | } |
378 | |
379 | return SelectCode(LD); |
380 | } |
381 | |
382 | |
383 | SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD, |
384 | unsigned Opcode, |
385 | DebugLoc dl) |
386 | { |
387 | SDValue Chain = LD->getChain(); |
388 | EVT LoadedVT = LD->getMemoryVT(); |
389 | SDValue Base = LD->getBasePtr(); |
390 | SDValue Offset = LD->getOffset(); |
391 | SDNode *OffsetNode = Offset.getNode(); |
392 | int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); |
393 | SDValue N1 = LD->getOperand(1); |
394 | SDValue CPTmpN1_0; |
395 | SDValue CPTmpN1_1; |
396 | if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && |
397 | N1.getNode()->getValueType(0) == MVT::i32) { |
398 | if (TII->isValidAutoIncImm(LoadedVT, Val)) { |
399 | SDValue TargetConst = CurDAG->getTargetConstant(Val, MVT::i32); |
400 | SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32, |
401 | MVT::Other, Base, TargetConst, |
402 | Chain); |
403 | SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, MVT::i64, |
404 | SDValue(Result_1, 0)); |
405 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
406 | MemOp[0] = LD->getMemOperand(); |
407 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
408 | const SDValue Froms[] = { SDValue(LD, 0), |
409 | SDValue(LD, 1), |
410 | SDValue(LD, 2) |
411 | }; |
412 | const SDValue Tos[] = { SDValue(Result_2, 0), |
413 | SDValue(Result_1, 1), |
414 | SDValue(Result_1, 2) |
415 | }; |
416 | ReplaceUses(Froms, Tos, 3); |
417 | return Result_2; |
418 | } |
419 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
420 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
421 | SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, |
422 | MVT::Other, Base, TargetConst0, |
423 | Chain); |
424 | SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::SXTW, dl, |
425 | MVT::i64, SDValue(Result_1, 0)); |
426 | SDNode* Result_3 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, |
427 | MVT::i32, Base, TargetConstVal, |
428 | SDValue(Result_1, 1)); |
429 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
430 | MemOp[0] = LD->getMemOperand(); |
431 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
432 | const SDValue Froms[] = { SDValue(LD, 0), |
433 | SDValue(LD, 1), |
434 | SDValue(LD, 2) |
435 | }; |
436 | const SDValue Tos[] = { SDValue(Result_2, 0), |
437 | SDValue(Result_3, 0), |
438 | SDValue(Result_1, 1) |
439 | }; |
440 | ReplaceUses(Froms, Tos, 3); |
441 | return Result_2; |
442 | } |
443 | return SelectCode(LD); |
444 | } |
445 | |
446 | |
447 | SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD, |
448 | unsigned Opcode, |
449 | DebugLoc dl) |
450 | { |
451 | SDValue Chain = LD->getChain(); |
452 | EVT LoadedVT = LD->getMemoryVT(); |
453 | SDValue Base = LD->getBasePtr(); |
454 | SDValue Offset = LD->getOffset(); |
455 | SDNode *OffsetNode = Offset.getNode(); |
456 | int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); |
457 | SDValue N1 = LD->getOperand(1); |
458 | SDValue CPTmpN1_0; |
459 | SDValue CPTmpN1_1; |
460 | if (SelectADDRriS11_2(N1, CPTmpN1_0, CPTmpN1_1) && |
461 | N1.getNode()->getValueType(0) == MVT::i32) { |
462 | if (TII->isValidAutoIncImm(LoadedVT, Val)) { |
463 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
464 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
465 | SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, |
466 | MVT::i32, MVT::Other, Base, |
467 | TargetConstVal, Chain); |
468 | SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, |
469 | TargetConst0); |
470 | SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, |
471 | MVT::i64, MVT::Other, |
472 | SDValue(Result_2,0), |
473 | SDValue(Result_1,0)); |
474 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
475 | MemOp[0] = LD->getMemOperand(); |
476 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
477 | const SDValue Froms[] = { SDValue(LD, 0), |
478 | SDValue(LD, 1), |
479 | SDValue(LD, 2) |
480 | }; |
481 | const SDValue Tos[] = { SDValue(Result_3, 0), |
482 | SDValue(Result_1, 1), |
483 | SDValue(Result_1, 2) |
484 | }; |
485 | ReplaceUses(Froms, Tos, 3); |
486 | return Result_3; |
487 | } |
488 | |
489 | |
490 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
491 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
492 | SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, |
493 | MVT::Other, |
494 | Base, TargetConst0, Chain); |
495 | SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, |
496 | TargetConst0); |
497 | SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, |
498 | MVT::i64, MVT::Other, |
499 | SDValue(Result_2,0), |
500 | SDValue(Result_1,0)); |
501 | |
502 | SDNode* Result_4 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, |
503 | Base, TargetConstVal, |
504 | SDValue(Result_1, 1)); |
505 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
506 | MemOp[0] = LD->getMemOperand(); |
507 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
508 | const SDValue Froms[] = { SDValue(LD, 0), |
509 | SDValue(LD, 1), |
510 | SDValue(LD, 2) |
511 | }; |
512 | const SDValue Tos[] = { SDValue(Result_3, 0), |
513 | SDValue(Result_4, 0), |
514 | SDValue(Result_1, 1) |
515 | }; |
516 | ReplaceUses(Froms, Tos, 3); |
517 | return Result_3; |
518 | } |
519 | |
520 | return SelectCode(LD); |
521 | } |
522 | |
523 | |
524 | SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, DebugLoc dl) { |
525 | SDValue Chain = LD->getChain(); |
526 | SDValue Base = LD->getBasePtr(); |
527 | SDValue Offset = LD->getOffset(); |
528 | SDNode *OffsetNode = Offset.getNode(); |
529 | |
530 | int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); |
531 | EVT LoadedVT = LD->getMemoryVT(); |
532 | unsigned Opcode = 0; |
533 | |
534 | |
535 | bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD); |
536 | |
537 | |
538 | if (LoadedVT == MVT::i64) { |
539 | if (TII->isValidAutoIncImm(LoadedVT, Val)) |
540 | Opcode = Hexagon::POST_LDrid; |
541 | else |
542 | Opcode = Hexagon::LDrid; |
543 | } else if (LoadedVT == MVT::i32) { |
544 | if (TII->isValidAutoIncImm(LoadedVT, Val)) |
545 | Opcode = Hexagon::POST_LDriw; |
546 | else |
547 | Opcode = Hexagon::LDriw; |
548 | } else if (LoadedVT == MVT::i16) { |
549 | if (TII->isValidAutoIncImm(LoadedVT, Val)) |
550 | Opcode = zextval ? Hexagon::POST_LDriuh : Hexagon::POST_LDrih; |
551 | else |
552 | Opcode = zextval ? Hexagon::LDriuh : Hexagon::LDrih; |
553 | } else if (LoadedVT == MVT::i8) { |
554 | if (TII->isValidAutoIncImm(LoadedVT, Val)) |
555 | Opcode = zextval ? Hexagon::POST_LDriub : Hexagon::POST_LDrib; |
556 | else |
557 | Opcode = zextval ? Hexagon::LDriub : Hexagon::LDrib; |
558 | } else |
559 | llvm_unreachable("unknown memory type")__builtin_unreachable(); |
560 | |
561 | |
562 | if (LD->getValueType(0) == MVT::i64 && |
563 | LD->getExtensionType() == ISD::ZEXTLOAD) { |
564 | return SelectIndexedLoadZeroExtend64(LD, Opcode, dl); |
565 | } |
566 | if (LD->getValueType(0) == MVT::i64 && |
567 | LD->getExtensionType() == ISD::SEXTLOAD) { |
568 | |
569 | return SelectIndexedLoadSignExtend64(LD, Opcode, dl); |
570 | } |
571 | if (TII->isValidAutoIncImm(LoadedVT, Val)) { |
572 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
573 | SDNode* Result = CurDAG->getMachineNode(Opcode, dl, |
574 | LD->getValueType(0), |
575 | MVT::i32, MVT::Other, Base, |
576 | TargetConstVal, Chain); |
577 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
578 | MemOp[0] = LD->getMemOperand(); |
579 | cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); |
580 | const SDValue Froms[] = { SDValue(LD, 0), |
581 | SDValue(LD, 1), |
582 | SDValue(LD, 2) |
583 | }; |
584 | const SDValue Tos[] = { SDValue(Result, 0), |
585 | SDValue(Result, 1), |
586 | SDValue(Result, 2) |
587 | }; |
588 | ReplaceUses(Froms, Tos, 3); |
589 | return Result; |
590 | } else { |
591 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
592 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
593 | SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, |
594 | LD->getValueType(0), |
595 | MVT::Other, Base, TargetConst0, |
596 | Chain); |
597 | SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, |
598 | Base, TargetConstVal, |
599 | SDValue(Result_1, 1)); |
600 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
601 | MemOp[0] = LD->getMemOperand(); |
602 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
603 | const SDValue Froms[] = { SDValue(LD, 0), |
604 | SDValue(LD, 1), |
605 | SDValue(LD, 2) |
606 | }; |
607 | const SDValue Tos[] = { SDValue(Result_1, 0), |
608 | SDValue(Result_2, 0), |
609 | SDValue(Result_1, 1) |
610 | }; |
611 | ReplaceUses(Froms, Tos, 3); |
612 | return Result_1; |
613 | } |
614 | } |
615 | |
616 | |
617 | SDNode *HexagonDAGToDAGISel::SelectLoad(SDNode *N) { |
618 | SDNode *result; |
619 | DebugLoc dl = N->getDebugLoc(); |
620 | LoadSDNode *LD = cast<LoadSDNode>(N); |
621 | ISD::MemIndexedMode AM = LD->getAddressingMode(); |
622 | |
623 | |
624 | if (AM != ISD::UNINDEXED) { |
625 | result = SelectIndexedLoad(LD, dl); |
626 | } else { |
627 | result = SelectBaseOffsetLoad(LD, dl); |
628 | } |
629 | |
630 | return result; |
631 | } |
632 | |
633 | |
634 | SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) { |
635 | SDValue Chain = ST->getChain(); |
636 | SDValue Base = ST->getBasePtr(); |
637 | SDValue Offset = ST->getOffset(); |
638 | SDValue Value = ST->getValue(); |
639 | SDNode *OffsetNode = Offset.getNode(); |
640 | |
641 | int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue(); |
642 | EVT StoredVT = ST->getMemoryVT(); |
643 | |
644 | |
645 | |
646 | if (TII->isValidAutoIncImm(StoredVT, Val)) { |
647 | SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value, |
648 | Chain}; |
649 | unsigned Opcode = 0; |
650 | |
651 | |
652 | if (StoredVT == MVT::i64) Opcode = Hexagon::POST_STdri; |
653 | else if (StoredVT == MVT::i32) Opcode = Hexagon::POST_STwri; |
654 | else if (StoredVT == MVT::i16) Opcode = Hexagon::POST_SThri; |
655 | else if (StoredVT == MVT::i8) Opcode = Hexagon::POST_STbri; |
656 | else llvm_unreachable("unknown memory type")__builtin_unreachable(); |
657 | |
658 | |
659 | SDNode* Result = CurDAG->getMachineNode(Opcode, dl, MVT::i32, |
660 | MVT::Other, Ops, 4); |
661 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
662 | MemOp[0] = ST->getMemOperand(); |
663 | cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); |
664 | |
665 | ReplaceUses(ST, Result); |
666 | ReplaceUses(SDValue(ST,1), SDValue(Result,1)); |
667 | return Result; |
668 | } |
669 | |
670 | |
671 | |
672 | |
673 | SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value, |
674 | Chain}; |
675 | unsigned Opcode = 0; |
676 | |
677 | |
678 | if (StoredVT == MVT::i64) Opcode = Hexagon::STrid; |
679 | else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; |
680 | else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih; |
681 | else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib; |
682 | else llvm_unreachable("unknown memory type")__builtin_unreachable(); |
683 | |
684 | |
685 | SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32); |
686 | SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops, |
687 | 4); |
688 | |
689 | SDNode* Result_2 = CurDAG->getMachineNode(Hexagon::ADD_ri, dl, MVT::i32, |
690 | Base, |
691 | TargetConstVal, |
692 | SDValue(Result_1, 0)); |
693 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
694 | MemOp[0] = ST->getMemOperand(); |
695 | cast<MachineSDNode>(Result_1)->setMemRefs(MemOp, MemOp + 1); |
696 | |
697 | ReplaceUses(SDValue(ST,0), SDValue(Result_2,0)); |
698 | ReplaceUses(SDValue(ST,1), SDValue(Result_1,0)); |
699 | return Result_2; |
700 | } |
701 | |
702 | |
703 | SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST, |
704 | DebugLoc dl) { |
705 | SDValue Chain = ST->getChain(); |
706 | SDNode* Const32 = ST->getBasePtr().getNode(); |
707 | SDValue Value = ST->getValue(); |
708 | unsigned Opcode = 0; |
709 | |
710 | |
711 | |
712 | |
713 | |
714 | |
715 | if ((Const32->getOpcode() == HexagonISD::CONST32) && |
716 | !(Value.getValueType() == MVT::i64 && ST->isTruncatingStore())) { |
717 | SDValue Base = Const32->getOperand(0); |
718 | if (Base.getOpcode() == ISD::TargetGlobalAddress) { |
719 | EVT StoredVT = ST->getMemoryVT(); |
720 | int64_t Offset = cast<GlobalAddressSDNode>(Base)->getOffset(); |
721 | if (Offset != 0 && OffsetFitsS11(StoredVT, Offset)) { |
722 | MVT PointerTy = TLI.getPointerTy(); |
723 | const GlobalValue* GV = |
724 | cast<GlobalAddressSDNode>(Base)->getGlobal(); |
725 | SDValue TargAddr = |
726 | CurDAG->getTargetGlobalAddress(GV, dl, PointerTy, 0); |
727 | SDNode* NewBase = CurDAG->getMachineNode(Hexagon::CONST32_set, |
728 | dl, PointerTy, |
729 | TargAddr); |
730 | |
731 | |
732 | if (StoredVT == MVT::i64) Opcode = Hexagon::STrid_indexed; |
733 | else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed; |
734 | else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed; |
735 | else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed; |
736 | else llvm_unreachable("unknown memory type")__builtin_unreachable(); |
737 | |
738 | SDValue Ops[] = {SDValue(NewBase,0), |
739 | CurDAG->getTargetConstant(Offset,PointerTy), |
740 | Value, Chain}; |
741 | |
742 | SDNode* Result = CurDAG->getMachineNode(Opcode, dl, |
743 | MVT::Other, Ops, 4); |
744 | MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1); |
745 | MemOp[0] = ST->getMemOperand(); |
746 | cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1); |
747 | ReplaceUses(ST, Result); |
748 | return Result; |
749 | } |
750 | } |
751 | } |
752 | |
753 | return SelectCode(ST); |
754 | } |
755 | |
756 | |
757 | SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) { |
758 | DebugLoc dl = N->getDebugLoc(); |
759 | StoreSDNode *ST = cast<StoreSDNode>(N); |
760 | ISD::MemIndexedMode AM = ST->getAddressingMode(); |
761 | |
762 | |
763 | if (AM != ISD::UNINDEXED) { |
764 | return SelectIndexedStore(ST, dl); |
765 | } |
766 | |
767 | return SelectBaseOffsetStore(ST, dl); |
768 | } |
769 | |
770 | SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) { |
771 | DebugLoc dl = N->getDebugLoc(); |
772 | |
773 | |
774 | |
775 | |
776 | |
777 | |
778 | |
779 | |
780 | |
781 | |
782 | |
783 | if (N->getValueType(0) == MVT::i64) { |
784 | |
785 | SDValue MulOp0 = N->getOperand(0); |
786 | SDValue MulOp1 = N->getOperand(1); |
787 | |
788 | SDValue OP0; |
789 | SDValue OP1; |
790 | |
791 | |
792 | if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { |
793 | SDValue Sext0 = MulOp0.getOperand(0); |
794 | if (Sext0.getNode()->getValueType(0) != MVT::i32) { |
795 | return SelectCode(N); |
796 | } |
797 | |
798 | OP0 = Sext0; |
799 | } else if (MulOp0.getOpcode() == ISD::LOAD) { |
800 | LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); |
801 | if (LD->getMemoryVT() != MVT::i32 || |
802 | LD->getExtensionType() != ISD::SEXTLOAD || |
803 | LD->getAddressingMode() != ISD::UNINDEXED) { |
804 | return SelectCode(N); |
805 | } |
806 | |
807 | SDValue Chain = LD->getChain(); |
808 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
809 | OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, |
810 | MVT::Other, |
811 | LD->getBasePtr(), TargetConst0, |
812 | Chain), 0); |
813 | } else { |
814 | return SelectCode(N); |
815 | } |
816 | |
817 | |
818 | if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { |
819 | SDValue Sext1 = MulOp1.getOperand(0); |
820 | if (Sext1.getNode()->getValueType(0) != MVT::i32) { |
821 | return SelectCode(N); |
822 | } |
823 | |
824 | OP1 = Sext1; |
825 | } else if (MulOp1.getOpcode() == ISD::LOAD) { |
826 | LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); |
827 | if (LD->getMemoryVT() != MVT::i32 || |
828 | LD->getExtensionType() != ISD::SEXTLOAD || |
829 | LD->getAddressingMode() != ISD::UNINDEXED) { |
830 | return SelectCode(N); |
831 | } |
832 | |
833 | SDValue Chain = LD->getChain(); |
834 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
835 | OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, |
836 | MVT::Other, |
837 | LD->getBasePtr(), TargetConst0, |
838 | Chain), 0); |
839 | } else { |
840 | return SelectCode(N); |
841 | } |
842 | |
843 | |
844 | SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY64, dl, MVT::i64, |
845 | OP0, OP1); |
846 | ReplaceUses(N, Result); |
847 | return Result; |
848 | } |
849 | |
850 | return SelectCode(N); |
851 | } |
852 | |
853 | |
854 | SDNode *HexagonDAGToDAGISel::SelectSelect(SDNode *N) { |
855 | DebugLoc dl = N->getDebugLoc(); |
856 | SDValue N0 = N->getOperand(0); |
857 | if (N0.getOpcode() == ISD::SETCC) { |
858 | SDValue N00 = N0.getOperand(0); |
859 | if (N00.getOpcode() == ISD::SIGN_EXTEND_INREG) { |
860 | SDValue N000 = N00.getOperand(0); |
861 | SDValue N001 = N00.getOperand(1); |
862 | if (cast<VTSDNode>(N001)->getVT() == MVT::i16) { |
863 | SDValue N01 = N0.getOperand(1); |
864 | SDValue N02 = N0.getOperand(2); |
865 | |
866 | |
867 | |
868 | |
869 | |
870 | |
871 | if (cast<CondCodeSDNode>(N02)->get() == ISD::SETLT) { |
872 | SDValue N1 = N->getOperand(1); |
873 | if (N01 == N1) { |
874 | SDValue N2 = N->getOperand(2); |
875 | if (N000 == N2 && |
876 | N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && |
877 | N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { |
878 | SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, |
879 | MVT::i32, N000); |
880 | SDNode *Result = CurDAG->getMachineNode(Hexagon::MAXw_rr, dl, |
881 | MVT::i32, |
882 | SDValue(SextNode, 0), |
883 | N1); |
884 | ReplaceUses(N, Result); |
885 | return Result; |
886 | } |
887 | } |
888 | } |
889 | |
890 | |
891 | |
892 | |
893 | |
894 | |
895 | if (cast<CondCodeSDNode>(N02)->get() == ISD::SETGT) { |
896 | SDValue N1 = N->getOperand(1); |
897 | if (N01 == N1) { |
898 | SDValue N2 = N->getOperand(2); |
899 | if (N000 == N2 && |
900 | N0.getNode()->getValueType(N0.getResNo()) == MVT::i1 && |
901 | N00.getNode()->getValueType(N00.getResNo()) == MVT::i32) { |
902 | SDNode *SextNode = CurDAG->getMachineNode(Hexagon::SXTH, dl, |
903 | MVT::i32, N000); |
904 | SDNode *Result = CurDAG->getMachineNode(Hexagon::MINw_rr, dl, |
905 | MVT::i32, |
906 | SDValue(SextNode, 0), |
907 | N1); |
908 | ReplaceUses(N, Result); |
909 | return Result; |
910 | } |
911 | } |
912 | } |
913 | } |
914 | } |
915 | } |
916 | |
917 | return SelectCode(N); |
918 | } |
919 | |
920 | |
921 | SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) { |
922 | DebugLoc dl = N->getDebugLoc(); |
923 | SDValue Shift = N->getOperand(0); |
924 | |
925 | |
926 | |
927 | |
928 | |
929 | |
930 | |
931 | |
932 | |
933 | |
934 | |
935 | |
936 | |
937 | if (N->getValueType(0) == MVT::i32) { |
938 | |
939 | if (Shift.getNode()->getValueType(0) == MVT::i64) { |
940 | |
941 | if (Shift.getOpcode() != ISD::SRL) { |
942 | return SelectCode(N); |
943 | } |
944 | |
945 | SDValue ShiftOp0 = Shift.getOperand(0); |
946 | SDValue ShiftOp1 = Shift.getOperand(1); |
947 | |
948 | |
949 | if (ShiftOp1.getOpcode() != ISD::Constant) { |
950 | return SelectCode(N); |
951 | } |
952 | |
953 | int32_t ShiftConst = |
954 | cast<ConstantSDNode>(ShiftOp1.getNode())->getSExtValue(); |
955 | if (ShiftConst != 32) { |
956 | return SelectCode(N); |
957 | } |
958 | |
959 | |
960 | SDValue Mul = ShiftOp0; |
961 | if (Mul.getOpcode() != ISD::MUL) { |
962 | return SelectCode(N); |
963 | } |
964 | |
965 | SDValue MulOp0 = Mul.getOperand(0); |
966 | SDValue MulOp1 = Mul.getOperand(1); |
967 | |
968 | SDValue OP0; |
969 | SDValue OP1; |
970 | |
971 | |
972 | if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) { |
973 | SDValue Sext0 = MulOp0.getOperand(0); |
974 | if (Sext0.getNode()->getValueType(0) != MVT::i32) { |
975 | return SelectCode(N); |
976 | } |
977 | |
978 | OP0 = Sext0; |
979 | } else if (MulOp0.getOpcode() == ISD::LOAD) { |
980 | LoadSDNode *LD = cast<LoadSDNode>(MulOp0.getNode()); |
981 | if (LD->getMemoryVT() != MVT::i32 || |
982 | LD->getExtensionType() != ISD::SEXTLOAD || |
983 | LD->getAddressingMode() != ISD::UNINDEXED) { |
984 | return SelectCode(N); |
985 | } |
986 | |
987 | SDValue Chain = LD->getChain(); |
988 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
989 | OP0 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, |
990 | MVT::Other, |
991 | LD->getBasePtr(), |
992 | TargetConst0, Chain), 0); |
993 | } else { |
994 | return SelectCode(N); |
995 | } |
996 | |
997 | |
998 | if (MulOp1.getOpcode() == ISD::SIGN_EXTEND) { |
999 | SDValue Sext1 = MulOp1.getOperand(0); |
1000 | if (Sext1.getNode()->getValueType(0) != MVT::i32) |
1001 | return SelectCode(N); |
1002 | |
1003 | OP1 = Sext1; |
1004 | } else if (MulOp1.getOpcode() == ISD::LOAD) { |
1005 | LoadSDNode *LD = cast<LoadSDNode>(MulOp1.getNode()); |
1006 | if (LD->getMemoryVT() != MVT::i32 || |
1007 | LD->getExtensionType() != ISD::SEXTLOAD || |
1008 | LD->getAddressingMode() != ISD::UNINDEXED) { |
1009 | return SelectCode(N); |
1010 | } |
1011 | |
1012 | SDValue Chain = LD->getChain(); |
1013 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
1014 | OP1 = SDValue (CurDAG->getMachineNode(Hexagon::LDriw, dl, MVT::i32, |
1015 | MVT::Other, |
1016 | LD->getBasePtr(), |
1017 | TargetConst0, Chain), 0); |
1018 | } else { |
1019 | return SelectCode(N); |
1020 | } |
1021 | |
1022 | |
1023 | SDNode *Result = CurDAG->getMachineNode(Hexagon::MPY, dl, MVT::i32, |
1024 | OP0, OP1); |
1025 | ReplaceUses(N, Result); |
1026 | return Result; |
1027 | } |
1028 | } |
1029 | |
1030 | return SelectCode(N); |
1031 | } |
1032 | |
1033 | |
1034 | SDNode *HexagonDAGToDAGISel::SelectSHL(SDNode *N) { |
1035 | DebugLoc dl = N->getDebugLoc(); |
1036 | if (N->getValueType(0) == MVT::i32) { |
1037 | SDValue Shl_0 = N->getOperand(0); |
1038 | SDValue Shl_1 = N->getOperand(1); |
1039 | |
1040 | if (Shl_1.getOpcode() == ISD::Constant) { |
1041 | if (Shl_0.getOpcode() == ISD::MUL) { |
1042 | SDValue Mul_0 = Shl_0.getOperand(0); |
1043 | SDValue Mul_1 = Shl_0.getOperand(1); |
1044 | |
1045 | if (Mul_1.getOpcode() == ISD::Constant) { |
1046 | int32_t ShlConst = |
1047 | cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); |
1048 | int32_t MulConst = |
1049 | cast<ConstantSDNode>(Mul_1.getNode())->getSExtValue(); |
1050 | int32_t ValConst = MulConst << ShlConst; |
1051 | SDValue Val = CurDAG->getTargetConstant(ValConst, |
1052 | MVT::i32); |
1053 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Val.getNode())) |
1054 | if (isInt<9>(CN->getSExtValue())) { |
1055 | SDNode* Result = |
1056 | CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, |
1057 | MVT::i32, Mul_0, Val); |
1058 | ReplaceUses(N, Result); |
1059 | return Result; |
1060 | } |
1061 | |
1062 | } |
1063 | } else if (Shl_0.getOpcode() == ISD::SUB) { |
1064 | SDValue Sub_0 = Shl_0.getOperand(0); |
1065 | SDValue Sub_1 = Shl_0.getOperand(1); |
1066 | if (Sub_0.getOpcode() == ISD::Constant) { |
1067 | int32_t SubConst = |
1068 | cast<ConstantSDNode>(Sub_0.getNode())->getSExtValue(); |
1069 | if (SubConst == 0) { |
1070 | if (Sub_1.getOpcode() == ISD::SHL) { |
1071 | SDValue Shl2_0 = Sub_1.getOperand(0); |
1072 | SDValue Shl2_1 = Sub_1.getOperand(1); |
1073 | if (Shl2_1.getOpcode() == ISD::Constant) { |
1074 | int32_t ShlConst = |
1075 | cast<ConstantSDNode>(Shl_1.getNode())->getSExtValue(); |
1076 | int32_t Shl2Const = |
1077 | cast<ConstantSDNode>(Shl2_1.getNode())->getSExtValue(); |
1078 | int32_t ValConst = 1 << (ShlConst+Shl2Const); |
1079 | SDValue Val = CurDAG->getTargetConstant(-ValConst, MVT::i32); |
1080 | if (ConstantSDNode *CN = |
1081 | dyn_cast<ConstantSDNode>(Val.getNode())) |
1082 | if (isInt<9>(CN->getSExtValue())) { |
1083 | SDNode* Result = |
1084 | CurDAG->getMachineNode(Hexagon::MPYI_ri, dl, MVT::i32, |
1085 | Shl2_0, Val); |
1086 | ReplaceUses(N, Result); |
1087 | return Result; |
1088 | } |
1089 | } |
1090 | } |
1091 | } |
1092 | } |
1093 | } |
1094 | } |
1095 | } |
1096 | return SelectCode(N); |
1097 | } |
1098 | |
1099 | |
1100 | |
1101 | |
1102 | |
1103 | |
1104 | |
1105 | |
1106 | |
1107 | |
1108 | |
1109 | |
1110 | SDNode *HexagonDAGToDAGISel::SelectZeroExtend(SDNode *N) { |
1111 | DebugLoc dl = N->getDebugLoc(); |
1112 | SDNode *IsIntrinsic = N->getOperand(0).getNode(); |
1113 | if ((IsIntrinsic->getOpcode() == ISD::INTRINSIC_WO_CHAIN)) { |
1114 | unsigned ID = |
1115 | cast<ConstantSDNode>(IsIntrinsic->getOperand(0))->getZExtValue(); |
1116 | if (doesIntrinsicReturnPredicate(ID)) { |
1117 | |
1118 | if (N->getValueType(0) == MVT::i64) { |
1119 | |
1120 | SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32); |
1121 | SDNode *Result_1 = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, |
1122 | MVT::i32, |
1123 | SDValue(IsIntrinsic, 0)); |
1124 | SDNode *Result_2 = CurDAG->getMachineNode(Hexagon::TFRI, dl, |
1125 | MVT::i32, |
1126 | TargetConst0); |
1127 | SDNode *Result_3 = CurDAG->getMachineNode(Hexagon::COMBINE_rr, dl, |
1128 | MVT::i64, MVT::Other, |
1129 | SDValue(Result_2, 0), |
1130 | SDValue(Result_1, 0)); |
1131 | ReplaceUses(N, Result_3); |
1132 | return Result_3; |
1133 | } |
1134 | if (N->getValueType(0) == MVT::i32) { |
1135 | |
1136 | SDNode* RsPd = CurDAG->getMachineNode(Hexagon::TFR_RsPd, dl, |
1137 | MVT::i32, |
1138 | SDValue(IsIntrinsic, 0)); |
1139 | ReplaceUses(N, RsPd); |
1140 | return RsPd; |
1141 | } |
1142 | llvm_unreachable("Unexpected value type")__builtin_unreachable(); |
1143 | } |
1144 | } |
1145 | return SelectCode(N); |
1146 | } |
1147 | |
1148 | |
1149 | |
1150 | |
1151 | |
1152 | |
1153 | SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) { |
1154 | DebugLoc dl = N->getDebugLoc(); |
1155 | unsigned ID = cast<ConstantSDNode>(N->getOperand(0))->getZExtValue(); |
1156 | unsigned IntrinsicWithPred = doesIntrinsicContainPredicate(ID); |
1157 | |
1158 | |
1159 | |
1160 | if (IntrinsicWithPred) { |
1161 | SmallVector<SDValue, 8> Ops; |
1162 | const MCInstrDesc &MCID = TII->get(IntrinsicWithPred); |
1163 | const TargetRegisterInfo *TRI = TM.getRegisterInfo(); |
1164 | |
1165 | |
1166 | |
1167 | |
1168 | |
1169 | for (unsigned i = 1; i < N->getNumOperands(); ++i) { |
1170 | SDNode *Arg = N->getOperand(i).getNode(); |
1171 | const TargetRegisterClass *RC = TII->getRegClass(MCID, i, TRI, *MF); |
1172 | |
1173 | if (RC == &Hexagon::IntRegsRegClass || |
1174 | RC == &Hexagon::DoubleRegsRegClass) { |
1175 | Ops.push_back(SDValue(Arg, 0)); |
1176 | } else if (RC == &Hexagon::PredRegsRegClass) { |
1177 | |
1178 | SDNode *PdRs = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, |
1179 | SDValue(Arg, 0)); |
1180 | Ops.push_back(SDValue(PdRs,0)); |
1181 | } else if (RC == NULL__null && (dyn_cast<ConstantSDNode>(Arg) != NULL__null)) { |
1182 | |
1183 | |
1184 | int32_t Val = cast<ConstantSDNode>(Arg)->getSExtValue(); |
1185 | SDValue SDVal = CurDAG->getTargetConstant(Val, MVT::i32); |
1186 | Ops.push_back(SDVal); |
1187 | } else { |
1188 | llvm_unreachable("Unimplemented")__builtin_unreachable(); |
1189 | } |
1190 | } |
1191 | EVT ReturnValueVT = N->getValueType(0); |
1192 | SDNode *Result = CurDAG->getMachineNode(IntrinsicWithPred, dl, |
1193 | ReturnValueVT, |
1194 | Ops.data(), Ops.size()); |
1195 | ReplaceUses(N, Result); |
1196 | return Result; |
1197 | } |
1198 | return SelectCode(N); |
1199 | } |
1200 | |
1201 | |
1202 | |
1203 | |
1204 | SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) { |
1205 | DebugLoc dl = N->getDebugLoc(); |
1206 | ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N); |
1207 | APFloat APF = CN->getValueAPF(); |
1208 | if (N->getValueType(0) == MVT::f32) { |
1209 | return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32, |
1210 | CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32)); |
1211 | } |
1212 | else if (N->getValueType(0) == MVT::f64) { |
1213 | return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64, |
1214 | CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64)); |
1215 | } |
1216 | |
1217 | return SelectCode(N); |
1218 | } |
1219 | |
1220 | |
1221 | |
1222 | |
1223 | |
1224 | SDNode *HexagonDAGToDAGISel::SelectConstant(SDNode *N) { |
1225 | DebugLoc dl = N->getDebugLoc(); |
1226 | if (N->getValueType(0) == MVT::i1) { |
1227 | SDNode* Result; |
1228 | int32_t Val = cast<ConstantSDNode>(N)->getSExtValue(); |
1229 | if (Val == -1) { |
1230 | |
1231 | SDNode* IntRegTFR = |
1232 | CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32, |
1233 | CurDAG->getTargetConstant(0, MVT::i32)); |
1234 | |
1235 | |
1236 | SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1, |
1237 | SDValue(IntRegTFR, 0)); |
1238 | |
1239 | |
1240 | SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1, |
1241 | SDValue(Pd, 0)); |
1242 | |
1243 | |
1244 | Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1, |
1245 | SDValue(Pd, 0), SDValue(NotPd, 0)); |
1246 | |
1247 | |
1248 | |
1249 | |
1250 | |
1251 | ReplaceUses(N, Result); |
1252 | return Result; |
1253 | } |
1254 | } |
1255 | |
1256 | return SelectCode(N); |
1257 | } |
1258 | |
1259 | |
1260 | |
1261 | |
1262 | |
1263 | SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) { |
1264 | DebugLoc dl = N->getDebugLoc(); |
1265 | if (N->getValueType(0) != MVT::i32) { |
1266 | return SelectCode(N); |
1267 | } |
1268 | |
1269 | SDNode* Src1 = N->getOperand(0).getNode(); |
1270 | if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse() |
1271 | || Src1->getValueType(0) != MVT::i32) { |
1272 | return SelectCode(N); |
1273 | } |
1274 | |
1275 | |
1276 | |
1277 | SDNode* Result = CurDAG->getMachineNode(Hexagon::ASR_ADD_rr, dl, MVT::i32, |
1278 | N->getOperand(1), |
1279 | Src1->getOperand(0), |
1280 | Src1->getOperand(1)); |
1281 | ReplaceUses(N, Result); |
1282 | |
1283 | return Result; |
1284 | } |
1285 | |
1286 | |
1287 | SDNode *HexagonDAGToDAGISel::Select(SDNode *N) { |
1288 | if (N->isMachineOpcode()) |
1289 | return NULL__null; |
1290 | |
1291 | |
1292 | switch (N->getOpcode()) { |
1293 | case ISD::Constant: |
1294 | return SelectConstant(N); |
1295 | |
1296 | case ISD::ConstantFP: |
1297 | return SelectConstantFP(N); |
1298 | |
1299 | case ISD::ADD: |
1300 | return SelectAdd(N); |
1301 | |
1302 | case ISD::SHL: |
1303 | return SelectSHL(N); |
1304 | |
1305 | case ISD::LOAD: |
1306 | return SelectLoad(N); |
1307 | |
1308 | case ISD::STORE: |
1309 | return SelectStore(N); |
1310 | |
1311 | case ISD::SELECT: |
1312 | return SelectSelect(N); |
1313 | |
1314 | case ISD::TRUNCATE: |
1315 | return SelectTruncate(N); |
1316 | |
1317 | case ISD::MUL: |
1318 | return SelectMul(N); |
1319 | |
1320 | case ISD::ZERO_EXTEND: |
1321 | return SelectZeroExtend(N); |
1322 | |
1323 | case ISD::INTRINSIC_WO_CHAIN: |
1324 | return SelectIntrinsicWOChain(N); |
1325 | } |
1326 | |
1327 | return SelectCode(N); |
1328 | } |
1329 | |
1330 | |
1331 | |
1332 | |
1333 | |
1334 | |
1335 | bool HexagonDAGToDAGISel::SelectADDRri(SDValue& Addr, SDValue &Base, |
1336 | SDValue &Offset) { |
1337 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1338 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1339 | return false; |
1340 | |
1341 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1342 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1343 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1344 | return true; |
1345 | } |
1346 | Base = Addr; |
1347 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1348 | return true; |
1349 | } |
1350 | |
1351 | |
1352 | bool HexagonDAGToDAGISel::SelectADDRriS11_0(SDValue& Addr, SDValue &Base, |
1353 | SDValue &Offset) { |
1354 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1355 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1356 | return false; |
1357 | |
1358 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1359 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1360 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1361 | return (IsS11_0_Offset(Offset.getNode())); |
1362 | } |
1363 | Base = Addr; |
1364 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1365 | return (IsS11_0_Offset(Offset.getNode())); |
1366 | } |
1367 | |
1368 | |
1369 | bool HexagonDAGToDAGISel::SelectADDRriS11_1(SDValue& Addr, SDValue &Base, |
1370 | SDValue &Offset) { |
1371 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1372 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1373 | return false; |
1374 | |
1375 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1376 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1377 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1378 | return (IsS11_1_Offset(Offset.getNode())); |
1379 | } |
1380 | Base = Addr; |
1381 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1382 | return (IsS11_1_Offset(Offset.getNode())); |
1383 | } |
1384 | |
1385 | |
1386 | bool HexagonDAGToDAGISel::SelectADDRriS11_2(SDValue& Addr, SDValue &Base, |
1387 | SDValue &Offset) { |
1388 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1389 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1390 | return false; |
1391 | |
1392 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1393 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1394 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1395 | return (IsS11_2_Offset(Offset.getNode())); |
1396 | } |
1397 | Base = Addr; |
1398 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1399 | return (IsS11_2_Offset(Offset.getNode())); |
1400 | } |
1401 | |
1402 | |
1403 | bool HexagonDAGToDAGISel::SelectADDRriU6_0(SDValue& Addr, SDValue &Base, |
1404 | SDValue &Offset) { |
1405 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1406 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1407 | return false; |
1408 | |
1409 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1410 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1411 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1412 | return (IsU6_0_Offset(Offset.getNode())); |
1413 | } |
1414 | Base = Addr; |
1415 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1416 | return (IsU6_0_Offset(Offset.getNode())); |
1417 | } |
1418 | |
1419 | |
1420 | bool HexagonDAGToDAGISel::SelectADDRriU6_1(SDValue& Addr, SDValue &Base, |
1421 | SDValue &Offset) { |
1422 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1423 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1424 | return false; |
1425 | |
1426 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1427 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1428 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1429 | return (IsU6_1_Offset(Offset.getNode())); |
1430 | } |
1431 | Base = Addr; |
1432 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1433 | return (IsU6_1_Offset(Offset.getNode())); |
1434 | } |
1435 | |
1436 | |
1437 | bool HexagonDAGToDAGISel::SelectADDRriU6_2(SDValue& Addr, SDValue &Base, |
1438 | SDValue &Offset) { |
1439 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1440 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1441 | return false; |
1442 | |
1443 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1444 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1445 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1446 | return (IsU6_2_Offset(Offset.getNode())); |
1447 | } |
1448 | Base = Addr; |
1449 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1450 | return (IsU6_2_Offset(Offset.getNode())); |
1451 | } |
1452 | |
1453 | |
1454 | bool HexagonDAGToDAGISel::SelectMEMriS11_2(SDValue& Addr, SDValue &Base, |
1455 | SDValue &Offset) { |
1456 | |
1457 | if (Addr.getOpcode() != ISD::ADD) { |
1458 | return(SelectADDRriS11_2(Addr, Base, Offset)); |
1459 | } |
1460 | |
1461 | return SelectADDRriS11_2(Addr, Base, Offset); |
1462 | } |
1463 | |
1464 | |
1465 | bool HexagonDAGToDAGISel::SelectADDRriS11_3(SDValue& Addr, SDValue &Base, |
1466 | SDValue &Offset) { |
1467 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1468 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1469 | return false; |
1470 | |
1471 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1472 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1473 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1474 | return (IsS11_3_Offset(Offset.getNode())); |
1475 | } |
1476 | Base = Addr; |
1477 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1478 | return (IsS11_3_Offset(Offset.getNode())); |
1479 | } |
1480 | |
1481 | bool HexagonDAGToDAGISel::SelectADDRrr(SDValue &Addr, SDValue &R1, |
1482 | SDValue &R2) { |
1483 | if (Addr.getOpcode() == ISD::FrameIndex) return false; |
1484 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1485 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1486 | return false; |
1487 | |
1488 | if (Addr.getOpcode() == ISD::ADD) { |
1489 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) |
1490 | if (isInt<13>(CN->getSExtValue())) |
1491 | return false; |
1492 | R1 = Addr.getOperand(0); |
1493 | R2 = Addr.getOperand(1); |
1494 | return true; |
1495 | } |
1496 | |
1497 | R1 = Addr; |
1498 | |
1499 | return true; |
1500 | } |
1501 | |
1502 | |
1503 | |
1504 | |
1505 | bool HexagonDAGToDAGISel::SelectAddr(SDNode *Op, SDValue Addr, |
1506 | SDValue &Base, SDValue &Offset) { |
1507 | if (Addr.getOpcode() == ISD::TargetExternalSymbol || |
1508 | Addr.getOpcode() == ISD::TargetGlobalAddress) |
1509 | return false; |
1510 | |
1511 | if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { |
1512 | Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i32); |
1513 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1514 | return true; |
1515 | } |
1516 | |
1517 | if (Addr.getOpcode() == ISD::ADD) { |
1518 | Base = Addr.getOperand(0); |
1519 | Offset = Addr.getOperand(1); |
1520 | return true; |
1521 | } |
1522 | |
1523 | Base = Addr; |
1524 | Offset = CurDAG->getTargetConstant(0, MVT::i32); |
1525 | return true; |
1526 | } |
1527 | |
1528 | |
1529 | bool HexagonDAGToDAGISel:: |
1530 | SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, |
1531 | std::vector<SDValue> &OutOps) { |
1532 | SDValue Op0, Op1; |
1533 | |
1534 | switch (ConstraintCode) { |
1535 | case 'o': |
1536 | case 'v': |
1537 | default: return true; |
1538 | case 'm': |
1539 | if (!SelectAddr(Op.getNode(), Op, Op0, Op1)) |
1540 | return true; |
1541 | break; |
1542 | } |
1543 | |
1544 | OutOps.push_back(Op0); |
1545 | OutOps.push_back(Op1); |
1546 | return false; |
1547 | } |
1548 | |
1549 | bool HexagonDAGToDAGISel::isConstExtProfitable(SDNode *N) const { |
1550 | unsigned UseCount = 0; |
1551 | for (SDNode::use_iterator I = N->use_begin(), E = N->use_end(); I != E; ++I) { |
1552 | UseCount++; |
1553 | } |
1554 | |
1555 | return (UseCount <= 1); |
1556 | |
1557 | } |
1558 | |
1559 | |
1560 | |
1561 | |
1562 | bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const { |
1563 | assert(N->getOpcode() == ISD::TargetGlobalAddress &&((void)0) |
1564 | "Expecting a target global address")((void)0); |
1565 | |
1566 | |
1567 | if (TM.getOptLevel() == CodeGenOpt::Aggressive) |
1568 | return true; |
1569 | |
1570 | GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N); |
1571 | DenseMap<const GlobalValue *, unsigned>::const_iterator GI = |
1572 | GlobalAddressUseCountMap.find(GA->getGlobal()); |
1573 | |
1574 | if (GI == GlobalAddressUseCountMap.end()) |
1575 | return false; |
1576 | |
1577 | return GI->second <= MaxNumOfUsesForConstExtenders; |
1578 | } |
1579 | |
1580 | |
1581 | |
1582 | |
1583 | inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) { |
1584 | return foldGlobalAddressImpl(N, R, false); |
1585 | } |
1586 | |
1587 | |
1588 | |
1589 | |
1590 | inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) { |
1591 | return foldGlobalAddressImpl(N, R, true); |
1592 | } |
1593 | |
1594 | |
1595 | |
1596 | |
1597 | bool HexagonDAGToDAGISel::foldGlobalAddressImpl(SDValue &N, SDValue &R, |
1598 | bool ShouldLookForGP) { |
1599 | if (N.getOpcode() == ISD::ADD) { |
1600 | SDValue N0 = N.getOperand(0); |
1601 | SDValue N1 = N.getOperand(1); |
1602 | if ((ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32_GP)) || |
1603 | (!ShouldLookForGP && (N0.getOpcode() == HexagonISD::CONST32))) { |
1604 | ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1); |
1605 | GlobalAddressSDNode *GA = |
1606 | dyn_cast<GlobalAddressSDNode>(N0.getOperand(0)); |
1607 | |
1608 | if (Const && GA && |
1609 | (GA->getOpcode() == ISD::TargetGlobalAddress)) { |
1610 | if ((N0.getOpcode() == HexagonISD::CONST32) && |
1611 | !hasNumUsesBelowThresGA(GA)) |
1612 | return false; |
1613 | R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), |
1614 | Const->getDebugLoc(), |
1615 | N.getValueType(), |
1616 | GA->getOffset() + |
1617 | (uint64_t)Const->getSExtValue()); |
1618 | return true; |
1619 | } |
1620 | } |
1621 | } |
1622 | return false; |
1623 | } |