xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelLowering.h (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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.
290b57cec5SDimitry Andric   RET_FLAG,
300b57cec5SDimitry Andric   /// Return from ISR.
310b57cec5SDimitry Andric   RETI_FLAG,
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.
410b57cec5SDimitry Andric   LSR,     ///< Logical shift right.
42fe6060f1SDimitry Andric   LSRBN,   ///< Byte logical shift right N bits.
43fe6060f1SDimitry Andric   LSRWN,   ///< Word logical shift right N bits.
440b57cec5SDimitry Andric   ASR,     ///< Arithmetic shift right.
45fe6060f1SDimitry Andric   ASRBN,   ///< Byte arithmetic shift right N bits.
46fe6060f1SDimitry Andric   ASRWN,   ///< Word arithmetic shift right N bits.
470b57cec5SDimitry Andric   ROR,     ///< Bit rotate right.
480b57cec5SDimitry Andric   ROL,     ///< Bit rotate left.
490b57cec5SDimitry Andric   LSLLOOP, ///< A loop of single logical shift left instructions.
500b57cec5SDimitry Andric   LSRLOOP, ///< A loop of single logical shift right instructions.
510b57cec5SDimitry Andric   ROLLOOP, ///< A loop of single left bit rotate instructions.
520b57cec5SDimitry Andric   RORLOOP, ///< A loop of single right bit rotate instructions.
530b57cec5SDimitry Andric   ASRLOOP, ///< A loop of single arithmetic shift right instructions.
540b57cec5SDimitry Andric   /// AVR conditional branches. Operand 0 is the chain operand, operand 1
550b57cec5SDimitry Andric   /// is the block to branch if condition is true, operand 2 is the
560b57cec5SDimitry Andric   /// condition code, and operand 3 is the flag operand produced by a CMP
570b57cec5SDimitry Andric   /// or TEST instruction.
580b57cec5SDimitry Andric   BRCOND,
590b57cec5SDimitry Andric   /// Compare instruction.
600b57cec5SDimitry Andric   CMP,
610b57cec5SDimitry Andric   /// Compare with carry instruction.
620b57cec5SDimitry Andric   CMPC,
630b57cec5SDimitry Andric   /// Test for zero or minus instruction.
640b57cec5SDimitry Andric   TST,
65e8d8bef9SDimitry Andric   /// Swap Rd[7:4] <-> Rd[3:0].
66e8d8bef9SDimitry Andric   SWAP,
670b57cec5SDimitry Andric   /// Operand 0 and operand 1 are selection variable, operand 2
680b57cec5SDimitry Andric   /// is condition code and operand 3 is flag operand.
690b57cec5SDimitry Andric   SELECT_CC
700b57cec5SDimitry Andric };
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric } // end of namespace AVRISD
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric class AVRSubtarget;
750b57cec5SDimitry Andric class AVRTargetMachine;
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric /// Performs target lowering for the AVR.
780b57cec5SDimitry Andric class AVRTargetLowering : public TargetLowering {
790b57cec5SDimitry Andric public:
800b57cec5SDimitry Andric   explicit AVRTargetLowering(const AVRTargetMachine &TM,
810b57cec5SDimitry Andric                              const AVRSubtarget &STI);
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric public:
840b57cec5SDimitry Andric   MVT getScalarShiftAmountTy(const DataLayout &, EVT LHSTy) const override {
850b57cec5SDimitry Andric     return MVT::i8;
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   MVT::SimpleValueType getCmpLibcallReturnType() const override {
890b57cec5SDimitry Andric     return MVT::i8;
900b57cec5SDimitry Andric   }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric   const char *getTargetNodeName(unsigned Opcode) const override;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
970b57cec5SDimitry Andric                           SelectionDAG &DAG) const override;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, Type *Ty,
1000b57cec5SDimitry Andric                              unsigned AS,
1010b57cec5SDimitry Andric                              Instruction *I = nullptr) const override;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   bool getPreIndexedAddressParts(SDNode *N, SDValue &Base, SDValue &Offset,
1040b57cec5SDimitry Andric                                  ISD::MemIndexedMode &AM,
1050b57cec5SDimitry Andric                                  SelectionDAG &DAG) const override;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, SDValue &Base,
1080b57cec5SDimitry Andric                                   SDValue &Offset, ISD::MemIndexedMode &AM,
1090b57cec5SDimitry Andric                                   SelectionDAG &DAG) const override;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   EVT getSetCCResultType(const DataLayout &DL, LLVMContext &Context,
1140b57cec5SDimitry Andric                          EVT VT) const override;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   MachineBasicBlock *
1170b57cec5SDimitry Andric   EmitInstrWithCustomInserter(MachineInstr &MI,
1180b57cec5SDimitry Andric                               MachineBasicBlock *MBB) const override;
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   ConstraintType getConstraintType(StringRef Constraint) const override;
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   ConstraintWeight
1230b57cec5SDimitry Andric   getSingleConstraintMatchWeight(AsmOperandInfo &info,
1240b57cec5SDimitry Andric                                  const char *constraint) const override;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   std::pair<unsigned, const TargetRegisterClass *>
1270b57cec5SDimitry Andric   getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
1280b57cec5SDimitry Andric                                StringRef Constraint, MVT VT) const override;
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric   unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
1330b57cec5SDimitry Andric                                     std::vector<SDValue> &Ops,
1340b57cec5SDimitry Andric                                     SelectionDAG &DAG) const override;
1350b57cec5SDimitry Andric 
136480093f4SDimitry Andric   Register getRegisterByName(const char *RegName, LLT VT,
1378bcb0991SDimitry Andric                              const MachineFunction &MF) const override;
1380b57cec5SDimitry Andric 
139*349cc55cSDimitry Andric   bool shouldSplitFunctionArgumentsAsLittleEndian(
140*349cc55cSDimitry Andric       const DataLayout &DL) const override {
1410b57cec5SDimitry Andric     return false;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric private:
1450b57cec5SDimitry Andric   SDValue getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC, SDValue &AVRcc,
1460b57cec5SDimitry Andric                     SelectionDAG &DAG, SDLoc dl) const;
147e8d8bef9SDimitry Andric   SDValue getAVRCmp(SDValue LHS, SDValue RHS, SelectionDAG &DAG,
148e8d8bef9SDimitry Andric                     SDLoc dl) const;
1490b57cec5SDimitry Andric   SDValue LowerShifts(SDValue Op, SelectionDAG &DAG) const;
1500b57cec5SDimitry Andric   SDValue LowerDivRem(SDValue Op, SelectionDAG &DAG) const;
1510b57cec5SDimitry Andric   SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
1520b57cec5SDimitry Andric   SDValue LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
1530b57cec5SDimitry Andric   SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
1540b57cec5SDimitry Andric   SDValue LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const;
1550b57cec5SDimitry Andric   SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
1560b57cec5SDimitry Andric   SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
1570b57cec5SDimitry Andric   SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
1580b57cec5SDimitry Andric 
1595ffd83dbSDimitry Andric   bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
1605ffd83dbSDimitry Andric                       bool isVarArg,
1610b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
1620b57cec5SDimitry Andric                       LLVMContext &Context) const override;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
1650b57cec5SDimitry Andric                       const SmallVectorImpl<ISD::OutputArg> &Outs,
1660b57cec5SDimitry Andric                       const SmallVectorImpl<SDValue> &OutVals, const SDLoc &dl,
1670b57cec5SDimitry Andric                       SelectionDAG &DAG) const override;
1680b57cec5SDimitry Andric   SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv,
1690b57cec5SDimitry Andric                                bool isVarArg,
1700b57cec5SDimitry Andric                                const SmallVectorImpl<ISD::InputArg> &Ins,
1710b57cec5SDimitry Andric                                const SDLoc &dl, SelectionDAG &DAG,
1720b57cec5SDimitry Andric                                SmallVectorImpl<SDValue> &InVals) const override;
1730b57cec5SDimitry Andric   SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
1740b57cec5SDimitry Andric                     SmallVectorImpl<SDValue> &InVals) const override;
1750b57cec5SDimitry Andric   SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
1760b57cec5SDimitry Andric                           CallingConv::ID CallConv, bool isVarArg,
1770b57cec5SDimitry Andric                           const SmallVectorImpl<ISD::InputArg> &Ins,
1780b57cec5SDimitry Andric                           const SDLoc &dl, SelectionDAG &DAG,
1790b57cec5SDimitry Andric                           SmallVectorImpl<SDValue> &InVals) const;
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric protected:
1820b57cec5SDimitry Andric   const AVRSubtarget &Subtarget;
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric private:
1850b57cec5SDimitry Andric   MachineBasicBlock *insertShift(MachineInstr &MI, MachineBasicBlock *BB) const;
1860b57cec5SDimitry Andric   MachineBasicBlock *insertMul(MachineInstr &MI, MachineBasicBlock *BB) const;
1870b57cec5SDimitry Andric };
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric } // end namespace llvm
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric #endif // LLVM_AVR_ISEL_LOWERING_H
192