1 | //===-- HexagonISelDAGToDAG.h -----------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // Hexagon specific code to select Hexagon machine instructions for |
9 | // SelectionDAG operations. |
10 | //===----------------------------------------------------------------------===// |
11 | |
12 | #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H |
13 | #define LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H |
14 | |
15 | #include "HexagonSubtarget.h" |
16 | #include "HexagonTargetMachine.h" |
17 | #include "llvm/CodeGen/SelectionDAG.h" |
18 | #include "llvm/CodeGen/SelectionDAGISel.h" |
19 | #include "llvm/Support/CodeGen.h" |
20 | |
21 | #include <vector> |
22 | |
23 | namespace llvm { |
24 | class MachineFunction; |
25 | class HexagonInstrInfo; |
26 | class HexagonRegisterInfo; |
27 | |
28 | class HexagonDAGToDAGISel : public SelectionDAGISel { |
29 | const HexagonSubtarget *HST; |
30 | const HexagonInstrInfo *HII; |
31 | const HexagonRegisterInfo *HRI; |
32 | public: |
33 | static char ID; |
34 | |
35 | HexagonDAGToDAGISel() = delete; |
36 | |
37 | explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm, |
38 | CodeGenOptLevel OptLevel) |
39 | : SelectionDAGISel(ID, tm, OptLevel), HST(nullptr), HII(nullptr), |
40 | HRI(nullptr) {} |
41 | |
42 | bool runOnMachineFunction(MachineFunction &MF) override { |
43 | // Reset the subtarget each time through. |
44 | HST = &MF.getSubtarget<HexagonSubtarget>(); |
45 | HII = HST->getInstrInfo(); |
46 | HRI = HST->getRegisterInfo(); |
47 | SelectionDAGISel::runOnMachineFunction(MF); |
48 | updateAligna(); |
49 | return true; |
50 | } |
51 | |
52 | bool ComplexPatternFuncMutatesDAG() const override { |
53 | return true; |
54 | } |
55 | void PreprocessISelDAG() override; |
56 | void emitFunctionEntryCode() override; |
57 | |
58 | void Select(SDNode *N) override; |
59 | |
60 | // Complex Pattern Selectors. |
61 | inline bool SelectAddrGA(SDValue &N, SDValue &R); |
62 | inline bool SelectAddrGP(SDValue &N, SDValue &R); |
63 | inline bool SelectAnyImm(SDValue &N, SDValue &R); |
64 | inline bool SelectAnyInt(SDValue &N, SDValue &R); |
65 | bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment); |
66 | bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment); |
67 | bool SelectAddrFI(SDValue &N, SDValue &R); |
68 | bool DetectUseSxtw(SDValue &N, SDValue &R); |
69 | |
70 | inline bool SelectAnyImm0(SDValue &N, SDValue &R); |
71 | inline bool SelectAnyImm1(SDValue &N, SDValue &R); |
72 | inline bool SelectAnyImm2(SDValue &N, SDValue &R); |
73 | inline bool SelectAnyImm3(SDValue &N, SDValue &R); |
74 | |
75 | // Generate a machine instruction node corresponding to the circ/brev |
76 | // load intrinsic. |
77 | MachineSDNode *LoadInstrForLoadIntrinsic(SDNode *IntN); |
78 | // Given the circ/brev load intrinsic and the already generated machine |
79 | // instruction, generate the appropriate store (that is a part of the |
80 | // intrinsic's functionality). |
81 | SDNode *StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN); |
82 | |
83 | void SelectFrameIndex(SDNode *N); |
84 | /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for |
85 | /// inline asm expressions. |
86 | bool SelectInlineAsmMemoryOperand(const SDValue &Op, |
87 | InlineAsm::ConstraintCode ConstraintID, |
88 | std::vector<SDValue> &OutOps) override; |
89 | bool tryLoadOfLoadIntrinsic(LoadSDNode *N); |
90 | bool SelectBrevLdIntrinsic(SDNode *IntN); |
91 | bool SelectNewCircIntrinsic(SDNode *IntN); |
92 | void SelectLoad(SDNode *N); |
93 | void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl); |
94 | void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl); |
95 | void SelectStore(SDNode *N); |
96 | void SelectSHL(SDNode *N); |
97 | void SelectIntrinsicWChain(SDNode *N); |
98 | void SelectIntrinsicWOChain(SDNode *N); |
99 | void (SDNode *N); |
100 | void SelectConstant(SDNode *N); |
101 | void SelectConstantFP(SDNode *N); |
102 | void SelectV65Gather(SDNode *N); |
103 | void SelectV65GatherPred(SDNode *N); |
104 | void SelectHVXDualOutput(SDNode *N); |
105 | void SelectAddSubCarry(SDNode *N); |
106 | void SelectVAlign(SDNode *N); |
107 | void SelectVAlignAddr(SDNode *N); |
108 | void SelectTypecast(SDNode *N); |
109 | void SelectP2D(SDNode *N); |
110 | void SelectD2P(SDNode *N); |
111 | void SelectQ2V(SDNode *N); |
112 | void SelectV2Q(SDNode *N); |
113 | void SelectFDiv(SDNode *N); |
114 | void FDiv(SDNode *N); |
115 | void FastFDiv(SDNode *N); |
116 | |
117 | // Include the declarations autogenerated from the selection patterns. |
118 | #define GET_DAGISEL_DECL |
119 | #include "HexagonGenDAGISel.inc" |
120 | |
121 | private: |
122 | // This is really only to get access to ReplaceNode (which is a protected |
123 | // member). Any other members used by HvxSelector can be moved around to |
124 | // make them accessible). |
125 | friend struct HvxSelector; |
126 | |
127 | SDValue selectUndef(const SDLoc &dl, MVT ResTy) { |
128 | SDNode *U = CurDAG->getMachineNode(Opcode: TargetOpcode::IMPLICIT_DEF, dl, VT: ResTy); |
129 | return SDValue(U, 0); |
130 | } |
131 | |
132 | bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src); |
133 | bool isAlignedMemNode(const MemSDNode *N) const; |
134 | bool isSmallStackStore(const StoreSDNode *N) const; |
135 | bool isPositiveHalfWord(const SDNode *N) const; |
136 | bool hasOneUse(const SDNode *N) const; |
137 | |
138 | // DAG preprocessing functions. |
139 | void PreprocessHvxISelDAG(); |
140 | void ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes); |
141 | void ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes); |
142 | void ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes); |
143 | void ppHoistZextI1(std::vector<SDNode*> &&Nodes); |
144 | void ppHvxShuffleOfShuffle(std::vector<SDNode*> &&Nodes); |
145 | |
146 | void (SDNode *N); |
147 | void SelectHvxShuffle(SDNode *N); |
148 | void SelectHvxRor(SDNode *N); |
149 | void SelectHvxVAlign(SDNode *N); |
150 | |
151 | // Function postprocessing. |
152 | void updateAligna(); |
153 | |
154 | SmallDenseMap<SDNode *,int> RootWeights; |
155 | SmallDenseMap<SDNode *,int> RootHeights; |
156 | SmallDenseMap<const Value *,int> GAUsesInFunction; |
157 | int getWeight(SDNode *N); |
158 | int getHeight(SDNode *N); |
159 | SDValue getMultiplierForSHL(SDNode *N); |
160 | SDValue factorOutPowerOf2(SDValue V, unsigned Power); |
161 | unsigned getUsesInFunction(const Value *V); |
162 | SDValue balanceSubTree(SDNode *N, bool Factorize = false); |
163 | void rebalanceAddressTrees(); |
164 | }; // end HexagonDAGToDAGISel |
165 | } |
166 | |
167 | #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H |
168 | |