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