1 //===-- HexagonISelDAGToDAG.cpp - A dag to dag inst selector for Hexagon --===//
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 Hexagon target.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "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 // Instruction Selector Implementation
35 //===----------------------------------------------------------------------===//
36
37 namespace llvm {
38 void initializeHexagonDAGToDAGISelPass(PassRegistry&);
39 }
40
41 //===--------------------------------------------------------------------===//
42 /// HexagonDAGToDAGISel - Hexagon specific code to select Hexagon machine
43 /// instructions for SelectionDAG operations.
44 ///
45 namespace {
46 class HexagonDAGToDAGISel : public SelectionDAGISel {
47 /// Subtarget - Keep a pointer to the Hexagon Subtarget around so that we can
48 /// make the right decision when generating code for different targets.
49 const HexagonSubtarget &Subtarget;
50
51 // Keep a reference to HexagonTargetMachine.
52 HexagonTargetMachine& TM;
53 const HexagonInstrInfo *TII;
54 DenseMap<const GlobalValue *, unsigned> GlobalAddressUseCountMap;
55 public:
HexagonDAGToDAGISel(HexagonTargetMachine & targetmachine,CodeGenOpt::Level OptLevel)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 // Complex Pattern Selectors.
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
getPassName() const83 virtual const char *getPassName() const {
84 return "Hexagon DAG->DAG Pattern Instruction Selection";
85 }
86
87 /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
88 /// inline asm expressions.
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 // XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
117 // [1..128], used in cmpb.gtu instructions.
XformU7ToU7M1Imm(signed Imm)118 inline SDValue XformU7ToU7M1Imm(signed Imm) {
119 assert((Imm >= 1 && Imm <= 128) && "Constant out of range for cmpb op");
120 return CurDAG->getTargetConstant(Imm - 1, MVT::i8);
121 }
122
123 // Include the pieces autogenerated from the target description.
124 #include "HexagonGenDAGISel.inc"
125 };
126 } // end anonymous namespace
127
128
129 /// createHexagonISelDag - This pass converts a legalized DAG into a
130 /// Hexagon-specific DAG, ready for instruction scheduling.
131 ///
createHexagonISelDag(HexagonTargetMachine & TM,CodeGenOpt::Level OptLevel)132 FunctionPass *llvm::createHexagonISelDag(HexagonTargetMachine &TM,
133 CodeGenOpt::Level OptLevel) {
134 return new HexagonDAGToDAGISel(TM, OptLevel);
135 }
136
initializePassOnce(PassRegistry & Registry)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 }
143
initializeHexagonDAGToDAGISelPass(PassRegistry & Registry)144 void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
145 CALL_ONCE_INITIALIZATION(initializePassOnce)
146 }
147
148
IsS11_0_Offset(SDNode * S)149 static bool IsS11_0_Offset(SDNode * S) {
150 ConstantSDNode *N = cast<ConstantSDNode>(S);
151
152 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
153 // field.
154 int64_t v = (int64_t)N->getSExtValue();
155 return isInt<11>(v);
156 }
157
158
IsS11_1_Offset(SDNode * S)159 static bool IsS11_1_Offset(SDNode * S) {
160 ConstantSDNode *N = cast<ConstantSDNode>(S);
161
162 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
163 // field.
164 int64_t v = (int64_t)N->getSExtValue();
165 return isShiftedInt<11,1>(v);
166 }
167
168
IsS11_2_Offset(SDNode * S)169 static bool IsS11_2_Offset(SDNode * S) {
170 ConstantSDNode *N = cast<ConstantSDNode>(S);
171
172 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
173 // field.
174 int64_t v = (int64_t)N->getSExtValue();
175 return isShiftedInt<11,2>(v);
176 }
177
178
IsS11_3_Offset(SDNode * S)179 static bool IsS11_3_Offset(SDNode * S) {
180 ConstantSDNode *N = cast<ConstantSDNode>(S);
181
182 // immS16 predicate - True if the immediate fits in a 16-bit sign extended
183 // field.
184 int64_t v = (int64_t)N->getSExtValue();
185 return isShiftedInt<11,3>(v);
186 }
187
188
IsU6_0_Offset(SDNode * S)189 static bool IsU6_0_Offset(SDNode * S) {
190 ConstantSDNode *N = cast<ConstantSDNode>(S);
191
192 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
193 // field.
194 int64_t v = (int64_t)N->getSExtValue();
195 return isUInt<6>(v);
196 }
197
198
IsU6_1_Offset(SDNode * S)199 static bool IsU6_1_Offset(SDNode * S) {
200 ConstantSDNode *N = cast<ConstantSDNode>(S);
201
202 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
203 // field.
204 int64_t v = (int64_t)N->getSExtValue();
205 return isShiftedUInt<6,1>(v);
206 }
207
208
IsU6_2_Offset(SDNode * S)209 static bool IsU6_2_Offset(SDNode * S) {
210 ConstantSDNode *N = cast<ConstantSDNode>(S);
211
212 // u6 predicate - True if the immediate fits in a 6-bit unsigned extended
213 // field.
214 int64_t v = (int64_t)N->getSExtValue();
215 return isShiftedUInt<6,2>(v);
216 }
217
218
219 // Intrinsics that return a a predicate.
doesIntrinsicReturnPredicate(unsigned ID)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 // Intrinsics that have predicate operands.
doesIntrinsicContainPredicate(unsigned ID)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 // Mapping hexagon_C2_muxir to MUX_pri. This is pretty weird - but
294 // that's how it's mapped in q6protos.h.
295 case Intrinsic::hexagon_C2_muxir:
296 return Hexagon::MUX_ri;
297
298 // Mapping hexagon_C2_muxri to MUX_pir. This is pretty weird - but
299 // that's how it's mapped in q6protos.h.
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
OffsetFitsS11(EVT MemType,int64_t Offset)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 // Try to lower loads of GlobalAdresses into base+offset loads. Custom
334 // lowering for GlobalAddress nodes has already turned it into a
335 // CONST32.
336 //
SelectBaseOffsetLoad(LoadSDNode * LD,DebugLoc dl)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 // Figure out base + offset opcode
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");
362
363 // Build indexed load.
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
SelectIndexedLoadSignExtend64(LoadSDNode * LD,unsigned Opcode,DebugLoc dl)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
SelectIndexedLoadZeroExtend64(LoadSDNode * LD,unsigned Opcode,DebugLoc dl)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 // Generate an indirect load.
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 // Add offset to base.
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), // Load value.
513 SDValue(Result_4, 0), // New address.
514 SDValue(Result_1, 1)
515 };
516 ReplaceUses(Froms, Tos, 3);
517 return Result_3;
518 }
519
520 return SelectCode(LD);
521 }
522
523
SelectIndexedLoad(LoadSDNode * LD,DebugLoc dl)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 // Get the constant value.
530 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
531 EVT LoadedVT = LD->getMemoryVT();
532 unsigned Opcode = 0;
533
534 // Check for zero ext loads.
535 bool zextval = (LD->getExtensionType() == ISD::ZEXTLOAD);
536
537 // Figure out the opcode.
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");
560
561 // For zero ext i64 loads, we need to add combine instructions.
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 // Handle sign ext i64 loads.
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
SelectLoad(SDNode * N)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 // Handle indexed loads.
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
SelectIndexedStore(StoreSDNode * ST,DebugLoc dl)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 // Get the constant value.
641 int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
642 EVT StoredVT = ST->getMemoryVT();
643
644 // Offset value must be within representable range
645 // and must have correct alignment properties.
646 if (TII->isValidAutoIncImm(StoredVT, Val)) {
647 SDValue Ops[] = {Base, CurDAG->getTargetConstant(Val, MVT::i32), Value,
648 Chain};
649 unsigned Opcode = 0;
650
651 // Figure out the post inc version of opcode.
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");
657
658 // Build post increment store.
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 // Note: Order of operands matches the def of instruction:
671 // def STrid : STInst<(outs), (ins MEMri:$addr, DoubleRegs:$src1), ...
672 // and it differs for POST_ST* for instance.
673 SDValue Ops[] = { Base, CurDAG->getTargetConstant(0, MVT::i32), Value,
674 Chain};
675 unsigned Opcode = 0;
676
677 // Figure out the opcode.
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");
683
684 // Build regular store.
685 SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
686 SDNode* Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::Other, Ops,
687 4);
688 // Build splitted incriment instruction.
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
SelectBaseOffsetStore(StoreSDNode * ST,DebugLoc dl)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 // Try to lower stores of GlobalAdresses into indexed stores. Custom
711 // lowering for GlobalAddress nodes has already turned it into a
712 // CONST32. Avoid truncating stores for the moment. Post-inc stores
713 // do the same. Don't think there's a reason for it, so will file a
714 // bug to fix.
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 // Figure out base + offset opcode
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");
737
738 SDValue Ops[] = {SDValue(NewBase,0),
739 CurDAG->getTargetConstant(Offset,PointerTy),
740 Value, Chain};
741 // build indexed store
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
SelectStore(SDNode * N)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 // Handle indexed stores.
763 if (AM != ISD::UNINDEXED) {
764 return SelectIndexedStore(ST, dl);
765 }
766
767 return SelectBaseOffsetStore(ST, dl);
768 }
769
SelectMul(SDNode * N)770 SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
771 DebugLoc dl = N->getDebugLoc();
772
773 //
774 // %conv.i = sext i32 %tmp1 to i64
775 // %conv2.i = sext i32 %add to i64
776 // %mul.i = mul nsw i64 %conv2.i, %conv.i
777 //
778 // --- match with the following ---
779 //
780 // %mul.i = mpy (%tmp1, %add)
781 //
782
783 if (N->getValueType(0) == MVT::i64) {
784 // Shifting a i64 signed multiply.
785 SDValue MulOp0 = N->getOperand(0);
786 SDValue MulOp1 = N->getOperand(1);
787
788 SDValue OP0;
789 SDValue OP1;
790
791 // Handle sign_extend and sextload.
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 // Same goes for the second operand.
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 // Generate a mpy instruction.
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
SelectSelect(SDNode * N)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 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
867 // i16:Other),IntRegs:i32:$src1, SETLT:Other),IntRegs:i32:$src1,
868 // IntRegs:i32:$src2)
869 // Emits: (MAXh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
870 // Pattern complexity = 9 cost = 1 size = 0.
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 // Pattern: (select:i32 (setcc:i1 (sext_inreg:i32 IntRegs:i32:$src2,
891 // i16:Other), IntRegs:i32:$src1, SETGT:Other), IntRegs:i32:$src1,
892 // IntRegs:i32:$src2)
893 // Emits: (MINh_rr:i32 IntRegs:i32:$src1, IntRegs:i32:$src2)
894 // Pattern complexity = 9 cost = 1 size = 0.
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
SelectTruncate(SDNode * N)921 SDNode *HexagonDAGToDAGISel::SelectTruncate(SDNode *N) {
922 DebugLoc dl = N->getDebugLoc();
923 SDValue Shift = N->getOperand(0);
924
925 //
926 // %conv.i = sext i32 %tmp1 to i64
927 // %conv2.i = sext i32 %add to i64
928 // %mul.i = mul nsw i64 %conv2.i, %conv.i
929 // %shr5.i = lshr i64 %mul.i, 32
930 // %conv3.i = trunc i64 %shr5.i to i32
931 //
932 // --- match with the following ---
933 //
934 // %conv3.i = mpy (%tmp1, %add)
935 //
936 // Trunc to i32.
937 if (N->getValueType(0) == MVT::i32) {
938 // Trunc from i64.
939 if (Shift.getNode()->getValueType(0) == MVT::i64) {
940 // Trunc child is logical shift right.
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 // Shift by const 32
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 // Shifting a i64 signed multiply
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 // Handle sign_extend and sextload
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 // Same goes for the second operand.
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 // Generate a mpy instruction.
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
SelectSHL(SDNode * N)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 // RHS is const.
1040 if (Shl_1.getOpcode() == ISD::Constant) {
1041 if (Shl_0.getOpcode() == ISD::MUL) {
1042 SDValue Mul_0 = Shl_0.getOperand(0); // Val
1043 SDValue Mul_1 = Shl_0.getOperand(1); // Const
1044 // RHS of mul is const.
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); // Const 0
1065 SDValue Sub_1 = Shl_0.getOperand(1); // Val
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); // Val
1072 SDValue Shl2_1 = Sub_1.getOperand(1); // Const
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 // If there is an zero_extend followed an intrinsic in DAG (this means - the
1102 // result of the intrinsic is predicate); convert the zero_extend to
1103 // transfer instruction.
1104 //
1105 // Zero extend -> transfer is lowered here. Otherwise, zero_extend will be
1106 // converted into a MUX as predicate registers defined as 1 bit in the
1107 // compiler. Architecture defines them as 8-bit registers.
1108 // We want to preserve all the lower 8-bits and, not just 1 LSB bit.
1109 //
SelectZeroExtend(SDNode * N)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 // Now we need to differentiate target data types.
1118 if (N->getValueType(0) == MVT::i64) {
1119 // Convert the zero_extend to Rs = Pd followed by COMBINE_rr(0,Rs).
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 // Convert the zero_extend to Rs = Pd
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");
1143 }
1144 }
1145 return SelectCode(N);
1146 }
1147
1148
1149 //
1150 // Checking for intrinsics which have predicate registers as operand(s)
1151 // and lowering to the actual intrinsic.
1152 //
SelectIntrinsicWOChain(SDNode * N)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 // We are concerned with only those intrinsics that have predicate registers
1159 // as at least one of the operands.
1160 if (IntrinsicWithPred) {
1161 SmallVector<SDValue, 8> Ops;
1162 const MCInstrDesc &MCID = TII->get(IntrinsicWithPred);
1163 const TargetRegisterInfo *TRI = TM.getRegisterInfo();
1164
1165 // Iterate over all the operands of the intrinsics.
1166 // For PredRegs, do the transfer.
1167 // For Double/Int Regs, just preserve the value
1168 // For immediates, lower it.
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 // Do the transfer.
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 && (dyn_cast<ConstantSDNode>(Arg) != NULL)) {
1182 // This is immediate operand. Lower it here making sure that we DO have
1183 // const SDNode for immediate value.
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");
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 // Map floating point constant values.
1203 //
SelectConstantFP(SDNode * N)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 // Map predicate true (encoded as -1 in LLVM) to a XOR.
1223 //
SelectConstant(SDNode * N)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 // Create the IntReg = 1 node.
1231 SDNode* IntRegTFR =
1232 CurDAG->getMachineNode(Hexagon::TFRI, dl, MVT::i32,
1233 CurDAG->getTargetConstant(0, MVT::i32));
1234
1235 // Pd = IntReg
1236 SDNode* Pd = CurDAG->getMachineNode(Hexagon::TFR_PdRs, dl, MVT::i1,
1237 SDValue(IntRegTFR, 0));
1238
1239 // not(Pd)
1240 SDNode* NotPd = CurDAG->getMachineNode(Hexagon::NOT_p, dl, MVT::i1,
1241 SDValue(Pd, 0));
1242
1243 // xor(not(Pd))
1244 Result = CurDAG->getMachineNode(Hexagon::XOR_pp, dl, MVT::i1,
1245 SDValue(Pd, 0), SDValue(NotPd, 0));
1246
1247 // We have just built:
1248 // Rs = Pd
1249 // Pd = xor(not(Pd), Pd)
1250
1251 ReplaceUses(N, Result);
1252 return Result;
1253 }
1254 }
1255
1256 return SelectCode(N);
1257 }
1258
1259
1260 //
1261 // Map add followed by a asr -> asr +=.
1262 //
SelectAdd(SDNode * N)1263 SDNode *HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
1264 DebugLoc dl = N->getDebugLoc();
1265 if (N->getValueType(0) != MVT::i32) {
1266 return SelectCode(N);
1267 }
1268 // Identify nodes of the form: add(asr(...)).
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 // Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
1276 // Rd and Rd' are assigned to the same register
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
Select(SDNode * N)1287 SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
1288 if (N->isMachineOpcode())
1289 return NULL; // Already selected.
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 // Hexagon_TODO: Five functions for ADDRri?! Surely there must be a better way
1333 // to define these instructions.
1334 //
SelectADDRri(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriS11_0(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriS11_1(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriS11_2(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriU6_0(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriU6_1(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRriU6_2(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectMEMriS11_2(SDValue & Addr,SDValue & Base,SDValue & Offset)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
SelectADDRriS11_3(SDValue & Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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
SelectADDRrr(SDValue & Addr,SDValue & R1,SDValue & R2)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; // Direct calls.
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; // Let the reg+imm pattern catch this!
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 // Handle generic address case. It is accessed from inlined asm =m constraints,
1504 // which could have any kind of pointer.
SelectAddr(SDNode * Op,SDValue Addr,SDValue & Base,SDValue & Offset)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; // Direct calls.
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::
SelectInlineAsmMemoryOperand(const SDValue & Op,char ConstraintCode,std::vector<SDValue> & OutOps)1530 SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode,
1531 std::vector<SDValue> &OutOps) {
1532 SDValue Op0, Op1;
1533
1534 switch (ConstraintCode) {
1535 case 'o': // Offsetable.
1536 case 'v': // Not offsetable.
1537 default: return true;
1538 case 'm': // Memory.
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
isConstExtProfitable(SDNode * N) const1549 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 // Return 'true' if use count of the global address is below threshold.
1561 //===--------------------------------------------------------------------===//
hasNumUsesBelowThresGA(SDNode * N) const1562 bool HexagonDAGToDAGISel::hasNumUsesBelowThresGA(SDNode *N) const {
1563 assert(N->getOpcode() == ISD::TargetGlobalAddress &&
1564 "Expecting a target global address");
1565
1566 // Always try to fold the address.
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 // Return true if the non GP-relative global address can be folded.
1582 //===--------------------------------------------------------------------===//
foldGlobalAddress(SDValue & N,SDValue & R)1583 inline bool HexagonDAGToDAGISel::foldGlobalAddress(SDValue &N, SDValue &R) {
1584 return foldGlobalAddressImpl(N, R, false);
1585 }
1586
1587 //===--------------------------------------------------------------------===//
1588 // Return true if the GP-relative global address can be folded.
1589 //===--------------------------------------------------------------------===//
foldGlobalAddressGP(SDValue & N,SDValue & R)1590 inline bool HexagonDAGToDAGISel::foldGlobalAddressGP(SDValue &N, SDValue &R) {
1591 return foldGlobalAddressImpl(N, R, true);
1592 }
1593
1594 //===--------------------------------------------------------------------===//
1595 // Fold offset of the global address if number of uses are below threshold.
1596 //===--------------------------------------------------------------------===//
foldGlobalAddressImpl(SDValue & N,SDValue & R,bool ShouldLookForGP)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 }
1624