LLVM: lib/Target/Hexagon/HexagonISelDAGToDAG.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
22#include "llvm/IR/IntrinsicsHexagon.h"
25using namespace llvm;
26
27#define DEBUG_TYPE "hexagon-isel"
28#define PASS_NAME "Hexagon DAG->DAG Pattern Instruction Selection"
29
30static
33 cl::desc("Rebalance address calculation trees to improve "
34 "instruction selection"));
35
36
37
38static
41 cl::desc("Rebalance address tree only if this allows optimizations"));
42
43static
46 cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"));
47
49 cl::init(true), cl::desc("Enable checking of SDNode's single-use status"));
50
51
52
53
54
55#define GET_DAGISEL_BODY HexagonDAGToDAGISel
56#include "HexagonGenDAGISel.inc"
57
58namespace llvm {
59
60
65}
66
71
73
75
77 SDValue Chain = LD->getChain();
81 EVT LoadedVT = LD->getMemoryVT();
82 unsigned Opcode = 0;
83
84
85
88 bool IsValidInc = HII->isValidAutoIncImm(LoadedVT, Inc);
89
92 case MVT::i8:
93 if (IsZeroExt)
94 Opcode = IsValidInc ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrub_io;
95 else
96 Opcode = IsValidInc ? Hexagon::L2_loadrb_pi : Hexagon::L2_loadrb_io;
97 break;
98 case MVT::i16:
99 if (IsZeroExt)
100 Opcode = IsValidInc ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadruh_io;
101 else
102 Opcode = IsValidInc ? Hexagon::L2_loadrh_pi : Hexagon::L2_loadrh_io;
103 break;
104 case MVT::i32:
105 case MVT::f32:
106 case MVT::v2i16:
107 case MVT::v4i8:
108 Opcode = IsValidInc ? Hexagon::L2_loadri_pi : Hexagon::L2_loadri_io;
109 break;
110 case MVT::i64:
111 case MVT::f64:
112 case MVT::v2i32:
113 case MVT::v4i16:
114 case MVT::v8i8:
115 Opcode = IsValidInc ? Hexagon::L2_loadrd_pi : Hexagon::L2_loadrd_io;
116 break;
117 case MVT::v64i8:
118 case MVT::v32i16:
119 case MVT::v16i32:
120 case MVT::v8i64:
121 case MVT::v128i8:
122 case MVT::v64i16:
123 case MVT::v32i32:
124 case MVT::v16i64:
125 if (isAlignedMemNode(LD)) {
126 if (LD->isNonTemporal())
127 Opcode = IsValidInc ? Hexagon::V6_vL32b_nt_pi : Hexagon::V6_vL32b_nt_ai;
128 else
129 Opcode = IsValidInc ? Hexagon::V6_vL32b_pi : Hexagon::V6_vL32b_ai;
130 } else {
131 Opcode = IsValidInc ? Hexagon::V6_vL32Ub_pi : Hexagon::V6_vL32Ub_ai;
132 }
133 break;
134 default:
136 }
137
138 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
140
144 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
145 return CurDAG->getMachineNode(Hexagon::A4_combineir, dl, MVT::i64,
147 }
149 return CurDAG->getMachineNode(Hexagon::A2_sxtw, dl, MVT::i64,
151 return N;
152 };
153
154
157
158 EVT ValueVT = LD->getValueType(0);
160
161
163 ValueVT = MVT::i32;
164 }
165
166 if (IsValidInc) {
168 MVT::i32, MVT::Other, Base,
169 IncV, Chain);
171 To[1] = SDValue(L, 1);
172 To[2] = SDValue(L, 2);
173
174 if (LD->getValueType(0) == MVT::i64)
175 L = getExt64(L, dl);
176 To[0] = SDValue(L, 0);
177 } else {
178 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
179 MachineSDNode *L = CurDAG->getMachineNode(Opcode, dl, ValueVT, MVT::Other,
180 Base, Zero, Chain);
182 To[2] = SDValue(L, 1);
186
187 if (LD->getValueType(0) == MVT::i64)
188 L = getExt64(L, dl);
189 To[0] = SDValue(L, 0);
190 }
192 CurDAG->RemoveDeadNode(LD);
193}
194
197 return nullptr;
198
201
202 static std::map<unsigned,unsigned> LoadPciMap = {
203 { Intrinsic::hexagon_circ_ldb, Hexagon::L2_loadrb_pci },
204 { Intrinsic::hexagon_circ_ldub, Hexagon::L2_loadrub_pci },
205 { Intrinsic::hexagon_circ_ldh, Hexagon::L2_loadrh_pci },
206 { Intrinsic::hexagon_circ_lduh, Hexagon::L2_loadruh_pci },
207 { Intrinsic::hexagon_circ_ldw, Hexagon::L2_loadri_pci },
208 { Intrinsic::hexagon_circ_ldd, Hexagon::L2_loadrd_pci },
209 };
210 auto FLC = LoadPciMap.find(IntNo);
211 if (FLC != LoadPciMap.end()) {
212 EVT ValTy = (IntNo == Intrinsic::hexagon_circ_ldd) ? MVT::i64 : MVT::i32;
213 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
214
217 CurDAG->getSignedTargetConstant(Inc->getSExtValue(), dl, MVT::i32);
219 { IntN->getOperand(2), I, IntN->getOperand(4),
220 IntN->getOperand(0) });
221 return Res;
222 }
223
224 return nullptr;
225}
226
229
230
231
235 unsigned Size = 1U << (SizeBits-1);
236
241
242 if (Size >= 4)
245 else
248
250 {
254 }
255
256
259 return StoreN;
260}
261
263
264
265
266
267
268
269
270
271
272
273
274
275
276 SDValue Ch = N->getOperand(0);
278
279
280
281
282
284
286 return false;
287
288
289
290
291
293 switch (C->getConstantOperandVal(1)) {
294 case Intrinsic::hexagon_circ_ldub:
295 case Intrinsic::hexagon_circ_lduh:
297 break;
298 case Intrinsic::hexagon_circ_ldw:
299 case Intrinsic::hexagon_circ_ldd:
301 break;
302 default:
304 break;
305 }
306 if (N->getExtensionType() != IntExt)
307 return false;
308
309
310
311 if (C->getNumOperands() < 4 || Loc.getNode() != C->getOperand(3).getNode())
312 return false;
313
319
320
321
322 CurDAG->RemoveDeadNode(C);
323 return true;
324 }
325 return false;
326}
327
328
331 return false;
332
333 const SDLoc &dl(IntN);
335
336 static const std::map<unsigned, unsigned> LoadBrevMap = {
337 { Intrinsic::hexagon_L2_loadrb_pbr, Hexagon::L2_loadrb_pbr },
338 { Intrinsic::hexagon_L2_loadrub_pbr, Hexagon::L2_loadrub_pbr },
339 { Intrinsic::hexagon_L2_loadrh_pbr, Hexagon::L2_loadrh_pbr },
340 { Intrinsic::hexagon_L2_loadruh_pbr, Hexagon::L2_loadruh_pbr },
341 { Intrinsic::hexagon_L2_loadri_pbr, Hexagon::L2_loadri_pbr },
342 { Intrinsic::hexagon_L2_loadrd_pbr, Hexagon::L2_loadrd_pbr }
343 };
344 auto FLI = LoadBrevMap.find(IntNo);
345 if (FLI != LoadBrevMap.end()) {
346 EVT ValTy =
347 (IntNo == Intrinsic::hexagon_L2_loadrd_pbr) ? MVT::i64 : MVT::i32;
348 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
349
350
351
353 FLI->second, dl, RTys,
354 {IntN->getOperand(2), IntN->getOperand(3), IntN->getOperand(0)});
355
358
362 CurDAG->RemoveDeadNode(IntN);
363 return true;
364 }
365 return false;
366}
367
368
369
372 return false;
373
377
378 static std::map<unsigned,unsigned> LoadNPcMap = {
379 { Intrinsic::hexagon_L2_loadrub_pci, Hexagon::PS_loadrub_pci },
380 { Intrinsic::hexagon_L2_loadrb_pci, Hexagon::PS_loadrb_pci },
381 { Intrinsic::hexagon_L2_loadruh_pci, Hexagon::PS_loadruh_pci },
382 { Intrinsic::hexagon_L2_loadrh_pci, Hexagon::PS_loadrh_pci },
383 { Intrinsic::hexagon_L2_loadri_pci, Hexagon::PS_loadri_pci },
384 { Intrinsic::hexagon_L2_loadrd_pci, Hexagon::PS_loadrd_pci },
385 { Intrinsic::hexagon_L2_loadrub_pcr, Hexagon::PS_loadrub_pcr },
386 { Intrinsic::hexagon_L2_loadrb_pcr, Hexagon::PS_loadrb_pcr },
387 { Intrinsic::hexagon_L2_loadruh_pcr, Hexagon::PS_loadruh_pcr },
388 { Intrinsic::hexagon_L2_loadrh_pcr, Hexagon::PS_loadrh_pcr },
389 { Intrinsic::hexagon_L2_loadri_pcr, Hexagon::PS_loadri_pcr },
390 { Intrinsic::hexagon_L2_loadrd_pcr, Hexagon::PS_loadrd_pcr }
391 };
392 auto FLI = LoadNPcMap.find (IntNo);
393 if (FLI != LoadNPcMap.end()) {
394 EVT ValTy = MVT::i32;
395 if (IntNo == Intrinsic::hexagon_L2_loadrd_pci ||
396 IntNo == Intrinsic::hexagon_L2_loadrd_pcr)
397 ValTy = MVT::i64;
398 EVT RTys[] = { ValTy, MVT::i32, MVT::Other };
399
402 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
403
406 } else
407
408
415 CurDAG->RemoveDeadNode(IntN);
416 return true;
417 }
418
419 static std::map<unsigned,unsigned> StoreNPcMap = {
420 { Intrinsic::hexagon_S2_storerb_pci, Hexagon::PS_storerb_pci },
421 { Intrinsic::hexagon_S2_storerh_pci, Hexagon::PS_storerh_pci },
422 { Intrinsic::hexagon_S2_storerf_pci, Hexagon::PS_storerf_pci },
423 { Intrinsic::hexagon_S2_storeri_pci, Hexagon::PS_storeri_pci },
424 { Intrinsic::hexagon_S2_storerd_pci, Hexagon::PS_storerd_pci },
425 { Intrinsic::hexagon_S2_storerb_pcr, Hexagon::PS_storerb_pcr },
426 { Intrinsic::hexagon_S2_storerh_pcr, Hexagon::PS_storerh_pcr },
427 { Intrinsic::hexagon_S2_storerf_pcr, Hexagon::PS_storerf_pcr },
428 { Intrinsic::hexagon_S2_storeri_pcr, Hexagon::PS_storeri_pcr },
429 { Intrinsic::hexagon_S2_storerd_pcr, Hexagon::PS_storerd_pcr }
430 };
431 auto FSI = StoreNPcMap.find (IntNo);
432 if (FSI != StoreNPcMap.end()) {
433 EVT RTys[] = { MVT::i32, MVT::Other };
434
437 SDValue I = CurDAG->getTargetConstant(Inc->getSExtValue(), DL, MVT::i32);
438
441 } else
442
443
449 CurDAG->RemoveDeadNode(IntN);
450 return true;
451 }
452
453 return false;
454}
455
459
460
464 return;
465 }
466
467
469 return;
470
471 SelectCode(LD);
472}
473
475 SDValue Chain = ST->getChain();
479
481 EVT StoredVT = ST->getMemoryVT();
482 EVT ValueVT = Value.getValueType();
483
484 bool IsValidInc = HII->isValidAutoIncImm(StoredVT, Inc);
485 unsigned Opcode = 0;
486
489 case MVT::i8:
490 Opcode = IsValidInc ? Hexagon::S2_storerb_pi : Hexagon::S2_storerb_io;
491 break;
492 case MVT::i16:
493 Opcode = IsValidInc ? Hexagon::S2_storerh_pi : Hexagon::S2_storerh_io;
494 break;
495 case MVT::i32:
496 case MVT::f32:
497 case MVT::v2i16:
498 case MVT::v4i8:
499 Opcode = IsValidInc ? Hexagon::S2_storeri_pi : Hexagon::S2_storeri_io;
500 break;
501 case MVT::i64:
502 case MVT::f64:
503 case MVT::v2i32:
504 case MVT::v4i16:
505 case MVT::v8i8:
506 Opcode = IsValidInc ? Hexagon::S2_storerd_pi : Hexagon::S2_storerd_io;
507 break;
508 case MVT::v64i8:
509 case MVT::v32i16:
510 case MVT::v16i32:
511 case MVT::v8i64:
512 case MVT::v128i8:
513 case MVT::v64i16:
514 case MVT::v32i32:
515 case MVT::v16i64:
516 if (isAlignedMemNode(ST)) {
517 if (ST->isNonTemporal())
518 Opcode = IsValidInc ? Hexagon::V6_vS32b_nt_pi : Hexagon::V6_vS32b_nt_ai;
519 else
520 Opcode = IsValidInc ? Hexagon::V6_vS32b_pi : Hexagon::V6_vS32b_ai;
521 } else {
522 Opcode = IsValidInc ? Hexagon::V6_vS32Ub_pi : Hexagon::V6_vS32Ub_ai;
523 }
524 break;
525 default:
527 }
528
529 if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
531 Value = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo,
532 dl, MVT::i32, Value);
533 }
534
535 SDValue IncV = CurDAG->getSignedTargetConstant(Inc, dl, MVT::i32);
537
538
541
542 if (IsValidInc) {
543
545 MachineSDNode *S = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::Other,
550 } else {
551 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
559 }
560
562 CurDAG->RemoveDeadNode(ST);
563}
564
568
569
573 return;
574 }
575
576 SelectCode(ST);
577}
578
581 SDValue Shl_0 = N->getOperand(0);
582 SDValue Shl_1 = N->getOperand(1);
583
584 auto Default = [this,N] () -> void { SelectCode(N); };
585
588
589
591
595
597 int32_t ValConst = C->getSExtValue() << ShlConst;
599 SDValue Val = CurDAG->getTargetConstant(ValConst, dl, MVT::i32);
600 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
601 MVT::i32, Mul_0, Val);
603 return;
604 }
605 }
607 }
608
618 int32_t ValConst = 1 << (ShlConst + C2->getSExtValue());
621 CurDAG->getSignedTargetConstant(-ValConst, dl, MVT::i32);
622 SDNode *Result = CurDAG->getMachineNode(Hexagon::M2_mpysmi, dl,
623 MVT::i32, Shl2_0, Val);
625 return;
626 }
627 }
628 }
629 }
630
632}
633
634
635
636
640 CurDAG->RemoveDeadNode(N);
641 return;
642 }
643
644
646 return;
647
649 return;
650
651 unsigned IntNo = N->getConstantOperandVal(1);
652 if (IntNo == Intrinsic::hexagon_V6_vgathermw ||
653 IntNo == Intrinsic::hexagon_V6_vgathermw_128B ||
654 IntNo == Intrinsic::hexagon_V6_vgathermh ||
655 IntNo == Intrinsic::hexagon_V6_vgathermh_128B ||
656 IntNo == Intrinsic::hexagon_V6_vgathermhw ||
657 IntNo == Intrinsic::hexagon_V6_vgathermhw_128B ||
658 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh ||
659 IntNo == Intrinsic::hexagon_V6_vgather_vscattermh_128B) {
661 return;
662 }
663 if (IntNo == Intrinsic::hexagon_V6_vgathermwq ||
664 IntNo == Intrinsic::hexagon_V6_vgathermwq_128B ||
665 IntNo == Intrinsic::hexagon_V6_vgathermhq ||
666 IntNo == Intrinsic::hexagon_V6_vgathermhq_128B ||
667 IntNo == Intrinsic::hexagon_V6_vgathermhwq ||
668 IntNo == Intrinsic::hexagon_V6_vgathermhwq_128B) {
670 return;
671 }
672
673 SelectCode(N);
674}
675
677 unsigned IID = N->getConstantOperandVal(0);
678 unsigned Bits;
679 switch (IID) {
680 case Intrinsic::hexagon_S2_vsplatrb:
681 Bits = 8;
682 break;
683 case Intrinsic::hexagon_S2_vsplatrh:
684 Bits = 16;
685 break;
686 case Intrinsic::hexagon_V6_vaddcarry:
687 case Intrinsic::hexagon_V6_vaddcarry_128B:
688 case Intrinsic::hexagon_V6_vsubcarry:
689 case Intrinsic::hexagon_V6_vsubcarry_128B:
691 return;
692 default:
693 SelectCode(N);
694 return;
695 }
696
697 SDValue V = N->getOperand(1);
699
700 if (keepsLowBits(V, Bits, U)) {
702 N->getOperand(0), U);
704 SelectCode(R.getNode());
705 return;
706 }
707 SelectCode(N);
708}
709
711 SDValue Inp = N->getOperand(0);
712 MVT ResTy = N->getValueType(0).getSimpleVT();
713 unsigned Idx = N->getConstantOperandVal(1);
714
720 assert(Idx == 0 || Idx == ResLen);
721
722 unsigned SubReg = Idx == 0 ? Hexagon::isub_lo : Hexagon::isub_hi;
724
726}
727
728
729
730
734 APInt A = CN->getValueAPF().bitcastToAPInt();
735 if (N->getValueType(0) == MVT::f32) {
736 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i32);
737 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, V));
738 return;
739 }
740 if (N->getValueType(0) == MVT::f64) {
741 SDValue V = CurDAG->getTargetConstant(A.getZExtValue(), dl, MVT::i64);
742 ReplaceNode(N, CurDAG->getMachineNode(Hexagon::CONST64, dl, MVT::f64, V));
743 return;
744 }
745
746 SelectCode(N);
747}
748
749
750
751
753 if (N->getValueType(0) == MVT::i1) {
754 assert(!(N->getAsZExtVal() >> 1));
756 ? Hexagon::PS_true
757 : Hexagon::PS_false;
759 return;
760 }
761
762 SelectCode(N);
763}
764
771 SDValue FI = CurDAG->getTargetFrameIndex(FX, MVT::i32);
773 SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i32);
775
776
777
778
779
780
782 R = CurDAG->getMachineNode(Hexagon::PS_fi, DL, MVT::i32, FI, Zero);
783 } else {
785 Register AR = HMFI.getStackAlignBaseReg();
788 R = CurDAG->getMachineNode(Hexagon::PS_fia, DL, MVT::i32, Ops);
789 }
790
792}
793
795 unsigned OpcCarry = N->getOpcode() == HexagonISD::ADDC ? Hexagon::A4_addp_c
796 : Hexagon::A4_subp_c;
798 { N->getOperand(0), N->getOperand(1),
799 N->getOperand(2) });
801}
802
804 MVT ResTy = N->getValueType(0).getSimpleVT();
805 if (HST->isHVXVectorType(ResTy, true))
806 return SelectHvxVAlign(N);
807
810 if (VecLen == 32) {
812 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
813 N->getOperand(0),
814 CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
815 N->getOperand(1),
816 CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
817 };
818 SDNode *R = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
819 MVT::i64, Ops);
820
821
823 SDValue M0 = CurDAG->getTargetConstant(0x18, dl, MVT::i32);
824 SDValue M1 = CurDAG->getTargetConstant(0x03, dl, MVT::i32);
825 if (HST->useCompound()) {
826 C = CurDAG->getMachineNode(Hexagon::S4_andi_asl_ri, dl, MVT::i32,
827 M0, N->getOperand(2), M1);
828 } else {
829 SDNode *T = CurDAG->getMachineNode(Hexagon::S2_asl_i_r, dl, MVT::i32,
831 C = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
833 }
834 SDNode *S = CurDAG->getMachineNode(Hexagon::S2_lsr_r_p, dl, MVT::i64,
836 SDValue E = CurDAG->getTargetExtractSubreg(Hexagon::isub_lo, dl, ResTy,
839 } else {
840 assert(VecLen == 64);
841 SDNode *Pu = CurDAG->getMachineNode(Hexagon::C2_tfrrp, dl, MVT::v8i1,
842 N->getOperand(2));
843 SDNode *VA = CurDAG->getMachineNode(Hexagon::S2_valignrb, dl, ResTy,
844 N->getOperand(0), N->getOperand(1),
847 }
848}
849
855
856 SDValue M = CurDAG->getTargetConstant(Mask, dl, MVT::i32);
857 SDNode *AA = CurDAG->getMachineNode(Hexagon::A2_andir, dl, MVT::i32,
858 N->getOperand(0), M);
860}
861
862
863
864
867 MVT OpTy = Op.getValueType().getSimpleVT();
869 CurDAG->getVTList(OpTy), {Op});
871}
872
874 MVT ResTy = N->getValueType(0).getSimpleVT();
876 N->getOperand(0));
878}
879
882 MVT ResTy = N->getValueType(0).getSimpleVT();
883 SDValue Zero = CurDAG->getTargetConstant(0, dl, MVT::i32);
884 SDNode *T = CurDAG->getMachineNode(Hexagon::A4_vcmpbgtui, dl, ResTy,
885 N->getOperand(0), Zero);
887}
888
891 MVT ResTy = N->getValueType(0).getSimpleVT();
892
893 MVT OpTy = N->getOperand(0).getValueType().getSimpleVT(); (void)OpTy;
895
896 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
897 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
898 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandvrt, dl, ResTy,
899 N->getOperand(0), SDValue(R,0));
901}
902
905 MVT ResTy = N->getValueType(0).getSimpleVT();
906
908
909 SDValue C = CurDAG->getSignedTargetConstant(-1, dl, MVT::i32);
910 SDNode *R = CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::i32, C);
911 SDNode *T = CurDAG->getMachineNode(Hexagon::V6_vandqrt, dl, ResTy,
912 N->getOperand(0), SDValue(R,0));
914}
915
918 ArrayRef ResultType(N->value_begin(), N->value_end());
920 Ops = {N->getOperand(0), N->getOperand(1)};
922 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
923 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
924 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
925
926 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
928 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
929
930 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
931 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
934 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
937 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
941 Hexagon::A2_andir, dl, MVT::f32, SDValue(n, 0),
942 CurDAG->getTargetConstant(0x80000000, dl, MVT::i32));
944 CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(q, 0),
947 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
950 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
952 SDNode *NNewQ = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
955
957 CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32, SDValue(n, 0),
959 std::array<SDValue, 4> temp1 = {SDValue(NNewQ, 0), SDValue(NqErr, 0),
963 CurDAG->getMachineNode(Hexagon::F2_sffma_sc, dl, MVT::f32, OpValue1);
965}
966
969 ArrayRef ResultType(N->value_begin(), N->value_end());
971 Ops = {N->getOperand(0), N->getOperand(1)};
973 VTs = CurDAG->getVTList(MVT::f32, MVT::f32);
974 SDNode *ResScale = CurDAG->getMachineNode(Hexagon::F2_sfrecipa, dl, VTs, Ops);
975 SDNode *D = CurDAG->getMachineNode(Hexagon::F2_sffixupd, dl, MVT::f32, Ops);
976
977 SDValue C = CurDAG->getTargetConstant(0x3f800000, dl, MVT::i32);
979 CurDAG->getMachineNode(Hexagon::A2_tfrsi, dl, MVT::f32, C);
980
981 SDNode *n = CurDAG->getMachineNode(Hexagon::F2_sffixupn, dl, MVT::f32, Ops);
982 SDNode *Err = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
985 SDNode *NewRec = CurDAG->getMachineNode(Hexagon::F2_sffma_lib, dl, MVT::f32,
988 SDNode *newErr = CurDAG->getMachineNode(Hexagon::F2_sffms_lib, dl, MVT::f32,
991
993 Hexagon::F2_sffma_lib, dl, MVT::f32, SDValue(NewRec, 0),
996 Hexagon::F2_sfmpy, dl, MVT::f32, SDValue(NNewRec, 0), SDValue(n, 0));
998}
999
1001 if (N->getFlags().hasAllowReassociation())
1003 else
1005}
1006
1008 if (N->isMachineOpcode())
1009 return N->setNodeId(-1);
1010
1011 auto isHvxOp = [this](SDNode *N) {
1012 for (unsigned i = 0, e = N->getNumValues(); i != e; ++i) {
1013 if (HST->isHVXVectorType(N->getValueType(i), true))
1014 return true;
1015 }
1017 if (HST->isHVXVectorType(I.getValueType(), true))
1018 return true;
1019 }
1020 return false;
1021 };
1022
1023 if (HST->useHVXOps() && isHvxOp(N)) {
1024 switch (N->getOpcode()) {
1027
1029 }
1030 }
1031
1032 switch (N->getOpcode()) {
1042
1054 }
1055
1056 SelectCode(N);
1057}
1058
1061 std::vector &OutOps) {
1063
1064 switch (ConstraintID) {
1065 default:
1066 return true;
1071 OutOps.push_back(Res);
1072 else
1073 OutOps.push_back(Inp);
1074 break;
1075 }
1076
1077 OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32));
1078 return false;
1079}
1080
1082
1083
1084
1085
1086 if (!U->hasOneUse())
1087 return false;
1088 unsigned Opc = U->getOpcode();
1089 switch (Opc) {
1094 break;
1095 default:
1096 return false;
1097 }
1098
1102
1105 return false;
1106
1107
1108
1109
1110
1111 SDNode *SYNode = SY.getNode();
1112 if (UUse->getOpcode() == ISD::STORE && SYNode->getOpcode() == ISD::LOAD) {
1115 if (LDBasePtr == STBasePtr)
1116 return true;
1117 }
1118 return false;
1119}
1120
1121
1122
1123
1124void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
1125 SelectionDAG &DAG = *CurDAG;
1126
1127 for (auto *I : Nodes) {
1128 if (I->getOpcode() != ISD::OR)
1129 continue;
1130
1131 auto IsSelect0 = [](const SDValue &Op) -> bool {
1133 return false;
1136 };
1137
1138 SDValue N0 = I->getOperand(0), N1 = I->getOperand(1);
1139 EVT VT = I->getValueType(0);
1140 bool SelN0 = IsSelect0(N0);
1141 SDValue SOp = SelN0 ? N0 : N1;
1142 SDValue VOp = SelN0 ? N1 : N0;
1143
1148 SDLoc DLS = SOp;
1157 }
1158 }
1159 }
1160}
1161
1162
1163
1164
1165
1166
1167
1168void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
1169 SelectionDAG &DAG = *CurDAG;
1170
1171 for (auto *I : Nodes) {
1172 if (I->getOpcode() != ISD::STORE)
1173 continue;
1174
1175
1177
1179 continue;
1180
1182
1184 continue;
1185
1188
1190 continue;
1193 if (CN == nullptr)
1194 continue;
1196 if (CV > 2)
1197 continue;
1198
1200 if (EN == nullptr)
1201 continue;
1203 if (EV % (1 << CV) != 0)
1204 continue;
1205 unsigned DV = EV / (1 << CV);
1206
1207
1211
1213
1216 }
1217}
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
1233 SelectionDAG &DAG = *CurDAG;
1234
1235 for (SDNode *N : Nodes) {
1236 unsigned Opc = N->getOpcode();
1237 if (Opc != ISD::LOAD && Opc != ISD::STORE)
1238 continue;
1239 SDValue Addr = Opc == ISD::LOAD ? N->getOperand(1) : N->getOperand(2);
1240
1242 continue;
1244
1246 continue;
1247
1248
1249
1250
1253 continue;
1255 if (SN == nullptr)
1256 continue;
1258 continue;
1260
1261
1263 if (MN == nullptr)
1264 continue;
1266 continue;
1268
1272
1273 if (TZ + M1 + LZ != 32)
1274 continue;
1275
1276 if (TZ > 2)
1277 continue;
1278
1279 if (LZ > CV)
1280 continue;
1281
1282
1285 SDLoc dl(S);
1286
1292 }
1293}
1294
1295
1296
1297void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
1298 SelectionDAG &DAG = *CurDAG;
1299
1300 for (SDNode *N : Nodes) {
1301 unsigned Opc = N->getOpcode();
1303 continue;
1304 SDValue OpI1 = N->getOperand(0);
1307 continue;
1308 for (SDUse &Use : N->uses()) {
1309 SDNode *U = Use.getUser();
1310 if (U->getNumValues() != 1)
1311 continue;
1312 EVT UVT = U->getValueType(0);
1314 continue;
1315
1317 continue;
1319 continue;
1320
1321
1322 unsigned I1N = Use.getOperandNo();
1324 for (unsigned i = 0, n = U->getNumOperands(); i != n; ++i)
1325 Ops[i] = U->getOperand(i);
1326 EVT BVT = Ops[I1N].getValueType();
1327
1328 const SDLoc &dl(U);
1332
1334 unsigned UseOpc = U->getMachineOpcode();
1335 Ops[I1N] = C0;
1337 Ops[I1N] = C1;
1339 } else {
1340 unsigned UseOpc = U->getOpcode();
1341 Ops[I1N] = C0;
1342 If0 = DAG.getNode(UseOpc, dl, UVT, Ops);
1343 Ops[I1N] = C1;
1344 If1 = DAG.getNode(UseOpc, dl, UVT, Ops);
1345 }
1346
1347
1355 }
1356 }
1357}
1358
1360
1361
1362 auto getNodes = [this]() -> std::vector<SDNode *> {
1363 std::vector<SDNode *> T;
1364 T.reserve(CurDAG->allnodes_size());
1367 return T;
1368 };
1369
1370 if (HST->useHVXOps())
1371 PreprocessHvxISelDAG();
1372
1373
1374
1375 ppSimplifyOrSelect0(getNodes());
1376
1377
1378
1379
1380
1381
1382
1383 ppAddrReorderAddShl(getNodes());
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398 ppAddrRewriteAndSrl(getNodes());
1399
1400
1401
1402 ppHoistZextI1(getNodes());
1403
1405 dbgs() << "Preprocessed (Hexagon) selection DAG:";
1407 });
1408
1410 rebalanceAddressTrees();
1411
1413 dbgs() << "Address tree balanced selection DAG:";
1415 });
1416 }
1417}
1418
1422 if (!HFI.needsAligna(*MF))
1423 return;
1424
1428
1429
1431 auto &HRI = *HST.getRegisterInfo();
1433 for (const MCPhysReg *R = HRI.getCalleeSavedRegs(MF); *R; ++R) {
1435 continue;
1436 AP = *R;
1437 break;
1438 }
1439 assert(AP.isValid() && "Couldn't reserve stack align register");
1440 BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::PS_aligna), AP)
1443}
1444
1445void HexagonDAGToDAGISel::updateAligna() {
1447 if (!HFI.needsAligna(*MF))
1448 return;
1449 auto *AlignaI = const_cast<MachineInstr*>(HFI.getAlignaInstr(*MF));
1450 assert(AlignaI != nullptr);
1452 if (AlignaI->getOperand(1).getImm() < MaxA)
1453 AlignaI->getOperand(1).setImm(MaxA);
1454}
1455
1456
1459 return false;
1460 auto &HFI = *HST->getFrameLowering();
1464 return false;
1465 R = CurDAG->getTargetFrameIndex(FX, MVT::i32);
1466 return true;
1467}
1468
1472
1476
1480
1493
1495 EVT T = N.getValueType();
1497 return false;
1499 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1500 return true;
1501}
1502
1504 Align Alignment) {
1505 switch (N.getOpcode()) {
1507 if (N.getValueType() != MVT::i32)
1508 return false;
1511 return false;
1512 R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
1513 return true;
1514 }
1517
1518 if (Alignment > Align(8))
1519 return false;
1520 R = N.getOperand(0);
1521 return true;
1523
1524 if (Alignment > Align(1))
1525 return false;
1526 R = N;
1527 return true;
1529
1530 if (Alignment > Align(4) ||
1532 return false;
1533 R = N;
1534 return true;
1535 }
1536
1539 return true;
1540
1541 return false;
1542}
1543
1545 bool UseGP, Align Alignment) {
1546 switch (N.getOpcode()) {
1548 SDValue N0 = N.getOperand(0);
1549 SDValue N1 = N.getOperand(1);
1550 unsigned GAOpc = N0.getOpcode();
1552 return false;
1554 return false;
1556 if ((Alignment, Const->getZExtValue()))
1557 return false;
1561 uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
1562 R = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(Const),
1563 N.getValueType(), NewOff);
1564 return true;
1565 }
1566 }
1567 }
1568 break;
1569 }
1573
1574
1575 if (!UseGP)
1576 R = N.getOperand(0);
1577 return !UseGP;
1579 if (UseGP)
1580 R = N.getOperand(0);
1581 return UseGP;
1582 default:
1583 return false;
1584 }
1585
1586 return false;
1587}
1588
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608 if (N.getValueType() != MVT::i64)
1609 return false;
1610 unsigned Opc = N.getOpcode();
1611 switch (Opc) {
1614
1616 ? N.getOperand(0).getValueType()
1618 unsigned SW = T.getSizeInBits();
1619 if (SW == 32)
1620 R = N.getOperand(0);
1621 else if (SW < 32)
1622 R = N;
1623 else
1624 return false;
1625 break;
1626 }
1627 case ISD::LOAD: {
1630 return false;
1631
1632
1633 if (L->getMemoryVT().getSizeInBits() > 32)
1634 return false;
1635 R = N;
1636 break;
1637 }
1640 if (!S || S->getZExtValue() != 32)
1641 return false;
1642 R = N;
1643 break;
1644 }
1647 if (T.getSizeInBits() == 32)
1648 R = N.getOperand(0);
1649 else
1650 return false;
1651 break;
1652 }
1653
1654 default:
1655 return false;
1656 }
1657 EVT RT = R.getValueType();
1658 if (RT == MVT::i64)
1659 return true;
1660 assert(RT == MVT::i32);
1661
1662
1665 CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID, dl, MVT::i32),
1666 R, CurDAG->getTargetConstant(Hexagon::isub_hi, dl, MVT::i32),
1667 R, CurDAG->getTargetConstant(Hexagon::isub_lo, dl, MVT::i32)
1668 };
1669 SDNode *T = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, dl,
1670 MVT::i64, Ops);
1672 return true;
1673}
1674
1675bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
1678 switch (Opc) {
1684 if (T.isInteger() && T.getSizeInBits() == NumBits) {
1685 Src = Op0;
1686 return true;
1687 }
1688 break;
1689 }
1695 if (T->getVT().getSizeInBits() == NumBits) {
1697 return true;
1698 }
1699 }
1700 break;
1702
1703 uint64_t Mask = (1ULL << NumBits) - 1;
1705 if (C->getZExtValue() == Mask) {
1707 return true;
1708 }
1709 }
1711 if (C->getZExtValue() == Mask) {
1713 return true;
1714 }
1715 }
1716 break;
1717 }
1720
1721 uint64_t Mask = (1ULL << NumBits) - 1;
1723 if ((C->getZExtValue() & Mask) == 0) {
1725 return true;
1726 }
1727 }
1729 if ((C->getZExtValue() & Mask) == 0) {
1731 return true;
1732 }
1733 }
1734 break;
1735 }
1736 default:
1737 break;
1738 }
1739 return false;
1740}
1741
1742bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
1743 return N->getAlign().value() >= N->getMemoryVT().getStoreSize();
1744}
1745
1746bool HexagonDAGToDAGISel::isSmallStackStore(const StoreSDNode *N) const {
1747 unsigned StackSize = MF->getFrameInfo().estimateStackSize(*MF);
1748 switch (N->getMemoryVT().getStoreSize()) {
1749 case 1:
1750 return StackSize <= 56;
1751 case 2:
1752 return StackSize <= 120;
1753 case 4:
1754 return StackSize <= 248;
1755 default:
1756 return false;
1757 }
1758}
1759
1760
1761bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {
1765 }
1769 }
1770 return false;
1771}
1772
1773bool HexagonDAGToDAGISel::hasOneUse(const SDNode *N) const {
1775}
1776
1777
1778
1779
1781 switch (N->getOpcode()) {
1784 return true;
1786
1787
1789 default:
1790 return false;
1791 }
1792}
1793
1794
1795int HexagonDAGToDAGISel::getWeight(SDNode *N) {
1797 return 1;
1798 assert(RootWeights.count(N) && "Cannot get weight of unseen root!");
1799 assert(RootWeights[N] != -1 && "Cannot get weight of unvisited root!");
1800 assert(RootWeights[N] != -2 && "Cannot get weight of RAWU'd root!");
1801 return RootWeights[N];
1802}
1803
1804int HexagonDAGToDAGISel::getHeight(SDNode *N) {
1806 return 0;
1807 assert(RootWeights.count(N) && RootWeights[N] >= 0 &&
1808 "Cannot query height of unvisited/RAUW'd node!");
1809 return RootHeights[N];
1810}
1811
1812namespace {
1813struct WeightedLeaf {
1815 int Weight;
1816 int InsertionOrder;
1817
1818 WeightedLeaf() = default;
1819
1820 WeightedLeaf(SDValue Value, int Weight, int InsertionOrder) :
1821 Value(Value), Weight(Weight), InsertionOrder(InsertionOrder) {
1822 assert(Weight >= 0 && "Weight must be >= 0");
1823 }
1824
1825 static bool Compare(const WeightedLeaf &A, const WeightedLeaf &B) {
1826 assert(A.Value.getNode() && B.Value.getNode());
1827 return A.Weight == B.Weight ?
1828 (A.InsertionOrder > B.InsertionOrder) :
1830 }
1831};
1832
1833
1834
1835
1836class LeafPrioQueue {
1838 bool HaveConst;
1839 WeightedLeaf ConstElt;
1840 unsigned Opcode;
1841
1842public:
1844 return (!HaveConst && Q.empty());
1845 }
1846
1847 size_t size() {
1848 return Q.size() + HaveConst;
1849 }
1850
1851 bool hasConst() {
1852 return HaveConst;
1853 }
1854
1855 const WeightedLeaf &top() {
1856 if (HaveConst)
1857 return ConstElt;
1858 return Q.front();
1859 }
1860
1861 WeightedLeaf pop() {
1862 if (HaveConst) {
1863 HaveConst = false;
1864 return ConstElt;
1865 }
1866 std::pop_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1868 }
1869
1870 void push(WeightedLeaf L, bool SeparateConst=true) {
1874 return;
1877 return;
1878
1879 HaveConst = true;
1880 ConstElt = L;
1881 } else {
1883 std::push_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1884 }
1885 }
1886
1887
1888
1889 void pushToBottom(WeightedLeaf L) {
1890 L.Weight = 1000;
1891 push(L, false);
1892 }
1893
1894
1895
1896 WeightedLeaf findSHL(uint64_t MaxAmount);
1897
1898 WeightedLeaf findMULbyConst();
1899
1900 LeafPrioQueue(unsigned Opcode) :
1901 HaveConst(false), Opcode(Opcode) { }
1902};
1903}
1904
1905WeightedLeaf LeafPrioQueue::findSHL(uint64_t MaxAmount) {
1906 int ResultPos;
1907 WeightedLeaf Result;
1908
1909 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1910 const WeightedLeaf &L = Q[Pos];
1911 const SDValue &Val = L.Value;
1915 continue;
1916 if (.Value.getNode() || Result.Weight > L.Weight ||
1917 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1918 {
1920 ResultPos = Pos;
1921 }
1922 }
1923
1924 if (Result.Value.getNode()) {
1925 Q.erase(&Q[ResultPos]);
1926 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1927 }
1928
1930}
1931
1932WeightedLeaf LeafPrioQueue::findMULbyConst() {
1933 int ResultPos;
1934 WeightedLeaf Result;
1935
1936 for (int Pos = 0, End = Q.size(); Pos != End; ++Pos) {
1937 const WeightedLeaf &L = Q[Pos];
1938 const SDValue &Val = L.Value;
1942 continue;
1943 if (.Value.getNode() || Result.Weight > L.Weight ||
1944 (Result.Weight == L.Weight && Result.InsertionOrder > L.InsertionOrder))
1945 {
1947 ResultPos = Pos;
1948 }
1949 }
1950
1951 if (Result.Value.getNode()) {
1952 Q.erase(&Q[ResultPos]);
1953 std::make_heap(Q.begin(), Q.end(), WeightedLeaf::Compare);
1954 }
1955
1957}
1958
1959SDValue HexagonDAGToDAGISel::getMultiplierForSHL(SDNode *N) {
1961 return CurDAG->getConstant(MulFactor, SDLoc(N),
1962 N->getOperand(1).getValueType());
1963}
1964
1965
1968 unsigned MaxFactor = 0;
1969 for (int i = 0; i < 2; ++i) {
1971 if ()
1972 continue;
1973 const APInt &CInt = C->getAPIntValue();
1976 }
1977 return MaxFactor;
1978 }
1981 return 0;
1983 }
1984
1985 return 0;
1986}
1987
1988
1990 if (V.getOpcode() == ISD::MUL) {
1991 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
1992 for (int i = 0; i < 2; ++i)
1994 V.getConstantOperandVal(i) % (1ULL << Amount) == 0) {
1995 uint64_t NewConst = V.getConstantOperandVal(i) >> Amount;
1996 return (NewConst == 1);
1997 }
1998 } else if (V.getOpcode() == ISD::SHL) {
1999 return (Amount == V.getConstantOperandVal(1));
2000 }
2001
2002 return false;
2003}
2004
2005SDValue HexagonDAGToDAGISel::factorOutPowerOf2(SDValue V, unsigned Power) {
2006 SDValue Ops[] = { V.getOperand(0), V.getOperand(1) };
2007 if (V.getOpcode() == ISD::MUL) {
2008 for (int i=0; i < 2; ++i) {
2010 V.getConstantOperandVal(i) % ((uint64_t)1 << Power) == 0) {
2011 uint64_t NewConst = V.getConstantOperandVal(i) >> Power;
2012 if (NewConst == 1)
2013 return Ops[!i];
2014 Ops[i] = CurDAG->getConstant(NewConst,
2015 SDLoc(V), V.getValueType());
2016 break;
2017 }
2018 }
2019 } else if (V.getOpcode() == ISD::SHL) {
2020 uint64_t ShiftAmount = V.getConstantOperandVal(1);
2021 if (ShiftAmount == Power)
2022 return Ops[0];
2023 Ops[1] = CurDAG->getConstant(ShiftAmount - Power,
2024 SDLoc(V), V.getValueType());
2025 }
2026
2027 return CurDAG->getNode(V.getOpcode(), SDLoc(V), V.getValueType(), Ops);
2028}
2029
2034
2035unsigned HexagonDAGToDAGISel::getUsesInFunction(const Value *V) {
2036 auto [It, Inserted] = GAUsesInFunction.try_emplace(V);
2037 if (!Inserted)
2038 return It->second;
2039
2040 unsigned Result = 0;
2041 const Function &CurF = CurDAG->getMachineFunction().getFunction();
2042 for (const User *U : V->users()) {
2046 }
2047
2048 It->second = Result;
2049
2051}
2052
2053
2054
2055
2056
2057
2058SDValue HexagonDAGToDAGISel::balanceSubTree(SDNode *N, bool TopLevel) {
2059 assert(RootWeights.count(N) && "Cannot balance non-root node.");
2060 assert(RootWeights[N] != -2 && "This node was RAUW'd!");
2062
2063
2064 if (RootWeights[N] != -1)
2066
2068
2071
2072
2075 SDNode *Op0N = Op0.getNode();
2076 int Weight;
2078 Weight = getWeight(balanceSubTree(Op0N).getNode());
2079
2080 } else
2081 Weight = getWeight(Op0N);
2082
2083 SDNode *Op1N = N->getOperand(1).getNode();
2085 Weight += getWeight(balanceSubTree(Op1N).getNode());
2086
2087 } else
2088 Weight += getWeight(Op1N);
2089
2090 RootWeights[N] = Weight;
2091 RootHeights[N] = std::max(getHeight(N->getOperand(0).getNode()),
2092 getHeight(N->getOperand(1).getNode())) + 1;
2093
2094 LLVM_DEBUG(dbgs() << "--> No need to balance root (Weight=" << Weight
2095 << " Height=" << RootHeights[N] << "): ");
2097
2099 }
2100
2103
2104 unsigned NOpcode = N->getOpcode();
2105
2106 LeafPrioQueue Leaves(NOpcode);
2109
2110
2113
2114 bool CanFactorize = false;
2115 WeightedLeaf Mul1, Mul2;
2116 unsigned MaxPowerOf2 = 0;
2117 WeightedLeaf GA;
2118
2119
2120
2121 bool HaveTopLevelShift = false;
2122 if (TopLevel &&
2127 HaveTopLevelShift = true;
2128
2129
2130
2131 int InsertionOrder = 0;
2132 SmallDenseMap<SDValue, int> NodeHeights;
2133 bool Imbalanced = false;
2134 int CurrentWeight = 0;
2135 while (!Worklist.empty()) {
2137
2138 if (Child.getNode() != N && RootWeights.count(Child.getNode())) {
2139
2140
2141 int Weight = RootWeights[Child.getNode()];
2142 if (Weight == -1) {
2143 Child = balanceSubTree(Child.getNode());
2144
2145 Weight = getWeight(Child.getNode());
2146 } else if (Weight == -2) {
2147
2148
2149
2150 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2151 return balanceSubTree(N, TopLevel);
2152 }
2153
2154 NodeHeights[Child] = 1;
2155 CurrentWeight += Weight;
2156
2157 unsigned PowerOf2;
2158 if (TopLevel && !CanFactorize && !HaveTopLevelShift &&
2161
2162
2163
2164 if (!Mul1.Value.getNode()) {
2165 Mul1 = WeightedLeaf(Child, Weight, InsertionOrder++);
2166 MaxPowerOf2 = PowerOf2;
2167 } else {
2168 Mul2 = WeightedLeaf(Child, Weight, InsertionOrder++);
2169 MaxPowerOf2 = std::min(MaxPowerOf2, PowerOf2);
2170
2171
2172 if (MaxPowerOf2 > 3)
2173 MaxPowerOf2 = 3;
2174
2175 CanFactorize = true;
2176 }
2177 } else
2178 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2180
2181 int Weight = getWeight(Child.getNode());
2182
2183 NodeHeights[Child] = getHeight(Child.getNode());
2184 CurrentWeight += Weight;
2185
2187 GA = WeightedLeaf(Child, Weight, InsertionOrder++);
2188 else
2189 Leaves.push(WeightedLeaf(Child, Weight, InsertionOrder++));
2190 } else {
2191
2192
2193 unsigned ChildOpcode = Child.getOpcode();
2194 assert(ChildOpcode == NOpcode ||
2196
2197
2199 if (ChildOpcode == ISD::SHL)
2200 Op1 = getMultiplierForSHL(Child.getNode());
2201 else
2203
2205 assert(!NodeHeights.count(Child) && "Parent visited before children?");
2206
2210 } else {
2211
2212 if (std::abs(NodeHeights[Op1] - NodeHeights[Child->getOperand(0)]) > 1)
2213 Imbalanced = true;
2214
2215 NodeHeights[Child] = std::max(NodeHeights[Op1],
2216 NodeHeights[Child->getOperand(0)]) + 1;
2217 }
2218 }
2219 }
2220
2222 << " weight=" << CurrentWeight
2223 << " imbalanced=" << Imbalanced << "\n");
2224
2225
2226
2229 LLVM_DEBUG(dbgs() << "--> Found common factor for two MUL children!\n");
2230 int Weight = Mul1.Weight + Mul2.Weight;
2231 int Height = std::max(NodeHeights[Mul1.Value], NodeHeights[Mul2.Value]) + 1;
2232 SDValue Mul1Factored = factorOutPowerOf2(Mul1.Value, MaxPowerOf2);
2233 SDValue Mul2Factored = factorOutPowerOf2(Mul2.Value, MaxPowerOf2);
2235 Mul1Factored, Mul2Factored);
2239 Sum, Const);
2240 NodeHeights[New] = Height;
2241 Leaves.push(WeightedLeaf(New, Weight, Mul1.InsertionOrder));
2242 } else if (Mul1.Value.getNode()) {
2243
2244
2245 Leaves.push(Mul1);
2246 if (Mul2.Value.getNode())
2247 Leaves.push(Mul2);
2248 CanFactorize = false;
2249 }
2250
2251
2252
2253
2254 bool CombinedGA = false;
2255 if (NOpcode == ISD::ADD && GA.Value.getNode() && Leaves.hasConst() &&
2256 GA.Value.hasOneUse() && N->use_size() < 3) {
2257 GlobalAddressSDNode *GANode =
2260
2261 if (getUsesInFunction(GANode->getGlobal()) == 1 && Offset->hasOneUse() &&
2263 LLVM_DEBUG(dbgs() << "--> Combining GA and offset ("
2264 << Offset->getSExtValue() << "): ");
2266
2268 CurDAG->getTargetGlobalAddress(GANode->getGlobal(), SDLoc(GA.Value),
2270 GANode->getOffset() + (uint64_t)Offset->getSExtValue());
2271 GA.Value = CurDAG->getNode(GA.Value.getOpcode(), SDLoc(GA.Value),
2273 GA.Weight += Leaves.top().Weight;
2274
2275 NodeHeights[GA.Value] = getHeight(GA.Value.getNode());
2276 CombinedGA = true;
2277
2278 Leaves.pop();
2279 }
2280 }
2281
2284 RootWeights[N] = CurrentWeight;
2285 RootHeights[N] = NodeHeights[SDValue(N, 0)];
2286
2288 }
2289
2290
2292 WeightedLeaf SHL = Leaves.findSHL(31);
2293 if (SHL.Value.getNode()) {
2294 int Height = std::max(NodeHeights[GA.Value], NodeHeights[SHL.Value]) + 1;
2295 GA.Value = CurDAG->getNode(ISD::ADD, SDLoc(GA.Value),
2297 GA.Value, SHL.Value);
2298 GA.Weight = SHL.Weight;
2299 NodeHeights[GA.Value] = Height;
2300 }
2301 }
2302
2304 Leaves.push(GA);
2305
2306
2307
2308 if (TopLevel && !CanFactorize && Leaves.hasConst()) {
2309 LLVM_DEBUG(dbgs() << "--> Pushing constant to tip of tree.");
2310 Leaves.pushToBottom(Leaves.pop());
2311 }
2312
2313 const DataLayout &DL = CurDAG->getDataLayout();
2315
2316
2317 while (Leaves.size() > 1) {
2318 WeightedLeaf L0 = Leaves.pop();
2319
2320
2321
2322 WeightedLeaf L1 = Leaves.findMULbyConst();
2323 if (!L1.Value.getNode())
2324 L1 = Leaves.pop();
2325
2326 assert(L0.Weight <= L1.Weight && "Priority queue is broken!");
2327
2329 int V0Weight = L0.Weight;
2331 int V1Weight = L1.Weight;
2332
2333
2334 if ((RootWeights.count(V0.getNode()) && RootWeights[V0.getNode()] == -2) ||
2335 (RootWeights.count(V1.getNode()) && RootWeights[V1.getNode()] == -2)) {
2336 LLVM_DEBUG(dbgs() << "--> Subtree was RAUWd. Restarting...\n");
2337 return balanceSubTree(N, TopLevel);
2338 }
2339
2342 EVT VT = N->getValueType(0);
2344
2345 if (V0C && !V1C) {
2348 }
2349
2350
2352 "Children must have been visited before re-combining them!");
2353 int Height = std::max(NodeHeights[V0], NodeHeights[V1]) + 1;
2354
2355
2357 NewNode = CurDAG->getNode(
2358 ISD::SHL, SDLoc(V0), VT, V0,
2359 CurDAG->getConstant(
2362 else
2363 NewNode = CurDAG->getNode(NOpcode, SDLoc(N), VT, V0, V1);
2364
2365 NodeHeights[NewNode] = Height;
2366
2367 int Weight = V0Weight + V1Weight;
2368 Leaves.push(WeightedLeaf(NewNode, Weight, L0.InsertionOrder));
2369
2370 LLVM_DEBUG(dbgs() << "--> Built new node (Weight=" << Weight
2371 << ",Height=" << Height << "):\n");
2373 }
2374
2375 assert(Leaves.size() == 1);
2376 SDValue NewRoot = Leaves.top().Value;
2377
2379 int Height = NodeHeights[NewRoot];
2380
2381
2387 NewRoot = CurDAG->getNode(
2388 ISD::SHL, SDLoc(NewRoot), VT, V0,
2389 CurDAG->getConstant(
2392 }
2393 }
2394
2395 if (N != NewRoot.getNode()) {
2398
2399
2401
2402 RootWeights[N] = -2;
2403 } else {
2405 }
2406
2407 RootWeights[NewRoot.getNode()] = Leaves.top().Weight;
2408 RootHeights[NewRoot.getNode()] = Height;
2409
2410 return NewRoot;
2411}
2412
2413void HexagonDAGToDAGISel::rebalanceAddressTrees() {
2416 if (N->getOpcode() != ISD::LOAD && N->getOpcode() != ISD::STORE)
2417 continue;
2418
2421 continue;
2422
2423
2424 if (RootWeights.count(BasePtr.getNode()))
2425 continue;
2426
2427 LLVM_DEBUG(dbgs() << "** Rebalancing address calculation in node: ");
2429
2430
2432
2435
2436 while (!Worklist.empty()) {
2438 unsigned Opcode = N->getOpcode();
2439
2441 continue;
2442
2443 Worklist.push_back(N->getOperand(0).getNode());
2444 Worklist.push_back(N->getOperand(1).getNode());
2445
2446
2447 if (N->hasOneUse() && Opcode == N->user_begin()->getOpcode())
2448 continue;
2449
2450
2451 RootWeights.try_emplace(N, -1);
2452 }
2453
2454
2455 RootWeights[BasePtr.getNode()] = -1;
2456 SDValue NewBasePtr = balanceSubTree(BasePtr.getNode(), true);
2457
2458 if (N->getOpcode() == ISD::LOAD)
2459 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0),
2460 NewBasePtr, N->getOperand(2));
2461 else
2462 N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), N->getOperand(1),
2463 NewBasePtr, N->getOperand(3));
2464
2467 }
2468
2469 CurDAG->RemoveDeadNodes();
2470 GAUsesInFunction.clear();
2471 RootHeights.clear();
2472 RootWeights.clear();
2473}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool willShiftRightEliminate(SDValue V, unsigned Amount)
Definition HexagonISelDAGToDAG.cpp:1989
static cl::opt< bool > RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"))
static unsigned getPowerOf2Factor(SDValue Val)
Definition HexagonISelDAGToDAG.cpp:1966
static cl::opt< bool > CheckSingleUse("hexagon-isel-su", cl::Hidden, cl::init(true), cl::desc("Enable checking of SDNode's single-use status"))
static cl::opt< bool > EnableAddressRebalancing("isel-rebalance-addr", cl::Hidden, cl::init(true), cl::desc("Rebalance address calculation trees to improve " "instruction selection"))
static bool isMemOPCandidate(SDNode *I, SDNode *U)
Definition HexagonISelDAGToDAG.cpp:1081
static bool isTargetConstant(const SDValue &V)
Definition HexagonISelDAGToDAG.cpp:2030
static bool isOpcodeHandled(const SDNode *N)
Definition HexagonISelDAGToDAG.cpp:1780
static cl::opt< bool > RebalanceOnlyForOptimizations("rebalance-only-opt", cl::Hidden, cl::init(false), cl::desc("Rebalance address tree only if this allows optimizations"))
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
#define DEBUG_WITH_TYPE(TYPE,...)
DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug information.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
Class for arbitrary precision integers.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countr_zero() const
Count the number of trailing zero bits.
unsigned logBase2() const
bool getBoolValue() const
Convert APInt to a boolean value.
bool isPowerOf2() const
Check if this APInt's value is a power of two greater than zero.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
uint64_t getZExtValue() const
const APInt & getAPIntValue() const
int64_t getSExtValue() const
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
FunctionPass class - This class is used to implement most global optimizations.
int64_t getOffset() const
const GlobalValue * getGlobal() const
This class is used to form a handle around another node that is persistent and is updated across invo...
const SDValue & getValue() const
HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, CodeGenOptLevel OptLevel)
Definition HexagonISelDAGToDAG.cpp:67
void SelectAddSubCarry(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:794
void SelectConstant(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:752
void SelectIntrinsicWOChain(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:676
void Select(SDNode *N) override
Main hook for targets to transform nodes into machine nodes.
Definition HexagonISelDAGToDAG.cpp:1007
bool SelectNewCircIntrinsic(SDNode *IntN)
Generate a machine instruction node for the new circular buffer intrinsics.
Definition HexagonISelDAGToDAG.cpp:370
bool tryLoadOfLoadIntrinsic(LoadSDNode *N)
Definition HexagonISelDAGToDAG.cpp:262
void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl)
Definition HexagonISelDAGToDAG.cpp:76
void SelectExtractSubvector(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:710
void SelectVAlign(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:803
MachineSDNode * LoadInstrForLoadIntrinsic(SDNode *IntN)
Definition HexagonISelDAGToDAG.cpp:195
bool SelectAnyImm2(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1487
bool SelectAnyImm(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1477
void SelectV65GatherPred(SDNode *N)
bool SelectAnyImm0(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1481
void SelectSHL(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:579
void SelectIntrinsicWChain(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:637
void SelectV2Q(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:889
bool SelectAnyImm1(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1484
void SelectConstantFP(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:731
bool DetectUseSxtw(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1589
bool SelectBrevLdIntrinsic(SDNode *IntN)
Definition HexagonISelDAGToDAG.cpp:329
void emitFunctionEntryCode() override
Definition HexagonISelDAGToDAG.cpp:1419
bool SelectAddrFI(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1457
void FDiv(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:916
SDNode * StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN)
Definition HexagonISelDAGToDAG.cpp:227
bool SelectAddrGP(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1473
bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment)
Definition HexagonISelDAGToDAG.cpp:1503
bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment)
Definition HexagonISelDAGToDAG.cpp:1544
void SelectFrameIndex(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:765
bool SelectAnyImm3(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1490
void FastFDiv(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:967
void SelectFDiv(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:1000
void SelectStore(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:565
void SelectLoad(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:456
HexagonDAGToDAGISel()=delete
bool SelectAnyInt(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1494
bool SelectAddrGA(SDValue &N, SDValue &R)
Definition HexagonISelDAGToDAG.cpp:1469
void PreprocessISelDAG() override
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
Definition HexagonISelDAGToDAG.cpp:1359
void SelectTypecast(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:865
void SelectD2P(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:880
void SelectVAlignAddr(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:850
void SelectP2D(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:873
bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps) override
SelectInlineAsmMemoryOperand - Implement addressing mode selection for inline asm expressions.
Definition HexagonISelDAGToDAG.cpp:1059
void SelectV65Gather(SDNode *N)
void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl)
Definition HexagonISelDAGToDAG.cpp:474
void SelectHVXDualOutput(SDNode *N)
void SelectQ2V(SDNode *N)
Definition HexagonISelDAGToDAG.cpp:903
Hexagon target-specific information for each MachineFunction.
const HexagonFrameLowering * getFrameLowering() const override
This class is used to represent ISD::LOAD nodes.
unsigned getVectorNumElements() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
MVT getVectorElementType() const
static MVT getIntegerVT(unsigned BitWidth)
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
Align getMaxAlign() const
Return the alignment in bytes that this function must be aligned to, which is greater than the defaul...
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
A description of a memory reference used in the backend.
An SDNode that represents everything that will be needed to construct a MachineInstr.
This is an abstract virtual class for memory operations.
Wrapper class representing virtual and physical registers.
constexpr bool isValid() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
LLVM_ABI void dump() const
Dump this node, for debugging.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
unsigned getNumValues() const
Return the number of values defined/returned by this operator.
unsigned getNumOperands() const
Return the number of values used by this operation.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
user_iterator user_begin() const
Provide iteration support to walk over all users of an SDNode.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node.
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
uint64_t getConstantOperandVal(unsigned i) const
unsigned getOpcode() const
SelectionDAGISelLegacy(char &ID, std::unique_ptr< SelectionDAGISel > S)
const TargetLowering * TLI
void ReplaceUses(SDValue F, SDValue T)
ReplaceUses - replace all uses of the old node F with the use of the new node T.
void ReplaceNode(SDNode *F, SDNode *T)
Replace all uses of F with T, then remove F from the DAG.
const TargetLowering * getTargetLowering() const
LLVM_ABI MachineSDNode * getMachineNode(unsigned Opcode, const SDLoc &dl, EVT VT)
These are used for target selectors to create a new node with specified return type(s),...
LLVM_ABI SDValue getBitcast(EVT VT, SDValue V)
Return a bitcast using the SDLoc of the value operand, and casting to the provided type.
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
iterator erase(const_iterator CI)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
LLVM Value Representation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Abstract Attribute helper functions.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
@ C
The default llvm calling convention, compatible with C.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SIGN_EXTEND
Conversion operators.
@ SELECT
Select(COND, TRUEVAL, FALSEVAL).
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ VECTOR_SHUFFLE
VECTOR_SHUFFLE(VEC1, VEC2) - Returns a vector, of the same type as VEC1/VEC2.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_WO_CHAIN
RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) This node represents a target intrinsic fun...
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
MemIndexedMode
MemIndexedMode enum - This enum defines the load / store indexed addressing modes.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
initializer< Ty > init(const Ty &Val)
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
int countr_one(T Value)
Count the number of ones from the least significant bit to the first zero bit.
bool isAligned(Align Lhs, uint64_t SizeInBytes)
Checks that SizeInBytes is a multiple of the alignment.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
unsigned M1(unsigned Val)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
constexpr bool isPowerOf2_32(uint32_t Value)
Return true if the argument is a power of two > 0.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa - Return true if the parameter to the template is an instance of one of the template type argu...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
FunctionPass * createHexagonISelDag(HexagonTargetMachine &TM, CodeGenOptLevel OptLevel)
createHexagonISelDag - This pass converts a legalized DAG into a Hexagon-specific DAG,...
Definition HexagonISelDAGToDAG.cpp:61
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
@ Default
The result values are uniform if and only if all operands are uniform.
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
This struct is a compact representation of a valid (non-zero power of two) alignment.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool isVector() const
Return true if this is a vector value type.
EVT getVectorElementType() const
Given a vector type, return the type of each element.
bool isInteger() const
Return true if this is an integer or a vector integer type.
This class contains a discriminated union of information about pointers in memory operands,...
This represents a list of ValueType's that has been intern'd by a SelectionDAG.