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