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