reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    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
//===-- 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/ADT/StringRef.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 HexagonTargetLowering;

class HexagonDAGToDAGISel : public SelectionDAGISel {
  const HexagonSubtarget *HST;
  const HexagonInstrInfo *HII;
  const HexagonRegisterInfo *HRI;
public:
  explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
                               CodeGenOpt::Level 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);
    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, uint32_t LogAlign);
  bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP,
                           uint32_t LogAlign);
  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);

  StringRef getPassName() const override {
    return "Hexagon DAG->DAG Pattern Instruction Selection";
  }

  // 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,
                                    unsigned 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 SelectZeroExtend(SDNode *N);
  void SelectIntrinsicWChain(SDNode *N);
  void SelectIntrinsicWOChain(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);

  // 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);
  }

  void SelectHvxShuffle(SDNode *N);
  void SelectHvxRor(SDNode *N);
  void SelectHvxVAlign(SDNode *N);

  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 ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes);
  void ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes);
  void ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes);
  void ppHoistZextI1(std::vector<SDNode*> &&Nodes);

  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
}

#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H