//===-- 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 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(); 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 &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 &&Nodes); void ppAddrReorderAddShl(std::vector &&Nodes); void ppAddrRewriteAndSrl(std::vector &&Nodes); void ppHoistZextI1(std::vector &&Nodes); void ppHvxShuffleOfShuffle(std::vector &&Nodes); void SelectHvxExtractSubvector(SDNode *N); void SelectHvxShuffle(SDNode *N); void SelectHvxRor(SDNode *N); void SelectHvxVAlign(SDNode *N); // Function postprocessing. void updateAligna(); SmallDenseMap RootWeights; SmallDenseMap RootHeights; SmallDenseMap 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