| 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 | |
| 33 | public: |
| 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 (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 | // Include the declarations autogenerated from the selection patterns. |
| 117 | #define GET_DAGISEL_DECL |
| 118 | #include "HexagonGenDAGISel.inc" |
| 119 | |
| 120 | private: |
| 121 | // This is really only to get access to ReplaceNode (which is a protected |
| 122 | // member). Any other members used by HvxSelector can be moved around to |
| 123 | // make them accessible). |
| 124 | friend struct HvxSelector; |
| 125 | |
| 126 | SDValue selectUndef(const SDLoc &dl, MVT ResTy) { |
| 127 | SDNode *U = CurDAG->getMachineNode(Opcode: TargetOpcode::IMPLICIT_DEF, dl, VT: ResTy); |
| 128 | return SDValue(U, 0); |
| 129 | } |
| 130 | |
| 131 | bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src); |
| 132 | bool isAlignedMemNode(const MemSDNode *N) const; |
| 133 | bool isSmallStackStore(const StoreSDNode *N) const; |
| 134 | bool isPositiveHalfWord(const SDNode *N) const; |
| 135 | bool hasOneUse(const SDNode *N) const; |
| 136 | |
| 137 | // DAG preprocessing functions. |
| 138 | void PreprocessHvxISelDAG(); |
| 139 | void ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes); |
| 140 | void ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes); |
| 141 | void ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes); |
| 142 | void ppHoistZextI1(std::vector<SDNode*> &&Nodes); |
| 143 | void ppHvxShuffleOfShuffle(std::vector<SDNode*> &&Nodes); |
| 144 | |
| 145 | void (SDNode *N); |
| 146 | void SelectHvxShuffle(SDNode *N); |
| 147 | void SelectHvxRor(SDNode *N); |
| 148 | void SelectHvxVAlign(SDNode *N); |
| 149 | |
| 150 | // Function postprocessing. |
| 151 | void updateAligna(); |
| 152 | |
| 153 | SmallDenseMap<SDNode *,int> RootWeights; |
| 154 | SmallDenseMap<SDNode *,int> RootHeights; |
| 155 | SmallDenseMap<const Value *,int> GAUsesInFunction; |
| 156 | int getWeight(SDNode *N); |
| 157 | int getHeight(SDNode *N); |
| 158 | SDValue getMultiplierForSHL(SDNode *N); |
| 159 | SDValue factorOutPowerOf2(SDValue V, unsigned Power); |
| 160 | unsigned getUsesInFunction(const Value *V); |
| 161 | SDValue balanceSubTree(SDNode *N, bool Factorize = false); |
| 162 | void rebalanceAddressTrees(); |
| 163 | }; // end HexagonDAGToDAGISel |
| 164 | |
| 165 | class HexagonDAGToDAGISelLegacy : public SelectionDAGISelLegacy { |
| 166 | public: |
| 167 | static char ID; |
| 168 | explicit HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, |
| 169 | CodeGenOptLevel OptLevel); |
| 170 | }; |
| 171 | } |
| 172 | |
| 173 | #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H |
| 174 | |