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 | |