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:
getScalarShiftAmountTy(const DataLayout &,EVT LHSTy)90   MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {
91     return MVT::i8;
92   }
93 
getCmpLibcallReturnType()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 
shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout & DL)146   bool shouldSplitFunctionArgumentsAsLittleEndian(
147       const DataLayout &DL) const override {
148     return false;
149   }
150 
151   ShiftLegalizationStrategy
preferredShiftLegalizationStrategy(SelectionDAG & DAG,SDNode * N,unsigned ExpansionFactor)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