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/ADT/StringRef.h"
18 #include "llvm/CodeGen/SelectionDAG.h"
19 #include "llvm/CodeGen/SelectionDAGISel.h"
20 #include "llvm/Support/CodeGen.h"
21 
22 #include <vector>
23 
24 namespace llvm {
25 class MachineFunction;
26 class HexagonInstrInfo;
27 class HexagonRegisterInfo;
28 
29 class HexagonDAGToDAGISel : public SelectionDAGISel {
30   const HexagonSubtarget *HST;
31   const HexagonInstrInfo *HII;
32   const HexagonRegisterInfo *HRI;
33 public:
34   explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
35                                CodeGenOpt::Level OptLevel)
36       : SelectionDAGISel(tm, OptLevel), HST(nullptr), HII(nullptr),
37         HRI(nullptr) {}
38 
39   bool runOnMachineFunction(MachineFunction &MF) override {
40     // Reset the subtarget each time through.
41     HST = &MF.getSubtarget<HexagonSubtarget>();
42     HII = HST->getInstrInfo();
43     HRI = HST->getRegisterInfo();
44     SelectionDAGISel::runOnMachineFunction(MF);
45     updateAligna();
46     return true;
47   }
48 
49   bool ComplexPatternFuncMutatesDAG() const override {
50     return true;
51   }
52   void PreprocessISelDAG() override;
53   void emitFunctionEntryCode() override;
54 
55   void Select(SDNode *N) override;
56 
57   // Complex Pattern Selectors.
58   inline bool SelectAddrGA(SDValue &N, SDValue &R);
59   inline bool SelectAddrGP(SDValue &N, SDValue &R);
60   inline bool SelectAnyImm(SDValue &N, SDValue &R);
61   inline bool SelectAnyInt(SDValue &N, SDValue &R);
62   bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment);
63   bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment);
64   bool SelectAddrFI(SDValue &N, SDValue &R);
65   bool DetectUseSxtw(SDValue &N, SDValue &R);
66 
67   inline bool SelectAnyImm0(SDValue &N, SDValue &R);
68   inline bool SelectAnyImm1(SDValue &N, SDValue &R);
69   inline bool SelectAnyImm2(SDValue &N, SDValue &R);
70   inline bool SelectAnyImm3(SDValue &N, SDValue &R);
71 
72   StringRef getPassName() const override {
73     return "Hexagon DAG->DAG Pattern Instruction Selection";
74   }
75 
76   // Generate a machine instruction node corresponding to the circ/brev
77   // load intrinsic.
78   MachineSDNode *LoadInstrForLoadIntrinsic(SDNode *IntN);
79   // Given the circ/brev load intrinsic and the already generated machine
80   // instruction, generate the appropriate store (that is a part of the
81   // intrinsic's functionality).
82   SDNode *StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN);
83 
84   void SelectFrameIndex(SDNode *N);
85   /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
86   /// inline asm expressions.
87   bool SelectInlineAsmMemoryOperand(const SDValue &Op,
88                                     unsigned ConstraintID,
89                                     std::vector<SDValue> &OutOps) override;
90   bool tryLoadOfLoadIntrinsic(LoadSDNode *N);
91   bool SelectBrevLdIntrinsic(SDNode *IntN);
92   bool SelectNewCircIntrinsic(SDNode *IntN);
93   void SelectLoad(SDNode *N);
94   void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl);
95   void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl);
96   void SelectStore(SDNode *N);
97   void SelectSHL(SDNode *N);
98   void SelectIntrinsicWChain(SDNode *N);
99   void SelectIntrinsicWOChain(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 
114   // Include the declarations autogenerated from the selection patterns.
115   #define GET_DAGISEL_DECL
116   #include "HexagonGenDAGISel.inc"
117 
118 private:
119   // This is really only to get access to ReplaceNode (which is a protected
120   // member). Any other members used by HvxSelector can be moved around to
121   // make them accessible).
122   friend struct HvxSelector;
123 
124   SDValue selectUndef(const SDLoc &dl, MVT ResTy) {
125     SDNode *U = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy);
126     return SDValue(U, 0);
127   }
128 
129   void SelectHvxShuffle(SDNode *N);
130   void SelectHvxRor(SDNode *N);
131   void SelectHvxVAlign(SDNode *N);
132 
133   bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src);
134   bool isAlignedMemNode(const MemSDNode *N) const;
135   bool isSmallStackStore(const StoreSDNode *N) const;
136   bool isPositiveHalfWord(const SDNode *N) const;
137   bool hasOneUse(const SDNode *N) const;
138 
139   // DAG preprocessing functions.
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 
145   // Function postprocessing.
146   void updateAligna();
147 
148   SmallDenseMap<SDNode *,int> RootWeights;
149   SmallDenseMap<SDNode *,int> RootHeights;
150   SmallDenseMap<const Value *,int> GAUsesInFunction;
151   int getWeight(SDNode *N);
152   int getHeight(SDNode *N);
153   SDValue getMultiplierForSHL(SDNode *N);
154   SDValue factorOutPowerOf2(SDValue V, unsigned Power);
155   unsigned getUsesInFunction(const Value *V);
156   SDValue balanceSubTree(SDNode *N, bool Factorize = false);
157   void rebalanceAddressTrees();
158 }; // end HexagonDAGToDAGISel
159 }
160 
161 #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H
162