xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelLowering.h (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- AVRISelLowering.h - AVR DAG Lowering Interface ----------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file defines the interfaces that AVR uses to lower LLVM code into a
100b57cec5SDimitry Andric // selection DAG.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_AVR_ISEL_LOWERING_H
150b57cec5SDimitry Andric #define LLVM_AVR_ISEL_LOWERING_H
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLowering.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace llvm {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace AVRISD {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric /// AVR Specific DAG Nodes
250b57cec5SDimitry Andric enum NodeType {
260b57cec5SDimitry Andric   /// Start the numbering where the builtin ops leave off.
270b57cec5SDimitry Andric   FIRST_NUMBER = ISD::BUILTIN_OP_END,
280b57cec5SDimitry Andric   /// Return from subroutine.
2906c3fb27SDimitry Andric   RET_GLUE,
300b57cec5SDimitry Andric   /// Return from ISR.
3106c3fb27SDimitry Andric   RETI_GLUE,
320b57cec5SDimitry Andric   /// Represents an abstract call instruction,
330b57cec5SDimitry Andric   /// which includes a bunch of information.
340b57cec5SDimitry Andric   CALL,
350b57cec5SDimitry Andric   /// A wrapper node for TargetConstantPool,
360b57cec5SDimitry Andric   /// TargetExternalSymbol, and TargetGlobalAddress.
370b57cec5SDimitry Andric   WRAPPER,
380b57cec5SDimitry Andric   LSL,     ///< Logical shift left.
39fe6060f1SDimitry Andric   LSLBN,   ///< Byte logical shift left N bits.
40fe6060f1SDimitry Andric   LSLWN,   ///< Word logical shift left N bits.
4104eeddc0SDimitry Andric   LSLHI,   ///< Higher 8-bit of word logical shift left.
42bdd1243dSDimitry Andric   LSLW,    ///< Wide logical shift left.
430b57cec5SDimitry Andric   LSR,     ///< Logical shift right.
44fe6060f1SDimitry Andric   LSRBN,   ///< Byte logical shift right N bits.
45fe6060f1SDimitry Andric   LSRWN,   ///< Word logical shift right N bits.
4604eeddc0SDimitry Andric   LSRLO,   ///< Lower 8-bit of word logical shift right.
47bdd1243dSDimitry Andric   LSRW,    ///< Wide logical shift right.
480b57cec5SDimitry Andric   ASR,     ///< Arithmetic shift right.
49fe6060f1SDimitry Andric   ASRBN,   ///< Byte arithmetic shift right N bits.
50fe6060f1SDimitry Andric   ASRWN,   ///< Word arithmetic shift right N bits.
5104eeddc0SDimitry Andric   ASRLO,   ///< Lower 8-bit of word arithmetic shift right.
52bdd1243dSDimitry Andric   ASRW,    ///< Wide arithmetic shift right.
530b57cec5SDimitry Andric   ROR,     ///< Bit rotate right.
540b57cec5SDimitry Andric   ROL,     ///< Bit rotate left.
550b57cec5SDimitry Andric   LSLLOOP, ///< A loop of single logical shift left instructions.
560b57cec5SDimitry Andric   LSRLOOP, ///< A loop of single logical shift right instructions.
570b57cec5SDimitry Andric   ROLLOOP, ///< A loop of single left bit rotate instructions.
580b57cec5SDimitry Andric   RORLOOP, ///< A loop of single right bit rotate instructions.
590b57cec5SDimitry Andric   ASRLOOP, ///< A loop of single arithmetic shift right instructions.
600b57cec5SDimitry Andric   /// AVR conditional branches. Operand 0 is the chain operand, operand 1
610b57cec5SDimitry Andric   /// is the block to branch if condition is true, operand 2 is the
620b57cec5SDimitry Andric   /// condition code, and operand 3 is the flag operand produced by a CMP
630b57cec5SDimitry Andric   /// or TEST instruction.
640b57cec5SDimitry Andric   BRCOND,
650b57cec5SDimitry Andric   /// Compare instruction.
660b57cec5SDimitry Andric   CMP,
670b57cec5SDimitry Andric   /// Compare with carry instruction.
680b57cec5SDimitry Andric   CMPC,
690b57cec5SDimitry Andric   /// Test for zero or minus instruction.
700b57cec5SDimitry Andric   TST,
71e8d8bef9SDimitry Andric   /// Swap Rd[7:4] <-> Rd[3:0].
72e8d8bef9SDimitry Andric   SWAP,
730b57cec5SDimitry Andric   /// Operand 0 and operand 1 are selection variable, operand 2
740b57cec5SDimitry Andric   /// is condition code and operand 3 is flag operand.
750b57cec5SDimitry Andric   SELECT_CC
760b57cec5SDimitry Andric };
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric } // end of namespace AVRISD
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric class AVRSubtarget;
810b57cec5SDimitry Andric class AVRTargetMachine;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric /// Performs target lowering for the AVR.
840b57cec5SDimitry Andric class AVRTargetLowering : public TargetLowering {
850b57cec5SDimitry Andric public:
860b57cec5SDimitry Andric   explicit AVRTargetLowering(const AVRTargetMachine &TM,
870b57cec5SDimitry Andric                              const AVRSubtarget &STI);
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric public:
900b57cec5SDimitry Andric   MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {
910b57cec5SDimitry Andric     return MVT::i8;
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   MVT::SimpleValueType getCmpLibcallReturnType() const override {
950b57cec5SDimitry Andric     return MVT::i8;
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   const char *getTargetNodeName(unsigned Opcode) const override;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
1030b57cec5SDimitry Andric                           SelectionDAG &DAG) const override;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
1060b57cec5SDimitry Andric                              unsigned AS,
1070b57cec5SDimitry Andric                              Instruction *I = nullptr) const override;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset,
1100b57cec5SDimitry Andric                                  ISD::MemIndexedMode &AM,
1110b57cec5SDimitry Andric                                  SelectionDAG &DAG) const override;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base,
1140b57cec5SDimitry Andric                                   SDValue &Offset, ISD::MemIndexedMode &AM,
1150b57cec5SDimitry Andric                                   SelectionDAG &DAG) const override;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
1200b57cec5SDimitry Andric                          EVT VT) const override;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   MachineBasicBlock *
1230b57cec5SDimitry Andric   EmitInstrWithCustomInserter(MachineInstr &MI,
1240b57cec5SDimitry Andric                               MachineBasicBlock *MBB) const override;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   ConstraintType getConstraintType(StringRef Constraint) const override;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   ConstraintWeight
1290b57cec5SDimitry Andric   getSingleConstraintMatchWeight(AsmOperandInfo &info,
1300b57cec5SDimitry Andric                                  const char *constraint) const override;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   std::pair<unsigned, const TargetRegisterClass *>
1330b57cec5SDimitry Andric   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
1340b57cec5SDimitry Andric                                StringRef Constraint, MVT VT) const override;
1350b57cec5SDimitry Andric 
136*5f757f3fSDimitry Andric   InlineAsm::ConstraintCode
137*5f757f3fSDimitry Andric   getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
1380b57cec5SDimitry Andric 
139*5f757f3fSDimitry Andric   void LowerAsmOperandForConstraint(SDValue Op, StringRef Constraint,
1400b57cec5SDimitry Andric                                     std::vector<SDValue> &Ops,
1410b57cec5SDimitry Andric                                     SelectionDAG &DAG) const override;
1420b57cec5SDimitry Andric 
143480093f4SDimitry Andric   Register getRegisterByName(const char *RegName, LLT VT,
1448bcb0991SDimitry Andric                              const MachineFunction &MF) const override;
1450b57cec5SDimitry Andric 
146349cc55cSDimitry Andric   bool shouldSplitFunctionArgumentsAsLittleEndian(
147349cc55cSDimitry Andric       const DataLayout &DL) const override {
1480b57cec5SDimitry Andric     return false;
1490b57cec5SDimitry Andric   }
1500b57cec5SDimitry Andric 
151bdd1243dSDimitry Andric   ShiftLegalizationStrategy
152bdd1243dSDimitry Andric   preferredShiftLegalizationStrategy(SelectionDAG &DAG, SDNode *N,
153bdd1243dSDimitry Andric                                      unsigned ExpansionFactor) const override {
154bdd1243dSDimitry Andric     return ShiftLegalizationStrategy::LowerToLibcall;
155bdd1243dSDimitry Andric   }
156bdd1243dSDimitry Andric 
1570b57cec5SDimitry Andric private:
1580b57cec5SDimitry Andric   SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
1590b57cec5SDimitry Andric                     SelectionDAG &DAG, SDLoc dl) const;
160e8d8bef9SDimitry Andric   SDValue getAVRCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
161e8d8bef9SDimitry Andric                     SDLoc dl) const;
1620b57cec5SDimitry Andric   SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;
1630b57cec5SDimitry Andric   SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
1640b57cec5SDimitry Andric   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
1650b57cec5SDimitry Andric   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
1660b57cec5SDimitry Andric   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
1670b57cec5SDimitry Andric   SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
1680b57cec5SDimitry Andric   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
1690b57cec5SDimitry Andric   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
1700b57cec5SDimitry Andric   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
1710b57cec5SDimitry Andric 
1725ffd83dbSDimitry Andric   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1735ffd83dbSDimitry Andric                       bool isVarArg,
1740b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
1750b57cec5SDimitry Andric                       LLVMContext &Context) const override;
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1780b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
1790b57cec5SDimitry Andric                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
1800b57cec5SDimitry Andric                       SelectionDAG &DAG) const override;
1810b57cec5SDimitry Andric   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
1820b57cec5SDimitry Andric                                bool isVarArg,
1830b57cec5SDimitry Andric                                const SmallVectorImpl<ISD::InputArg> &Ins,
1840b57cec5SDimitry Andric                                const SDLoc &dl, SelectionDAG &DAG,
1850b57cec5SDimitry Andric                                SmallVectorImpl<SDValue> &InVals) const override;
1860b57cec5SDimitry Andric   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
1870b57cec5SDimitry Andric                     SmallVectorImpl<SDValue> &InVals) const override;
18806c3fb27SDimitry Andric   SDValue LowerCallResult(SDValue Chain, SDValue InGlue,
1890b57cec5SDimitry Andric                           CallingConv::ID CallConv, bool isVarArg,
1900b57cec5SDimitry Andric                           const SmallVectorImpl<ISD::InputArg> &Ins,
1910b57cec5SDimitry Andric                           const SDLoc &dl, SelectionDAG &DAG,
1920b57cec5SDimitry Andric                           SmallVectorImpl<SDValue> &InVals) const;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric protected:
1950b57cec5SDimitry Andric   const AVRSubtarget &Subtarget;
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric private:
19806c3fb27SDimitry Andric   MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB,
19906c3fb27SDimitry Andric                                  bool Tiny) const;
200bdd1243dSDimitry Andric   MachineBasicBlock *insertWideShift(MachineInstr &MI,
201bdd1243dSDimitry Andric                                      MachineBasicBlock *BB) const;
2020b57cec5SDimitry Andric   MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const;
203bdd1243dSDimitry Andric   MachineBasicBlock *insertCopyZero(MachineInstr &MI,
20404eeddc0SDimitry Andric                                     MachineBasicBlock *BB) const;
20581ad6265SDimitry Andric   MachineBasicBlock *insertAtomicArithmeticOp(MachineInstr &MI,
20681ad6265SDimitry Andric                                               MachineBasicBlock *BB,
20781ad6265SDimitry Andric                                               unsigned Opcode, int Width) const;
2080b57cec5SDimitry Andric };
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric } // end namespace llvm
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric #endif // LLVM_AVR_ISEL_LOWERING_H
213