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
20namespace llvm {
21
22namespace AVRISD {
23
24/// AVR Specific DAG Nodes
25enum 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
80class AVRSubtarget;
81class AVRTargetMachine;
82
83/// Performs target lowering for the AVR.
84class AVRTargetLowering : public TargetLowering {
85public:
86 explicit AVRTargetLowering(const AVRTargetMachine &TM,
87 const AVRSubtarget &STI);
88
89public:
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
157private:
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
194protected:
195 const AVRSubtarget &Subtarget;
196
197private:
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