1*0b57cec5SDimitry Andric //===-- AVRISelLowering.h - AVR DAG Lowering Interface ----------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file defines the interfaces that AVR uses to lower LLVM code into a 10*0b57cec5SDimitry Andric // selection DAG. 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #ifndef LLVM_AVR_ISEL_LOWERING_H 15*0b57cec5SDimitry Andric #define LLVM_AVR_ISEL_LOWERING_H 16*0b57cec5SDimitry Andric 17*0b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 18*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h" 19*0b57cec5SDimitry Andric 20*0b57cec5SDimitry Andric namespace llvm { 21*0b57cec5SDimitry Andric 22*0b57cec5SDimitry Andric namespace AVRISD { 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric /// AVR Specific DAG Nodes 25*0b57cec5SDimitry Andric enum NodeType { 26*0b57cec5SDimitry Andric /// Start the numbering where the builtin ops leave off. 27*0b57cec5SDimitry Andric FIRST_NUMBER = ISD::BUILTIN_OP_END, 28*0b57cec5SDimitry Andric /// Return from subroutine. 29*0b57cec5SDimitry Andric RET_FLAG, 30*0b57cec5SDimitry Andric /// Return from ISR. 31*0b57cec5SDimitry Andric RETI_FLAG, 32*0b57cec5SDimitry Andric /// Represents an abstract call instruction, 33*0b57cec5SDimitry Andric /// which includes a bunch of information. 34*0b57cec5SDimitry Andric CALL, 35*0b57cec5SDimitry Andric /// A wrapper node for TargetConstantPool, 36*0b57cec5SDimitry Andric /// TargetExternalSymbol, and TargetGlobalAddress. 37*0b57cec5SDimitry Andric WRAPPER, 38*0b57cec5SDimitry Andric LSL, ///< Logical shift left. 39*0b57cec5SDimitry Andric LSR, ///< Logical shift right. 40*0b57cec5SDimitry Andric ASR, ///< Arithmetic shift right. 41*0b57cec5SDimitry Andric ROR, ///< Bit rotate right. 42*0b57cec5SDimitry Andric ROL, ///< Bit rotate left. 43*0b57cec5SDimitry Andric LSLLOOP, ///< A loop of single logical shift left instructions. 44*0b57cec5SDimitry Andric LSRLOOP, ///< A loop of single logical shift right instructions. 45*0b57cec5SDimitry Andric ROLLOOP, ///< A loop of single left bit rotate instructions. 46*0b57cec5SDimitry Andric RORLOOP, ///< A loop of single right bit rotate instructions. 47*0b57cec5SDimitry Andric ASRLOOP, ///< A loop of single arithmetic shift right instructions. 48*0b57cec5SDimitry Andric /// AVR conditional branches. Operand 0 is the chain operand, operand 1 49*0b57cec5SDimitry Andric /// is the block to branch if condition is true, operand 2 is the 50*0b57cec5SDimitry Andric /// condition code, and operand 3 is the flag operand produced by a CMP 51*0b57cec5SDimitry Andric /// or TEST instruction. 52*0b57cec5SDimitry Andric BRCOND, 53*0b57cec5SDimitry Andric /// Compare instruction. 54*0b57cec5SDimitry Andric CMP, 55*0b57cec5SDimitry Andric /// Compare with carry instruction. 56*0b57cec5SDimitry Andric CMPC, 57*0b57cec5SDimitry Andric /// Test for zero or minus instruction. 58*0b57cec5SDimitry Andric TST, 59*0b57cec5SDimitry Andric /// Operand 0 and operand 1 are selection variable, operand 2 60*0b57cec5SDimitry Andric /// is condition code and operand 3 is flag operand. 61*0b57cec5SDimitry Andric SELECT_CC 62*0b57cec5SDimitry Andric }; 63*0b57cec5SDimitry Andric 64*0b57cec5SDimitry Andric } // end of namespace AVRISD 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric class AVRSubtarget; 67*0b57cec5SDimitry Andric class AVRTargetMachine; 68*0b57cec5SDimitry Andric 69*0b57cec5SDimitry Andric /// Performs target lowering for the AVR. 70*0b57cec5SDimitry Andric class AVRTargetLowering : public TargetLowering { 71*0b57cec5SDimitry Andric public: 72*0b57cec5SDimitry Andric explicit AVRTargetLowering(const AVRTargetMachine &TM, 73*0b57cec5SDimitry Andric const AVRSubtarget &STI); 74*0b57cec5SDimitry Andric 75*0b57cec5SDimitry Andric public: 76*0b57cec5SDimitry Andric MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override { 77*0b57cec5SDimitry Andric return MVT::i8; 78*0b57cec5SDimitry Andric } 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric MVT::SimpleValueType getCmpLibcallReturnType() const override { 81*0b57cec5SDimitry Andric return MVT::i8; 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric const char *getTargetNodeName(unsigned Opcode) const override; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results, 89*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 90*0b57cec5SDimitry Andric 91*0b57cec5SDimitry Andric bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty, 92*0b57cec5SDimitry Andric unsigned AS, 93*0b57cec5SDimitry Andric Instruction *I = nullptr) const override; 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset, 96*0b57cec5SDimitry Andric ISD::MemIndexedMode &AM, 97*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base, 100*0b57cec5SDimitry Andric SDValue &Offset, ISD::MemIndexedMode &AM, 101*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context, 106*0b57cec5SDimitry Andric EVT VT) const override; 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric MachineBasicBlock * 109*0b57cec5SDimitry Andric EmitInstrWithCustomInserter(MachineInstr &MI, 110*0b57cec5SDimitry Andric MachineBasicBlock *MBB) const override; 111*0b57cec5SDimitry Andric 112*0b57cec5SDimitry Andric ConstraintType getConstraintType(StringRef Constraint) const override; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric ConstraintWeight 115*0b57cec5SDimitry Andric getSingleConstraintMatchWeight(AsmOperandInfo &info, 116*0b57cec5SDimitry Andric const char *constraint) const override; 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *> 119*0b57cec5SDimitry Andric getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, 120*0b57cec5SDimitry Andric StringRef Constraint, MVT VT) const override; 121*0b57cec5SDimitry Andric 122*0b57cec5SDimitry Andric unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 123*0b57cec5SDimitry Andric 124*0b57cec5SDimitry Andric void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, 125*0b57cec5SDimitry Andric std::vector<SDValue> &Ops, 126*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric unsigned getRegisterByName(const char* RegName, EVT VT, 129*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric bool shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL) 132*0b57cec5SDimitry Andric const override { 133*0b57cec5SDimitry Andric return false; 134*0b57cec5SDimitry Andric } 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric private: 137*0b57cec5SDimitry Andric SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc, 138*0b57cec5SDimitry Andric SelectionDAG &DAG, SDLoc dl) const; 139*0b57cec5SDimitry Andric SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const; 140*0b57cec5SDimitry Andric SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const; 141*0b57cec5SDimitry Andric SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 142*0b57cec5SDimitry Andric SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 143*0b57cec5SDimitry Andric SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; 144*0b57cec5SDimitry Andric SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; 145*0b57cec5SDimitry Andric SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; 146*0b57cec5SDimitry Andric SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; 147*0b57cec5SDimitry Andric SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; 148*0b57cec5SDimitry Andric 149*0b57cec5SDimitry Andric CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC) const; 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric bool CanLowerReturn(CallingConv::ID CallConv, 152*0b57cec5SDimitry Andric MachineFunction &MF, bool isVarArg, 153*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 154*0b57cec5SDimitry Andric LLVMContext &Context) const override; 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 157*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::OutputArg> &Outs, 158*0b57cec5SDimitry Andric const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, 159*0b57cec5SDimitry Andric SelectionDAG &DAG) const override; 160*0b57cec5SDimitry Andric SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 161*0b57cec5SDimitry Andric bool isVarArg, 162*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 163*0b57cec5SDimitry Andric const SDLoc &dl, SelectionDAG &DAG, 164*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 165*0b57cec5SDimitry Andric SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 166*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const override; 167*0b57cec5SDimitry Andric SDValue LowerCallResult(SDValue Chain, SDValue InFlag, 168*0b57cec5SDimitry Andric CallingConv::ID CallConv, bool isVarArg, 169*0b57cec5SDimitry Andric const SmallVectorImpl<ISD::InputArg> &Ins, 170*0b57cec5SDimitry Andric const SDLoc &dl, SelectionDAG &DAG, 171*0b57cec5SDimitry Andric SmallVectorImpl<SDValue> &InVals) const; 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric protected: 174*0b57cec5SDimitry Andric 175*0b57cec5SDimitry Andric const AVRSubtarget &Subtarget; 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric private: 178*0b57cec5SDimitry Andric MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const; 179*0b57cec5SDimitry Andric MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const; 180*0b57cec5SDimitry Andric }; 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric } // end namespace llvm 183*0b57cec5SDimitry Andric 184*0b57cec5SDimitry Andric #endif // LLVM_AVR_ISEL_LOWERING_H 185