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_FLAG, 30 /// Return from ISR. 31 RETI_FLAG, 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 unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; 137 138 void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, 139 std::vector<SDValue> &Ops, 140 SelectionDAG &DAG) const override; 141 142 Register getRegisterByName(const char *RegName, LLT VT, 143 const MachineFunction &MF) const override; 144 145 bool shouldSplitFunctionArgumentsAsLittleEndian( 146 const DataLayout &DL) const override { 147 return false; 148 } 149 150 ShiftLegalizationStrategy 151 preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N, 152 unsigned ExpansionFactor) const override { 153 return ShiftLegalizationStrategy::LowerToLibcall; 154 } 155 156 private: 157 SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc, 158 SelectionDAG &DAG, SDLoc dl) const; 159 SDValue getAVRCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG, 160 SDLoc dl) const; 161 SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const; 162 SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const; 163 SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; 164 SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const; 165 SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; 166 SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const; 167 SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; 168 SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const; 169 SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const; 170 171 bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF, 172 bool isVarArg, 173 const SmallVectorImpl<ISD::OutputArg> &Outs, 174 LLVMContext &Context) const override; 175 176 SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, 177 const SmallVectorImpl<ISD::OutputArg> &Outs, 178 const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl, 179 SelectionDAG &DAG) const override; 180 SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, 181 bool isVarArg, 182 const SmallVectorImpl<ISD::InputArg> &Ins, 183 const SDLoc &dl, SelectionDAG &DAG, 184 SmallVectorImpl<SDValue> &InVals) const override; 185 SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, 186 SmallVectorImpl<SDValue> &InVals) const override; 187 SDValue LowerCallResult(SDValue Chain, SDValue InFlag, 188 CallingConv::ID CallConv, bool isVarArg, 189 const SmallVectorImpl<ISD::InputArg> &Ins, 190 const SDLoc &dl, SelectionDAG &DAG, 191 SmallVectorImpl<SDValue> &InVals) const; 192 193 protected: 194 const AVRSubtarget &Subtarget; 195 196 private: 197 MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const; 198 MachineBasicBlock *insertWideShift(MachineInstr &MI, 199 MachineBasicBlock *BB) const; 200 MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const; 201 MachineBasicBlock *insertCopyZero(MachineInstr &MI, 202 MachineBasicBlock *BB) const; 203 MachineBasicBlock *insertAtomicArithmeticOp(MachineInstr &MI, 204 MachineBasicBlock *BB, 205 unsigned Opcode, int Width) const; 206 }; 207 208 } // end namespace llvm 209 210 #endif // LLVM_AVR_ISEL_LOWERING_H 211