10b57cec5SDimitry Andric //===-- HexagonISelDAGToDAG.h -----------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // Hexagon specific code to select Hexagon machine instructions for 90b57cec5SDimitry Andric // SelectionDAG operations. 100b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H 130b57cec5SDimitry Andric #define LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "HexagonSubtarget.h" 160b57cec5SDimitry Andric #include "HexagonTargetMachine.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAGISel.h" 190b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #include <vector> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace llvm { 240b57cec5SDimitry Andric class MachineFunction; 250b57cec5SDimitry Andric class HexagonInstrInfo; 260b57cec5SDimitry Andric class HexagonRegisterInfo; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class HexagonDAGToDAGISel : public SelectionDAGISel { 290b57cec5SDimitry Andric const HexagonSubtarget *HST; 300b57cec5SDimitry Andric const HexagonInstrInfo *HII; 310b57cec5SDimitry Andric const HexagonRegisterInfo *HRI; 32bdd1243dSDimitry Andric 33*0fca6ea1SDimitry Andric public: 34bdd1243dSDimitry Andric HexagonDAGToDAGISel() = delete; 35bdd1243dSDimitry Andric HexagonDAGToDAGISel(HexagonTargetMachine & tm,CodeGenOptLevel OptLevel)360b57cec5SDimitry Andric explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm, 375f757f3fSDimitry Andric CodeGenOptLevel OptLevel) 38*0fca6ea1SDimitry Andric : SelectionDAGISel(tm, OptLevel), HST(nullptr), HII(nullptr), 390b57cec5SDimitry Andric HRI(nullptr) {} 400b57cec5SDimitry Andric runOnMachineFunction(MachineFunction & MF)410b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override { 420b57cec5SDimitry Andric // Reset the subtarget each time through. 430b57cec5SDimitry Andric HST = &MF.getSubtarget<HexagonSubtarget>(); 440b57cec5SDimitry Andric HII = HST->getInstrInfo(); 450b57cec5SDimitry Andric HRI = HST->getRegisterInfo(); 460b57cec5SDimitry Andric SelectionDAGISel::runOnMachineFunction(MF); 47480093f4SDimitry Andric updateAligna(); 480b57cec5SDimitry Andric return true; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric ComplexPatternFuncMutatesDAG()510b57cec5SDimitry Andric bool ComplexPatternFuncMutatesDAG() const override { 520b57cec5SDimitry Andric return true; 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric void PreprocessISelDAG() override; 555ffd83dbSDimitry Andric void emitFunctionEntryCode() override; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric void Select(SDNode *N) override; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric // Complex Pattern Selectors. 600b57cec5SDimitry Andric inline bool SelectAddrGA(SDValue &N, SDValue &R); 610b57cec5SDimitry Andric inline bool SelectAddrGP(SDValue &N, SDValue &R); 620b57cec5SDimitry Andric inline bool SelectAnyImm(SDValue &N, SDValue &R); 630b57cec5SDimitry Andric inline bool SelectAnyInt(SDValue &N, SDValue &R); 645ffd83dbSDimitry Andric bool SelectAnyImmediate(SDValue &N, SDValue &R, Align Alignment); 655ffd83dbSDimitry Andric bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP, Align Alignment); 660b57cec5SDimitry Andric bool SelectAddrFI(SDValue &N, SDValue &R); 670b57cec5SDimitry Andric bool DetectUseSxtw(SDValue &N, SDValue &R); 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric inline bool SelectAnyImm0(SDValue &N, SDValue &R); 700b57cec5SDimitry Andric inline bool SelectAnyImm1(SDValue &N, SDValue &R); 710b57cec5SDimitry Andric inline bool SelectAnyImm2(SDValue &N, SDValue &R); 720b57cec5SDimitry Andric inline bool SelectAnyImm3(SDValue &N, SDValue &R); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Generate a machine instruction node corresponding to the circ/brev 750b57cec5SDimitry Andric // load intrinsic. 760b57cec5SDimitry Andric MachineSDNode *LoadInstrForLoadIntrinsic(SDNode *IntN); 770b57cec5SDimitry Andric // Given the circ/brev load intrinsic and the already generated machine 780b57cec5SDimitry Andric // instruction, generate the appropriate store (that is a part of the 790b57cec5SDimitry Andric // intrinsic's functionality). 800b57cec5SDimitry Andric SDNode *StoreInstrForLoadIntrinsic(MachineSDNode *LoadN, SDNode *IntN); 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void SelectFrameIndex(SDNode *N); 830b57cec5SDimitry Andric /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for 840b57cec5SDimitry Andric /// inline asm expressions. 850b57cec5SDimitry Andric bool SelectInlineAsmMemoryOperand(const SDValue &Op, 865f757f3fSDimitry Andric InlineAsm::ConstraintCode ConstraintID, 870b57cec5SDimitry Andric std::vector<SDValue> &OutOps) override; 880b57cec5SDimitry Andric bool tryLoadOfLoadIntrinsic(LoadSDNode *N); 890b57cec5SDimitry Andric bool SelectBrevLdIntrinsic(SDNode *IntN); 900b57cec5SDimitry Andric bool SelectNewCircIntrinsic(SDNode *IntN); 910b57cec5SDimitry Andric void SelectLoad(SDNode *N); 920b57cec5SDimitry Andric void SelectIndexedLoad(LoadSDNode *LD, const SDLoc &dl); 930b57cec5SDimitry Andric void SelectIndexedStore(StoreSDNode *ST, const SDLoc &dl); 940b57cec5SDimitry Andric void SelectStore(SDNode *N); 950b57cec5SDimitry Andric void SelectSHL(SDNode *N); 960b57cec5SDimitry Andric void SelectIntrinsicWChain(SDNode *N); 970b57cec5SDimitry Andric void SelectIntrinsicWOChain(SDNode *N); 98bdd1243dSDimitry Andric void SelectExtractSubvector(SDNode *N); 990b57cec5SDimitry Andric void SelectConstant(SDNode *N); 1000b57cec5SDimitry Andric void SelectConstantFP(SDNode *N); 1010b57cec5SDimitry Andric void SelectV65Gather(SDNode *N); 1020b57cec5SDimitry Andric void SelectV65GatherPred(SDNode *N); 1030b57cec5SDimitry Andric void SelectHVXDualOutput(SDNode *N); 1040b57cec5SDimitry Andric void SelectAddSubCarry(SDNode *N); 1050b57cec5SDimitry Andric void SelectVAlign(SDNode *N); 1060b57cec5SDimitry Andric void SelectVAlignAddr(SDNode *N); 1070b57cec5SDimitry Andric void SelectTypecast(SDNode *N); 1080b57cec5SDimitry Andric void SelectP2D(SDNode *N); 1090b57cec5SDimitry Andric void SelectD2P(SDNode *N); 1100b57cec5SDimitry Andric void SelectQ2V(SDNode *N); 1110b57cec5SDimitry Andric void SelectV2Q(SDNode *N); 112*0fca6ea1SDimitry Andric void SelectFDiv(SDNode *N); 113*0fca6ea1SDimitry Andric void FDiv(SDNode *N); 114*0fca6ea1SDimitry Andric void FastFDiv(SDNode *N); 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Include the declarations autogenerated from the selection patterns. 1170b57cec5SDimitry Andric #define GET_DAGISEL_DECL 1180b57cec5SDimitry Andric #include "HexagonGenDAGISel.inc" 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric private: 1210b57cec5SDimitry Andric // This is really only to get access to ReplaceNode (which is a protected 1220b57cec5SDimitry Andric // member). Any other members used by HvxSelector can be moved around to 1230b57cec5SDimitry Andric // make them accessible). 1240b57cec5SDimitry Andric friend struct HvxSelector; 1250b57cec5SDimitry Andric selectUndef(const SDLoc & dl,MVT ResTy)1260b57cec5SDimitry Andric SDValue selectUndef(const SDLoc &dl, MVT ResTy) { 1270b57cec5SDimitry Andric SDNode *U = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, ResTy); 1280b57cec5SDimitry Andric return SDValue(U, 0); 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src); 1320b57cec5SDimitry Andric bool isAlignedMemNode(const MemSDNode *N) const; 1330b57cec5SDimitry Andric bool isSmallStackStore(const StoreSDNode *N) const; 1340b57cec5SDimitry Andric bool isPositiveHalfWord(const SDNode *N) const; 1350b57cec5SDimitry Andric bool hasOneUse(const SDNode *N) const; 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric // DAG preprocessing functions. 138bdd1243dSDimitry Andric void PreprocessHvxISelDAG(); 1390b57cec5SDimitry Andric void ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes); 1400b57cec5SDimitry Andric void ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes); 1410b57cec5SDimitry Andric void ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes); 1420b57cec5SDimitry Andric void ppHoistZextI1(std::vector<SDNode*> &&Nodes); 143bdd1243dSDimitry Andric void ppHvxShuffleOfShuffle(std::vector<SDNode*> &&Nodes); 144bdd1243dSDimitry Andric 145bdd1243dSDimitry Andric void SelectHvxExtractSubvector(SDNode *N); 146bdd1243dSDimitry Andric void SelectHvxShuffle(SDNode *N); 147bdd1243dSDimitry Andric void SelectHvxRor(SDNode *N); 148bdd1243dSDimitry Andric void SelectHvxVAlign(SDNode *N); 1490b57cec5SDimitry Andric 150480093f4SDimitry Andric // Function postprocessing. 151480093f4SDimitry Andric void updateAligna(); 152480093f4SDimitry Andric 1530b57cec5SDimitry Andric SmallDenseMap<SDNode *,int> RootWeights; 1540b57cec5SDimitry Andric SmallDenseMap<SDNode *,int> RootHeights; 1550b57cec5SDimitry Andric SmallDenseMap<const Value *,int> GAUsesInFunction; 1560b57cec5SDimitry Andric int getWeight(SDNode *N); 1570b57cec5SDimitry Andric int getHeight(SDNode *N); 1580b57cec5SDimitry Andric SDValue getMultiplierForSHL(SDNode *N); 1590b57cec5SDimitry Andric SDValue factorOutPowerOf2(SDValue V, unsigned Power); 1600b57cec5SDimitry Andric unsigned getUsesInFunction(const Value *V); 1610b57cec5SDimitry Andric SDValue balanceSubTree(SDNode *N, bool Factorize = false); 1620b57cec5SDimitry Andric void rebalanceAddressTrees(); 1630b57cec5SDimitry Andric }; // end HexagonDAGToDAGISel 164*0fca6ea1SDimitry Andric 165*0fca6ea1SDimitry Andric class HexagonDAGToDAGISelLegacy : public SelectionDAGISelLegacy { 166*0fca6ea1SDimitry Andric public: 167*0fca6ea1SDimitry Andric static char ID; 168*0fca6ea1SDimitry Andric explicit HexagonDAGToDAGISelLegacy(HexagonTargetMachine &tm, 169*0fca6ea1SDimitry Andric CodeGenOptLevel OptLevel); 170*0fca6ea1SDimitry Andric }; 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_HEXAGON_HEXAGONISELDAGTODAG_H 174