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 161 162 163 164 165
|
//===-- 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 HexagonDAGToDAGISel : public SelectionDAGISel {
const HexagonSubtarget *HST;
const HexagonInstrInfo *HII;
const HexagonRegisterInfo *HRI;
public:
static char ID;
HexagonDAGToDAGISel() = delete;
explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
CodeGenOpt::Level OptLevel)
: SelectionDAGISel(ID, 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,
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 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);
// 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
}
#endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H
|