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   LSR,     ///< Logical shift right.
42   LSRBN,   ///< Byte logical shift right N bits.
43   LSRWN,   ///< Word logical shift right N bits.
44   ASR,     ///< Arithmetic shift right.
45   ASRBN,   ///< Byte arithmetic shift right N bits.
46   ASRWN,   ///< Word arithmetic shift right N bits.
47   ROR,     ///< Bit rotate right.
48   ROL,     ///< Bit rotate left.
49   LSLLOOP, ///< A loop of single logical shift left instructions.
50   LSRLOOP, ///< A loop of single logical shift right instructions.
51   ROLLOOP, ///< A loop of single left bit rotate instructions.
52   RORLOOP, ///< A loop of single right bit rotate instructions.
53   ASRLOOP, ///< A loop of single arithmetic shift right instructions.
54   /// AVR conditional branches. Operand 0 is the chain operand, operand 1
55   /// is the block to branch if condition is true, operand 2 is the
56   /// condition code, and operand 3 is the flag operand produced by a CMP
57   /// or TEST instruction.
58   BRCOND,
59   /// Compare instruction.
60   CMP,
61   /// Compare with carry instruction.
62   CMPC,
63   /// Test for zero or minus instruction.
64   TST,
65   /// Swap Rd[7:4] <-> Rd[3:0].
66   SWAP,
67   /// Operand 0 and operand 1 are selection variable, operand 2
68   /// is condition code and operand 3 is flag operand.
69   SELECT_CC
70 };
71 
72 } // end of namespace AVRISD
73 
74 class AVRSubtarget;
75 class AVRTargetMachine;
76 
77 /// Performs target lowering for the AVR.
78 class AVRTargetLowering : public TargetLowering {
79 public:
80   explicit AVRTargetLowering(const AVRTargetMachine &TM,
81                              const AVRSubtarget &STI);
82 
83 public:
84   MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {
85     return MVT::i8;
86   }
87 
88   MVT::SimpleValueType getCmpLibcallReturnType() const override {
89     return MVT::i8;
90   }
91 
92   const char *getTargetNodeName(unsigned Opcode) const override;
93 
94   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
95 
96   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
97                           SelectionDAG &DAG) const override;
98 
99   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
100                              unsigned AS,
101                              Instruction *I = nullptr) const override;
102 
103   bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset,
104                                  ISD::MemIndexedMode &AM,
105                                  SelectionDAG &DAG) const override;
106 
107   bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base,
108                                   SDValue &Offset, ISD::MemIndexedMode &AM,
109                                   SelectionDAG &DAG) const override;
110 
111   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
112 
113   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
114                          EVT VT) const override;
115 
116   MachineBasicBlock *
117   EmitInstrWithCustomInserter(MachineInstr &MI,
118                               MachineBasicBlock *MBB) const override;
119 
120   ConstraintType getConstraintType(StringRef Constraint) const override;
121 
122   ConstraintWeight
123   getSingleConstraintMatchWeight(AsmOperandInfo &info,
124                                  const char *constraint) const override;
125 
126   std::pair<unsigned, const TargetRegisterClass *>
127   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
128                                StringRef Constraint, MVT VT) const override;
129 
130   unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
131 
132   void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
133                                     std::vector<SDValue> &Ops,
134                                     SelectionDAG &DAG) const override;
135 
136   Register getRegisterByName(const char* RegName, LLT VT,
137                              const MachineFunction &MF) const override;
138 
139   bool shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL)
140     const override {
141     return false;
142   }
143 
144 private:
145   SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
146                     SelectionDAG &DAG, SDLoc dl) const;
147   SDValue getAVRCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
148                     SDLoc dl) const;
149   SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;
150   SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
151   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
152   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
153   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
154   SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
155   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
156   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
157   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
158 
159   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
160                       bool isVarArg,
161                       const SmallVectorImpl<ISD::OutputArg> &Outs,
162                       LLVMContext &Context) const override;
163 
164   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
165                       const SmallVectorImpl<ISD::OutputArg> &Outs,
166                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
167                       SelectionDAG &DAG) const override;
168   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
169                                bool isVarArg,
170                                const SmallVectorImpl<ISD::InputArg> &Ins,
171                                const SDLoc &dl, SelectionDAG &DAG,
172                                SmallVectorImpl<SDValue> &InVals) const override;
173   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
174                     SmallVectorImpl<SDValue> &InVals) const override;
175   SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
176                           CallingConv::ID CallConv, bool isVarArg,
177                           const SmallVectorImpl<ISD::InputArg> &Ins,
178                           const SDLoc &dl, SelectionDAG &DAG,
179                           SmallVectorImpl<SDValue> &InVals) const;
180 
181 protected:
182 
183   const AVRSubtarget &Subtarget;
184 
185 private:
186   MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const;
187   MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const;
188 };
189 
190 } // end namespace llvm
191 
192 #endif // LLVM_AVR_ISEL_LOWERING_H
193