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