xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelLowering.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===-- AVRISelLowering.h - AVR DAG Lowering Interface ----------*- C++ -*-===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric // This file defines the interfaces that AVR uses to lower LLVM code into a
10*0b57cec5SDimitry Andric // selection DAG.
11*0b57cec5SDimitry Andric //
12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13*0b57cec5SDimitry Andric 
14*0b57cec5SDimitry Andric #ifndef LLVM_AVR_ISEL_LOWERING_H
15*0b57cec5SDimitry Andric #define LLVM_AVR_ISEL_LOWERING_H
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
18*0b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
19*0b57cec5SDimitry Andric 
20*0b57cec5SDimitry Andric namespace llvm {
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric namespace AVRISD {
23*0b57cec5SDimitry Andric 
24*0b57cec5SDimitry Andric /// AVR Specific DAG Nodes
25*0b57cec5SDimitry Andric enum NodeType {
26*0b57cec5SDimitry Andric   /// Start the numbering where the builtin ops leave off.
27*0b57cec5SDimitry Andric   FIRST_NUMBER = ISD::BUILTIN_OP_END,
28*0b57cec5SDimitry Andric   /// Return from subroutine.
29*0b57cec5SDimitry Andric   RET_FLAG,
30*0b57cec5SDimitry Andric   /// Return from ISR.
31*0b57cec5SDimitry Andric   RETI_FLAG,
32*0b57cec5SDimitry Andric   /// Represents an abstract call instruction,
33*0b57cec5SDimitry Andric   /// which includes a bunch of information.
34*0b57cec5SDimitry Andric   CALL,
35*0b57cec5SDimitry Andric   /// A wrapper node for TargetConstantPool,
36*0b57cec5SDimitry Andric   /// TargetExternalSymbol, and TargetGlobalAddress.
37*0b57cec5SDimitry Andric   WRAPPER,
38*0b57cec5SDimitry Andric   LSL,     ///< Logical shift left.
39*0b57cec5SDimitry Andric   LSR,     ///< Logical shift right.
40*0b57cec5SDimitry Andric   ASR,     ///< Arithmetic shift right.
41*0b57cec5SDimitry Andric   ROR,     ///< Bit rotate right.
42*0b57cec5SDimitry Andric   ROL,     ///< Bit rotate left.
43*0b57cec5SDimitry Andric   LSLLOOP, ///< A loop of single logical shift left instructions.
44*0b57cec5SDimitry Andric   LSRLOOP, ///< A loop of single logical shift right instructions.
45*0b57cec5SDimitry Andric   ROLLOOP, ///< A loop of single left bit rotate instructions.
46*0b57cec5SDimitry Andric   RORLOOP, ///< A loop of single right bit rotate instructions.
47*0b57cec5SDimitry Andric   ASRLOOP, ///< A loop of single arithmetic shift right instructions.
48*0b57cec5SDimitry Andric   /// AVR conditional branches. Operand 0 is the chain operand, operand 1
49*0b57cec5SDimitry Andric   /// is the block to branch if condition is true, operand 2 is the
50*0b57cec5SDimitry Andric   /// condition code, and operand 3 is the flag operand produced by a CMP
51*0b57cec5SDimitry Andric   /// or TEST instruction.
52*0b57cec5SDimitry Andric   BRCOND,
53*0b57cec5SDimitry Andric   /// Compare instruction.
54*0b57cec5SDimitry Andric   CMP,
55*0b57cec5SDimitry Andric   /// Compare with carry instruction.
56*0b57cec5SDimitry Andric   CMPC,
57*0b57cec5SDimitry Andric   /// Test for zero or minus instruction.
58*0b57cec5SDimitry Andric   TST,
59*0b57cec5SDimitry Andric   /// Operand 0 and operand 1 are selection variable, operand 2
60*0b57cec5SDimitry Andric   /// is condition code and operand 3 is flag operand.
61*0b57cec5SDimitry Andric   SELECT_CC
62*0b57cec5SDimitry Andric };
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric } // end of namespace AVRISD
65*0b57cec5SDimitry Andric 
66*0b57cec5SDimitry Andric class AVRSubtarget;
67*0b57cec5SDimitry Andric class AVRTargetMachine;
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric /// Performs target lowering for the AVR.
70*0b57cec5SDimitry Andric class AVRTargetLowering : public TargetLowering {
71*0b57cec5SDimitry Andric public:
72*0b57cec5SDimitry Andric   explicit AVRTargetLowering(const AVRTargetMachine &TM,
73*0b57cec5SDimitry Andric                              const AVRSubtarget &STI);
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric public:
76*0b57cec5SDimitry Andric   MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {
77*0b57cec5SDimitry Andric     return MVT::i8;
78*0b57cec5SDimitry Andric   }
79*0b57cec5SDimitry Andric 
80*0b57cec5SDimitry Andric   MVT::SimpleValueType getCmpLibcallReturnType() const override {
81*0b57cec5SDimitry Andric     return MVT::i8;
82*0b57cec5SDimitry Andric   }
83*0b57cec5SDimitry Andric 
84*0b57cec5SDimitry Andric   const char *getTargetNodeName(unsigned Opcode) const override;
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
87*0b57cec5SDimitry Andric 
88*0b57cec5SDimitry Andric   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
89*0b57cec5SDimitry Andric                           SelectionDAG &DAG) const override;
90*0b57cec5SDimitry Andric 
91*0b57cec5SDimitry Andric   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
92*0b57cec5SDimitry Andric                              unsigned AS,
93*0b57cec5SDimitry Andric                              Instruction *I = nullptr) const override;
94*0b57cec5SDimitry Andric 
95*0b57cec5SDimitry Andric   bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset,
96*0b57cec5SDimitry Andric                                  ISD::MemIndexedMode &AM,
97*0b57cec5SDimitry Andric                                  SelectionDAG &DAG) const override;
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric   bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base,
100*0b57cec5SDimitry Andric                                   SDValue &Offset, ISD::MemIndexedMode &AM,
101*0b57cec5SDimitry Andric                                   SelectionDAG &DAG) const override;
102*0b57cec5SDimitry Andric 
103*0b57cec5SDimitry Andric   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
104*0b57cec5SDimitry Andric 
105*0b57cec5SDimitry Andric   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
106*0b57cec5SDimitry Andric                          EVT VT) const override;
107*0b57cec5SDimitry Andric 
108*0b57cec5SDimitry Andric   MachineBasicBlock *
109*0b57cec5SDimitry Andric   EmitInstrWithCustomInserter(MachineInstr &MI,
110*0b57cec5SDimitry Andric                               MachineBasicBlock *MBB) const override;
111*0b57cec5SDimitry Andric 
112*0b57cec5SDimitry Andric   ConstraintType getConstraintType(StringRef Constraint) const override;
113*0b57cec5SDimitry Andric 
114*0b57cec5SDimitry Andric   ConstraintWeight
115*0b57cec5SDimitry Andric   getSingleConstraintMatchWeight(AsmOperandInfo &info,
116*0b57cec5SDimitry Andric                                  const char *constraint) const override;
117*0b57cec5SDimitry Andric 
118*0b57cec5SDimitry Andric   std::pair<unsigned, const TargetRegisterClass *>
119*0b57cec5SDimitry Andric   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
120*0b57cec5SDimitry Andric                                StringRef Constraint, MVT VT) const override;
121*0b57cec5SDimitry Andric 
122*0b57cec5SDimitry Andric   unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric   void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
125*0b57cec5SDimitry Andric                                     std::vector<SDValue> &Ops,
126*0b57cec5SDimitry Andric                                     SelectionDAG &DAG) const override;
127*0b57cec5SDimitry Andric 
128*0b57cec5SDimitry Andric   unsigned getRegisterByName(const char* RegName, EVT VT,
129*0b57cec5SDimitry Andric                              SelectionDAG &DAG) const override;
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric   bool shouldSplitFunctionArgumentsAsLittleEndian(const DataLayout &DL)
132*0b57cec5SDimitry Andric     const override {
133*0b57cec5SDimitry Andric     return false;
134*0b57cec5SDimitry Andric   }
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric private:
137*0b57cec5SDimitry Andric   SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
138*0b57cec5SDimitry Andric                     SelectionDAG &DAG, SDLoc dl) const;
139*0b57cec5SDimitry Andric   SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;
140*0b57cec5SDimitry Andric   SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
141*0b57cec5SDimitry Andric   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
142*0b57cec5SDimitry Andric   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
143*0b57cec5SDimitry Andric   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
144*0b57cec5SDimitry Andric   SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
145*0b57cec5SDimitry Andric   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
146*0b57cec5SDimitry Andric   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
147*0b57cec5SDimitry Andric   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
148*0b57cec5SDimitry Andric 
149*0b57cec5SDimitry Andric   CCAssignFn *CCAssignFnForReturn(CallingConv::ID CC) const;
150*0b57cec5SDimitry Andric 
151*0b57cec5SDimitry Andric   bool CanLowerReturn(CallingConv::ID CallConv,
152*0b57cec5SDimitry Andric                       MachineFunction &MF, bool isVarArg,
153*0b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
154*0b57cec5SDimitry Andric                       LLVMContext &Context) const override;
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
157*0b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
158*0b57cec5SDimitry Andric                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
159*0b57cec5SDimitry Andric                       SelectionDAG &DAG) const override;
160*0b57cec5SDimitry Andric   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
161*0b57cec5SDimitry Andric                                bool isVarArg,
162*0b57cec5SDimitry Andric                                const SmallVectorImpl<ISD::InputArg> &Ins,
163*0b57cec5SDimitry Andric                                const SDLoc &dl, SelectionDAG &DAG,
164*0b57cec5SDimitry Andric                                SmallVectorImpl<SDValue> &InVals) const override;
165*0b57cec5SDimitry Andric   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
166*0b57cec5SDimitry Andric                     SmallVectorImpl<SDValue> &InVals) const override;
167*0b57cec5SDimitry Andric   SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
168*0b57cec5SDimitry Andric                           CallingConv::ID CallConv, bool isVarArg,
169*0b57cec5SDimitry Andric                           const SmallVectorImpl<ISD::InputArg> &Ins,
170*0b57cec5SDimitry Andric                           const SDLoc &dl, SelectionDAG &DAG,
171*0b57cec5SDimitry Andric                           SmallVectorImpl<SDValue> &InVals) const;
172*0b57cec5SDimitry Andric 
173*0b57cec5SDimitry Andric protected:
174*0b57cec5SDimitry Andric 
175*0b57cec5SDimitry Andric   const AVRSubtarget &Subtarget;
176*0b57cec5SDimitry Andric 
177*0b57cec5SDimitry Andric private:
178*0b57cec5SDimitry Andric   MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const;
179*0b57cec5SDimitry Andric   MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const;
180*0b57cec5SDimitry Andric };
181*0b57cec5SDimitry Andric 
182*0b57cec5SDimitry Andric } // end namespace llvm
183*0b57cec5SDimitry Andric 
184*0b57cec5SDimitry Andric #endif // LLVM_AVR_ISEL_LOWERING_H
185