xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AVR/AVRISelLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- AVRISelLowering.cpp - AVR DAG Lowering Implementation -------------===//
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 #include "AVRISelLowering.h"
150b57cec5SDimitry Andric 
1681ad6265SDimitry Andric #include "llvm/ADT/ArrayRef.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/STLExtras.h"
18349cc55cSDimitry Andric #include "llvm/ADT/StringSwitch.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
250b57cec5SDimitry Andric #include "llvm/IR/Function.h"
260b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric #include "AVR.h"
290b57cec5SDimitry Andric #include "AVRMachineFunctionInfo.h"
300b57cec5SDimitry Andric #include "AVRSubtarget.h"
310b57cec5SDimitry Andric #include "AVRTargetMachine.h"
320b57cec5SDimitry Andric #include "MCTargetDesc/AVRMCTargetDesc.h"
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric namespace llvm {
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric AVRTargetLowering::AVRTargetLowering(const AVRTargetMachine &TM,
370b57cec5SDimitry Andric                                      const AVRSubtarget &STI)
380b57cec5SDimitry Andric     : TargetLowering(TM), Subtarget(STI) {
390b57cec5SDimitry Andric   // Set up the register classes.
400b57cec5SDimitry Andric   addRegisterClass(MVT::i8, &AVR::GPR8RegClass);
410b57cec5SDimitry Andric   addRegisterClass(MVT::i16, &AVR::DREGSRegClass);
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric   // Compute derived properties from the register classes.
440b57cec5SDimitry Andric   computeRegisterProperties(Subtarget.getRegisterInfo());
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   setBooleanContents(ZeroOrOneBooleanContent);
470b57cec5SDimitry Andric   setBooleanVectorContents(ZeroOrOneBooleanContent);
480b57cec5SDimitry Andric   setSchedulingPreference(Sched::RegPressure);
490b57cec5SDimitry Andric   setStackPointerRegisterToSaveRestore(AVR::SP);
500b57cec5SDimitry Andric   setSupportsUnalignedAtomics(true);
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric   setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
530b57cec5SDimitry Andric   setOperationAction(ISD::BlockAddress, MVT::i16, Custom);
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
560b57cec5SDimitry Andric   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
570b57cec5SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i8, Expand);
580b57cec5SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand);
590b57cec5SDimitry Andric 
60bdd1243dSDimitry Andric   setOperationAction(ISD::INLINEASM, MVT::Other, Custom);
61bdd1243dSDimitry Andric 
620b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
630b57cec5SDimitry Andric     for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
640b57cec5SDimitry Andric       setLoadExtAction(N, VT, MVT::i1, Promote);
650b57cec5SDimitry Andric       setLoadExtAction(N, VT, MVT::i8, Expand);
660b57cec5SDimitry Andric     }
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   setTruncStoreAction(MVT::i16, MVT::i8, Expand);
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
720b57cec5SDimitry Andric     setOperationAction(ISD::ADDC, VT, Legal);
730b57cec5SDimitry Andric     setOperationAction(ISD::SUBC, VT, Legal);
740b57cec5SDimitry Andric     setOperationAction(ISD::ADDE, VT, Legal);
750b57cec5SDimitry Andric     setOperationAction(ISD::SUBE, VT, Legal);
760b57cec5SDimitry Andric   }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   // sub (x, imm) gets canonicalized to add (x, -imm), so for illegal types
790b57cec5SDimitry Andric   // revert into a sub since we don't have an add with immediate instruction.
800b57cec5SDimitry Andric   setOperationAction(ISD::ADD, MVT::i32, Custom);
810b57cec5SDimitry Andric   setOperationAction(ISD::ADD, MVT::i64, Custom);
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   // our shift instructions are only able to shift 1 bit at a time, so handle
840b57cec5SDimitry Andric   // this in a custom way.
850b57cec5SDimitry Andric   setOperationAction(ISD::SRA, MVT::i8, Custom);
860b57cec5SDimitry Andric   setOperationAction(ISD::SHL, MVT::i8, Custom);
870b57cec5SDimitry Andric   setOperationAction(ISD::SRL, MVT::i8, Custom);
880b57cec5SDimitry Andric   setOperationAction(ISD::SRA, MVT::i16, Custom);
890b57cec5SDimitry Andric   setOperationAction(ISD::SHL, MVT::i16, Custom);
900b57cec5SDimitry Andric   setOperationAction(ISD::SRL, MVT::i16, Custom);
91bdd1243dSDimitry Andric   setOperationAction(ISD::SRA, MVT::i32, Custom);
92bdd1243dSDimitry Andric   setOperationAction(ISD::SHL, MVT::i32, Custom);
93bdd1243dSDimitry Andric   setOperationAction(ISD::SRL, MVT::i32, Custom);
940b57cec5SDimitry Andric   setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand);
950b57cec5SDimitry Andric   setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand);
960b57cec5SDimitry Andric   setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   setOperationAction(ISD::ROTL, MVT::i8, Custom);
990b57cec5SDimitry Andric   setOperationAction(ISD::ROTL, MVT::i16, Expand);
1000b57cec5SDimitry Andric   setOperationAction(ISD::ROTR, MVT::i8, Custom);
1010b57cec5SDimitry Andric   setOperationAction(ISD::ROTR, MVT::i16, Expand);
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i8, Custom);
1040b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i16, Custom);
1050b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i32, Custom);
1060b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i64, Custom);
1070b57cec5SDimitry Andric   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
1100b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::i16, Custom);
1110b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::i32, Expand);
1120b57cec5SDimitry Andric   setOperationAction(ISD::SELECT_CC, MVT::i64, Expand);
1130b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::i8, Custom);
1140b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::i16, Custom);
1150b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::i32, Custom);
1160b57cec5SDimitry Andric   setOperationAction(ISD::SETCC, MVT::i64, Custom);
1170b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::i8, Expand);
1180b57cec5SDimitry Andric   setOperationAction(ISD::SELECT, MVT::i16, Expand);
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   setOperationAction(ISD::BSWAP, MVT::i16, Expand);
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   // Add support for postincrement and predecrement load/stores.
1230b57cec5SDimitry Andric   setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
1240b57cec5SDimitry Andric   setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
1250b57cec5SDimitry Andric   setIndexedLoadAction(ISD::PRE_DEC, MVT::i8, Legal);
1260b57cec5SDimitry Andric   setIndexedLoadAction(ISD::PRE_DEC, MVT::i16, Legal);
1270b57cec5SDimitry Andric   setIndexedStoreAction(ISD::POST_INC, MVT::i8, Legal);
1280b57cec5SDimitry Andric   setIndexedStoreAction(ISD::POST_INC, MVT::i16, Legal);
1290b57cec5SDimitry Andric   setIndexedStoreAction(ISD::PRE_DEC, MVT::i8, Legal);
1300b57cec5SDimitry Andric   setIndexedStoreAction(ISD::PRE_DEC, MVT::i16, Legal);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   setOperationAction(ISD::VASTART, MVT::Other, Custom);
1350b57cec5SDimitry Andric   setOperationAction(ISD::VAEND, MVT::Other, Expand);
1360b57cec5SDimitry Andric   setOperationAction(ISD::VAARG, MVT::Other, Expand);
1370b57cec5SDimitry Andric   setOperationAction(ISD::VACOPY, MVT::Other, Expand);
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // Atomic operations which must be lowered to rtlib calls
1400b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
1410b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_SWAP, VT, Expand);
1420b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_CMP_SWAP, VT, Expand);
1430b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_NAND, VT, Expand);
1440b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_MAX, VT, Expand);
1450b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_MIN, VT, Expand);
1460b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_UMAX, VT, Expand);
1470b57cec5SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_UMIN, VT, Expand);
1480b57cec5SDimitry Andric   }
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   // Division/remainder
1510b57cec5SDimitry Andric   setOperationAction(ISD::UDIV, MVT::i8, Expand);
1520b57cec5SDimitry Andric   setOperationAction(ISD::UDIV, MVT::i16, Expand);
1530b57cec5SDimitry Andric   setOperationAction(ISD::UREM, MVT::i8, Expand);
1540b57cec5SDimitry Andric   setOperationAction(ISD::UREM, MVT::i16, Expand);
1550b57cec5SDimitry Andric   setOperationAction(ISD::SDIV, MVT::i8, Expand);
1560b57cec5SDimitry Andric   setOperationAction(ISD::SDIV, MVT::i16, Expand);
1570b57cec5SDimitry Andric   setOperationAction(ISD::SREM, MVT::i8, Expand);
1580b57cec5SDimitry Andric   setOperationAction(ISD::SREM, MVT::i16, Expand);
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric   // Make division and modulus custom
1615ffd83dbSDimitry Andric   setOperationAction(ISD::UDIVREM, MVT::i8, Custom);
1625ffd83dbSDimitry Andric   setOperationAction(ISD::UDIVREM, MVT::i16, Custom);
1635ffd83dbSDimitry Andric   setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
1645ffd83dbSDimitry Andric   setOperationAction(ISD::SDIVREM, MVT::i8, Custom);
1655ffd83dbSDimitry Andric   setOperationAction(ISD::SDIVREM, MVT::i16, Custom);
1665ffd83dbSDimitry Andric   setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   // Do not use MUL. The AVR instructions are closer to SMUL_LOHI &co.
1690b57cec5SDimitry Andric   setOperationAction(ISD::MUL, MVT::i8, Expand);
1700b57cec5SDimitry Andric   setOperationAction(ISD::MUL, MVT::i16, Expand);
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   // Expand 16 bit multiplications.
1730b57cec5SDimitry Andric   setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand);
1740b57cec5SDimitry Andric   setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand);
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   // Expand multiplications to libcalls when there is
1770b57cec5SDimitry Andric   // no hardware MUL.
1780b57cec5SDimitry Andric   if (!Subtarget.supportsMultiplication()) {
1790b57cec5SDimitry Andric     setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
1800b57cec5SDimitry Andric     setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
1810b57cec5SDimitry Andric   }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
1840b57cec5SDimitry Andric     setOperationAction(ISD::MULHS, VT, Expand);
1850b57cec5SDimitry Andric     setOperationAction(ISD::MULHU, VT, Expand);
1860b57cec5SDimitry Andric   }
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
1890b57cec5SDimitry Andric     setOperationAction(ISD::CTPOP, VT, Expand);
1900b57cec5SDimitry Andric     setOperationAction(ISD::CTLZ, VT, Expand);
1910b57cec5SDimitry Andric     setOperationAction(ISD::CTTZ, VT, Expand);
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
1950b57cec5SDimitry Andric     setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand);
1960b57cec5SDimitry Andric     // TODO: The generated code is pretty poor. Investigate using the
1970b57cec5SDimitry Andric     // same "shift and subtract with carry" trick that we do for
1980b57cec5SDimitry Andric     // extending 8-bit to 16-bit. This may require infrastructure
1990b57cec5SDimitry Andric     // improvements in how we treat 16-bit "registers" to be feasible.
2000b57cec5SDimitry Andric   }
2010b57cec5SDimitry Andric 
2020b57cec5SDimitry Andric   // Division and modulus rtlib functions
2030b57cec5SDimitry Andric   setLibcallName(RTLIB::SDIVREM_I8, "__divmodqi4");
2040b57cec5SDimitry Andric   setLibcallName(RTLIB::SDIVREM_I16, "__divmodhi4");
2050b57cec5SDimitry Andric   setLibcallName(RTLIB::SDIVREM_I32, "__divmodsi4");
2060b57cec5SDimitry Andric   setLibcallName(RTLIB::UDIVREM_I8, "__udivmodqi4");
2070b57cec5SDimitry Andric   setLibcallName(RTLIB::UDIVREM_I16, "__udivmodhi4");
2080b57cec5SDimitry Andric   setLibcallName(RTLIB::UDIVREM_I32, "__udivmodsi4");
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   // Several of the runtime library functions use a special calling conv
2110b57cec5SDimitry Andric   setLibcallCallingConv(RTLIB::SDIVREM_I8, CallingConv::AVR_BUILTIN);
2120b57cec5SDimitry Andric   setLibcallCallingConv(RTLIB::SDIVREM_I16, CallingConv::AVR_BUILTIN);
2130b57cec5SDimitry Andric   setLibcallCallingConv(RTLIB::UDIVREM_I8, CallingConv::AVR_BUILTIN);
2140b57cec5SDimitry Andric   setLibcallCallingConv(RTLIB::UDIVREM_I16, CallingConv::AVR_BUILTIN);
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   // Trigonometric rtlib functions
2170b57cec5SDimitry Andric   setLibcallName(RTLIB::SIN_F32, "sin");
2180b57cec5SDimitry Andric   setLibcallName(RTLIB::COS_F32, "cos");
2190b57cec5SDimitry Andric 
2208bcb0991SDimitry Andric   setMinFunctionAlignment(Align(2));
2210b57cec5SDimitry Andric   setMinimumJumpTableEntries(UINT_MAX);
2220b57cec5SDimitry Andric }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric const char *AVRTargetLowering::getTargetNodeName(unsigned Opcode) const {
2250b57cec5SDimitry Andric #define NODE(name)                                                             \
2260b57cec5SDimitry Andric   case AVRISD::name:                                                           \
2270b57cec5SDimitry Andric     return #name
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   switch (Opcode) {
2300b57cec5SDimitry Andric   default:
2310b57cec5SDimitry Andric     return nullptr;
23206c3fb27SDimitry Andric     NODE(RET_GLUE);
23306c3fb27SDimitry Andric     NODE(RETI_GLUE);
2340b57cec5SDimitry Andric     NODE(CALL);
2350b57cec5SDimitry Andric     NODE(WRAPPER);
2360b57cec5SDimitry Andric     NODE(LSL);
237bdd1243dSDimitry Andric     NODE(LSLW);
2380b57cec5SDimitry Andric     NODE(LSR);
239bdd1243dSDimitry Andric     NODE(LSRW);
2400b57cec5SDimitry Andric     NODE(ROL);
2410b57cec5SDimitry Andric     NODE(ROR);
2420b57cec5SDimitry Andric     NODE(ASR);
243bdd1243dSDimitry Andric     NODE(ASRW);
2440b57cec5SDimitry Andric     NODE(LSLLOOP);
2450b57cec5SDimitry Andric     NODE(LSRLOOP);
2465ffd83dbSDimitry Andric     NODE(ROLLOOP);
2475ffd83dbSDimitry Andric     NODE(RORLOOP);
2480b57cec5SDimitry Andric     NODE(ASRLOOP);
2490b57cec5SDimitry Andric     NODE(BRCOND);
2500b57cec5SDimitry Andric     NODE(CMP);
2510b57cec5SDimitry Andric     NODE(CMPC);
2520b57cec5SDimitry Andric     NODE(TST);
2530b57cec5SDimitry Andric     NODE(SELECT_CC);
2540b57cec5SDimitry Andric #undef NODE
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric EVT AVRTargetLowering::getSetCCResultType(const DataLayout &DL, LLVMContext &,
2590b57cec5SDimitry Andric                                           EVT VT) const {
2600b57cec5SDimitry Andric   assert(!VT.isVector() && "No AVR SetCC type for vectors!");
2610b57cec5SDimitry Andric   return MVT::i8;
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
2650b57cec5SDimitry Andric   unsigned Opc8;
2660b57cec5SDimitry Andric   const SDNode *N = Op.getNode();
2670b57cec5SDimitry Andric   EVT VT = Op.getValueType();
2680b57cec5SDimitry Andric   SDLoc dl(N);
26906c3fb27SDimitry Andric   assert(llvm::has_single_bit<uint32_t>(VT.getSizeInBits()) &&
2705ffd83dbSDimitry Andric          "Expected power-of-2 shift amount");
2710b57cec5SDimitry Andric 
272bdd1243dSDimitry Andric   if (VT.getSizeInBits() == 32) {
273bdd1243dSDimitry Andric     if (!isa<ConstantSDNode>(N->getOperand(1))) {
274bdd1243dSDimitry Andric       // 32-bit shifts are converted to a loop in IR.
275bdd1243dSDimitry Andric       // This should be unreachable.
276bdd1243dSDimitry Andric       report_fatal_error("Expected a constant shift amount!");
277bdd1243dSDimitry Andric     }
278bdd1243dSDimitry Andric     SDVTList ResTys = DAG.getVTList(MVT::i16, MVT::i16);
279bdd1243dSDimitry Andric     SDValue SrcLo =
280bdd1243dSDimitry Andric         DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i16, Op.getOperand(0),
281bdd1243dSDimitry Andric                     DAG.getConstant(0, dl, MVT::i16));
282bdd1243dSDimitry Andric     SDValue SrcHi =
283bdd1243dSDimitry Andric         DAG.getNode(ISD::EXTRACT_ELEMENT, dl, MVT::i16, Op.getOperand(0),
284bdd1243dSDimitry Andric                     DAG.getConstant(1, dl, MVT::i16));
285647cbc5dSDimitry Andric     uint64_t ShiftAmount = N->getConstantOperandVal(1);
286bdd1243dSDimitry Andric     if (ShiftAmount == 16) {
287bdd1243dSDimitry Andric       // Special case these two operations because they appear to be used by the
288bdd1243dSDimitry Andric       // generic codegen parts to lower 32-bit numbers.
289bdd1243dSDimitry Andric       // TODO: perhaps we can lower shift amounts bigger than 16 to a 16-bit
290bdd1243dSDimitry Andric       // shift of a part of the 32-bit value?
291bdd1243dSDimitry Andric       switch (Op.getOpcode()) {
292bdd1243dSDimitry Andric       case ISD::SHL: {
293bdd1243dSDimitry Andric         SDValue Zero = DAG.getConstant(0, dl, MVT::i16);
294bdd1243dSDimitry Andric         return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, Zero, SrcLo);
295bdd1243dSDimitry Andric       }
296bdd1243dSDimitry Andric       case ISD::SRL: {
297bdd1243dSDimitry Andric         SDValue Zero = DAG.getConstant(0, dl, MVT::i16);
298bdd1243dSDimitry Andric         return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, SrcHi, Zero);
299bdd1243dSDimitry Andric       }
300bdd1243dSDimitry Andric       }
301bdd1243dSDimitry Andric     }
302bdd1243dSDimitry Andric     SDValue Cnt = DAG.getTargetConstant(ShiftAmount, dl, MVT::i8);
303bdd1243dSDimitry Andric     unsigned Opc;
304bdd1243dSDimitry Andric     switch (Op.getOpcode()) {
305bdd1243dSDimitry Andric     default:
306bdd1243dSDimitry Andric       llvm_unreachable("Invalid 32-bit shift opcode!");
307bdd1243dSDimitry Andric     case ISD::SHL:
308bdd1243dSDimitry Andric       Opc = AVRISD::LSLW;
309bdd1243dSDimitry Andric       break;
310bdd1243dSDimitry Andric     case ISD::SRL:
311bdd1243dSDimitry Andric       Opc = AVRISD::LSRW;
312bdd1243dSDimitry Andric       break;
313bdd1243dSDimitry Andric     case ISD::SRA:
314bdd1243dSDimitry Andric       Opc = AVRISD::ASRW;
315bdd1243dSDimitry Andric       break;
316bdd1243dSDimitry Andric     }
317bdd1243dSDimitry Andric     SDValue Result = DAG.getNode(Opc, dl, ResTys, SrcLo, SrcHi, Cnt);
318bdd1243dSDimitry Andric     return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i32, Result.getValue(0),
319bdd1243dSDimitry Andric                        Result.getValue(1));
320bdd1243dSDimitry Andric   }
321bdd1243dSDimitry Andric 
3220b57cec5SDimitry Andric   // Expand non-constant shifts to loops.
3230b57cec5SDimitry Andric   if (!isa<ConstantSDNode>(N->getOperand(1))) {
3240b57cec5SDimitry Andric     switch (Op.getOpcode()) {
3250b57cec5SDimitry Andric     default:
3260b57cec5SDimitry Andric       llvm_unreachable("Invalid shift opcode!");
3270b57cec5SDimitry Andric     case ISD::SHL:
3280b57cec5SDimitry Andric       return DAG.getNode(AVRISD::LSLLOOP, dl, VT, N->getOperand(0),
3290b57cec5SDimitry Andric                          N->getOperand(1));
3300b57cec5SDimitry Andric     case ISD::SRL:
3310b57cec5SDimitry Andric       return DAG.getNode(AVRISD::LSRLOOP, dl, VT, N->getOperand(0),
3320b57cec5SDimitry Andric                          N->getOperand(1));
3335ffd83dbSDimitry Andric     case ISD::ROTL: {
3345ffd83dbSDimitry Andric       SDValue Amt = N->getOperand(1);
3355ffd83dbSDimitry Andric       EVT AmtVT = Amt.getValueType();
3365ffd83dbSDimitry Andric       Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt,
3375ffd83dbSDimitry Andric                         DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT));
3385ffd83dbSDimitry Andric       return DAG.getNode(AVRISD::ROLLOOP, dl, VT, N->getOperand(0), Amt);
3395ffd83dbSDimitry Andric     }
3405ffd83dbSDimitry Andric     case ISD::ROTR: {
3415ffd83dbSDimitry Andric       SDValue Amt = N->getOperand(1);
3425ffd83dbSDimitry Andric       EVT AmtVT = Amt.getValueType();
3435ffd83dbSDimitry Andric       Amt = DAG.getNode(ISD::AND, dl, AmtVT, Amt,
3445ffd83dbSDimitry Andric                         DAG.getConstant(VT.getSizeInBits() - 1, dl, AmtVT));
3455ffd83dbSDimitry Andric       return DAG.getNode(AVRISD::RORLOOP, dl, VT, N->getOperand(0), Amt);
3465ffd83dbSDimitry Andric     }
3470b57cec5SDimitry Andric     case ISD::SRA:
3480b57cec5SDimitry Andric       return DAG.getNode(AVRISD::ASRLOOP, dl, VT, N->getOperand(0),
3490b57cec5SDimitry Andric                          N->getOperand(1));
3500b57cec5SDimitry Andric     }
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric 
353647cbc5dSDimitry Andric   uint64_t ShiftAmount = N->getConstantOperandVal(1);
3540b57cec5SDimitry Andric   SDValue Victim = N->getOperand(0);
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   switch (Op.getOpcode()) {
3570b57cec5SDimitry Andric   case ISD::SRA:
3580b57cec5SDimitry Andric     Opc8 = AVRISD::ASR;
3590b57cec5SDimitry Andric     break;
3600b57cec5SDimitry Andric   case ISD::ROTL:
3610b57cec5SDimitry Andric     Opc8 = AVRISD::ROL;
3625ffd83dbSDimitry Andric     ShiftAmount = ShiftAmount % VT.getSizeInBits();
3630b57cec5SDimitry Andric     break;
3640b57cec5SDimitry Andric   case ISD::ROTR:
3650b57cec5SDimitry Andric     Opc8 = AVRISD::ROR;
3665ffd83dbSDimitry Andric     ShiftAmount = ShiftAmount % VT.getSizeInBits();
3670b57cec5SDimitry Andric     break;
3680b57cec5SDimitry Andric   case ISD::SRL:
3690b57cec5SDimitry Andric     Opc8 = AVRISD::LSR;
3700b57cec5SDimitry Andric     break;
3710b57cec5SDimitry Andric   case ISD::SHL:
3720b57cec5SDimitry Andric     Opc8 = AVRISD::LSL;
3730b57cec5SDimitry Andric     break;
3740b57cec5SDimitry Andric   default:
3750b57cec5SDimitry Andric     llvm_unreachable("Invalid shift opcode");
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric 
378fe6060f1SDimitry Andric   // Optimize int8/int16 shifts.
379e8d8bef9SDimitry Andric   if (VT.getSizeInBits() == 8) {
380e8d8bef9SDimitry Andric     if (Op.getOpcode() == ISD::SHL && 4 <= ShiftAmount && ShiftAmount < 7) {
381e8d8bef9SDimitry Andric       // Optimize LSL when 4 <= ShiftAmount <= 6.
382e8d8bef9SDimitry Andric       Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim);
383e8d8bef9SDimitry Andric       Victim =
384e8d8bef9SDimitry Andric           DAG.getNode(ISD::AND, dl, VT, Victim, DAG.getConstant(0xf0, dl, VT));
385e8d8bef9SDimitry Andric       ShiftAmount -= 4;
386e8d8bef9SDimitry Andric     } else if (Op.getOpcode() == ISD::SRL && 4 <= ShiftAmount &&
387e8d8bef9SDimitry Andric                ShiftAmount < 7) {
388e8d8bef9SDimitry Andric       // Optimize LSR when 4 <= ShiftAmount <= 6.
389e8d8bef9SDimitry Andric       Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim);
390e8d8bef9SDimitry Andric       Victim =
391e8d8bef9SDimitry Andric           DAG.getNode(ISD::AND, dl, VT, Victim, DAG.getConstant(0x0f, dl, VT));
392e8d8bef9SDimitry Andric       ShiftAmount -= 4;
393e8d8bef9SDimitry Andric     } else if (Op.getOpcode() == ISD::SHL && ShiftAmount == 7) {
394e8d8bef9SDimitry Andric       // Optimize LSL when ShiftAmount == 7.
395fe6060f1SDimitry Andric       Victim = DAG.getNode(AVRISD::LSLBN, dl, VT, Victim,
396fe6060f1SDimitry Andric                            DAG.getConstant(7, dl, VT));
397e8d8bef9SDimitry Andric       ShiftAmount = 0;
398e8d8bef9SDimitry Andric     } else if (Op.getOpcode() == ISD::SRL && ShiftAmount == 7) {
399e8d8bef9SDimitry Andric       // Optimize LSR when ShiftAmount == 7.
400fe6060f1SDimitry Andric       Victim = DAG.getNode(AVRISD::LSRBN, dl, VT, Victim,
401fe6060f1SDimitry Andric                            DAG.getConstant(7, dl, VT));
402e8d8bef9SDimitry Andric       ShiftAmount = 0;
40304eeddc0SDimitry Andric     } else if (Op.getOpcode() == ISD::SRA && ShiftAmount == 6) {
40404eeddc0SDimitry Andric       // Optimize ASR when ShiftAmount == 6.
40504eeddc0SDimitry Andric       Victim = DAG.getNode(AVRISD::ASRBN, dl, VT, Victim,
40604eeddc0SDimitry Andric                            DAG.getConstant(6, dl, VT));
40704eeddc0SDimitry Andric       ShiftAmount = 0;
408e8d8bef9SDimitry Andric     } else if (Op.getOpcode() == ISD::SRA && ShiftAmount == 7) {
409e8d8bef9SDimitry Andric       // Optimize ASR when ShiftAmount == 7.
410fe6060f1SDimitry Andric       Victim = DAG.getNode(AVRISD::ASRBN, dl, VT, Victim,
411fe6060f1SDimitry Andric                            DAG.getConstant(7, dl, VT));
412e8d8bef9SDimitry Andric       ShiftAmount = 0;
41306c3fb27SDimitry Andric     } else if (Op.getOpcode() == ISD::ROTL && ShiftAmount == 3) {
41406c3fb27SDimitry Andric       // Optimize left rotation 3 bits to swap then right rotation 1 bit.
41506c3fb27SDimitry Andric       Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim);
41606c3fb27SDimitry Andric       Victim =
41706c3fb27SDimitry Andric           DAG.getNode(AVRISD::ROR, dl, VT, Victim, DAG.getConstant(1, dl, VT));
41806c3fb27SDimitry Andric       ShiftAmount = 0;
41906c3fb27SDimitry Andric     } else if (Op.getOpcode() == ISD::ROTR && ShiftAmount == 3) {
42006c3fb27SDimitry Andric       // Optimize right rotation 3 bits to swap then left rotation 1 bit.
42106c3fb27SDimitry Andric       Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim);
42206c3fb27SDimitry Andric       Victim =
42306c3fb27SDimitry Andric           DAG.getNode(AVRISD::ROL, dl, VT, Victim, DAG.getConstant(1, dl, VT));
42406c3fb27SDimitry Andric       ShiftAmount = 0;
42506c3fb27SDimitry Andric     } else if (Op.getOpcode() == ISD::ROTL && ShiftAmount == 7) {
42606c3fb27SDimitry Andric       // Optimize left rotation 7 bits to right rotation 1 bit.
42706c3fb27SDimitry Andric       Victim =
42806c3fb27SDimitry Andric           DAG.getNode(AVRISD::ROR, dl, VT, Victim, DAG.getConstant(1, dl, VT));
42906c3fb27SDimitry Andric       ShiftAmount = 0;
43006c3fb27SDimitry Andric     } else if (Op.getOpcode() == ISD::ROTR && ShiftAmount == 7) {
43106c3fb27SDimitry Andric       // Optimize right rotation 7 bits to left rotation 1 bit.
43206c3fb27SDimitry Andric       Victim =
43306c3fb27SDimitry Andric           DAG.getNode(AVRISD::ROL, dl, VT, Victim, DAG.getConstant(1, dl, VT));
43406c3fb27SDimitry Andric       ShiftAmount = 0;
43506c3fb27SDimitry Andric     } else if ((Op.getOpcode() == ISD::ROTR || Op.getOpcode() == ISD::ROTL) &&
43606c3fb27SDimitry Andric                ShiftAmount >= 4) {
43706c3fb27SDimitry Andric       // Optimize left/right rotation with the SWAP instruction.
43806c3fb27SDimitry Andric       Victim = DAG.getNode(AVRISD::SWAP, dl, VT, Victim);
43906c3fb27SDimitry Andric       ShiftAmount -= 4;
440e8d8bef9SDimitry Andric     }
441fe6060f1SDimitry Andric   } else if (VT.getSizeInBits() == 16) {
44281ad6265SDimitry Andric     if (Op.getOpcode() == ISD::SRA)
44381ad6265SDimitry Andric       // Special optimization for int16 arithmetic right shift.
44481ad6265SDimitry Andric       switch (ShiftAmount) {
44581ad6265SDimitry Andric       case 15:
44681ad6265SDimitry Andric         Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
44781ad6265SDimitry Andric                              DAG.getConstant(15, dl, VT));
44881ad6265SDimitry Andric         ShiftAmount = 0;
44981ad6265SDimitry Andric         break;
45081ad6265SDimitry Andric       case 14:
45181ad6265SDimitry Andric         Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
45281ad6265SDimitry Andric                              DAG.getConstant(14, dl, VT));
45381ad6265SDimitry Andric         ShiftAmount = 0;
45481ad6265SDimitry Andric         break;
45581ad6265SDimitry Andric       case 7:
45681ad6265SDimitry Andric         Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
45781ad6265SDimitry Andric                              DAG.getConstant(7, dl, VT));
45881ad6265SDimitry Andric         ShiftAmount = 0;
45981ad6265SDimitry Andric         break;
46081ad6265SDimitry Andric       default:
46181ad6265SDimitry Andric         break;
46281ad6265SDimitry Andric       }
463fe6060f1SDimitry Andric     if (4 <= ShiftAmount && ShiftAmount < 8)
464fe6060f1SDimitry Andric       switch (Op.getOpcode()) {
465fe6060f1SDimitry Andric       case ISD::SHL:
466fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
467fe6060f1SDimitry Andric                              DAG.getConstant(4, dl, VT));
468fe6060f1SDimitry Andric         ShiftAmount -= 4;
469fe6060f1SDimitry Andric         break;
470fe6060f1SDimitry Andric       case ISD::SRL:
471fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
472fe6060f1SDimitry Andric                              DAG.getConstant(4, dl, VT));
473fe6060f1SDimitry Andric         ShiftAmount -= 4;
474fe6060f1SDimitry Andric         break;
475fe6060f1SDimitry Andric       default:
476fe6060f1SDimitry Andric         break;
477fe6060f1SDimitry Andric       }
478fe6060f1SDimitry Andric     else if (8 <= ShiftAmount && ShiftAmount < 12)
479fe6060f1SDimitry Andric       switch (Op.getOpcode()) {
480fe6060f1SDimitry Andric       case ISD::SHL:
481fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
482fe6060f1SDimitry Andric                              DAG.getConstant(8, dl, VT));
483fe6060f1SDimitry Andric         ShiftAmount -= 8;
48404eeddc0SDimitry Andric         // Only operate on the higher byte for remaining shift bits.
48504eeddc0SDimitry Andric         Opc8 = AVRISD::LSLHI;
486fe6060f1SDimitry Andric         break;
487fe6060f1SDimitry Andric       case ISD::SRL:
488fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
489fe6060f1SDimitry Andric                              DAG.getConstant(8, dl, VT));
490fe6060f1SDimitry Andric         ShiftAmount -= 8;
49104eeddc0SDimitry Andric         // Only operate on the lower byte for remaining shift bits.
49204eeddc0SDimitry Andric         Opc8 = AVRISD::LSRLO;
493fe6060f1SDimitry Andric         break;
494fe6060f1SDimitry Andric       case ISD::SRA:
495fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
496fe6060f1SDimitry Andric                              DAG.getConstant(8, dl, VT));
497fe6060f1SDimitry Andric         ShiftAmount -= 8;
49804eeddc0SDimitry Andric         // Only operate on the lower byte for remaining shift bits.
49904eeddc0SDimitry Andric         Opc8 = AVRISD::ASRLO;
500fe6060f1SDimitry Andric         break;
501fe6060f1SDimitry Andric       default:
502fe6060f1SDimitry Andric         break;
503fe6060f1SDimitry Andric       }
504fe6060f1SDimitry Andric     else if (12 <= ShiftAmount)
505fe6060f1SDimitry Andric       switch (Op.getOpcode()) {
506fe6060f1SDimitry Andric       case ISD::SHL:
507fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSLWN, dl, VT, Victim,
508fe6060f1SDimitry Andric                              DAG.getConstant(12, dl, VT));
509fe6060f1SDimitry Andric         ShiftAmount -= 12;
51004eeddc0SDimitry Andric         // Only operate on the higher byte for remaining shift bits.
51104eeddc0SDimitry Andric         Opc8 = AVRISD::LSLHI;
512fe6060f1SDimitry Andric         break;
513fe6060f1SDimitry Andric       case ISD::SRL:
514fe6060f1SDimitry Andric         Victim = DAG.getNode(AVRISD::LSRWN, dl, VT, Victim,
515fe6060f1SDimitry Andric                              DAG.getConstant(12, dl, VT));
516fe6060f1SDimitry Andric         ShiftAmount -= 12;
51704eeddc0SDimitry Andric         // Only operate on the lower byte for remaining shift bits.
51804eeddc0SDimitry Andric         Opc8 = AVRISD::LSRLO;
51904eeddc0SDimitry Andric         break;
52004eeddc0SDimitry Andric       case ISD::SRA:
52104eeddc0SDimitry Andric         Victim = DAG.getNode(AVRISD::ASRWN, dl, VT, Victim,
52204eeddc0SDimitry Andric                              DAG.getConstant(8, dl, VT));
52304eeddc0SDimitry Andric         ShiftAmount -= 8;
52404eeddc0SDimitry Andric         // Only operate on the lower byte for remaining shift bits.
52504eeddc0SDimitry Andric         Opc8 = AVRISD::ASRLO;
526fe6060f1SDimitry Andric         break;
527fe6060f1SDimitry Andric       default:
528fe6060f1SDimitry Andric         break;
529fe6060f1SDimitry Andric       }
530e8d8bef9SDimitry Andric   }
531e8d8bef9SDimitry Andric 
5320b57cec5SDimitry Andric   while (ShiftAmount--) {
5330b57cec5SDimitry Andric     Victim = DAG.getNode(Opc8, dl, VT, Victim);
5340b57cec5SDimitry Andric   }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   return Victim;
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerDivRem(SDValue Op, SelectionDAG &DAG) const {
5400b57cec5SDimitry Andric   unsigned Opcode = Op->getOpcode();
5410b57cec5SDimitry Andric   assert((Opcode == ISD::SDIVREM || Opcode == ISD::UDIVREM) &&
5420b57cec5SDimitry Andric          "Invalid opcode for Div/Rem lowering");
5430b57cec5SDimitry Andric   bool IsSigned = (Opcode == ISD::SDIVREM);
5440b57cec5SDimitry Andric   EVT VT = Op->getValueType(0);
5450b57cec5SDimitry Andric   Type *Ty = VT.getTypeForEVT(*DAG.getContext());
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   RTLIB::Libcall LC;
5480b57cec5SDimitry Andric   switch (VT.getSimpleVT().SimpleTy) {
5490b57cec5SDimitry Andric   default:
5500b57cec5SDimitry Andric     llvm_unreachable("Unexpected request for libcall!");
5510b57cec5SDimitry Andric   case MVT::i8:
5520b57cec5SDimitry Andric     LC = IsSigned ? RTLIB::SDIVREM_I8 : RTLIB::UDIVREM_I8;
5530b57cec5SDimitry Andric     break;
5540b57cec5SDimitry Andric   case MVT::i16:
5550b57cec5SDimitry Andric     LC = IsSigned ? RTLIB::SDIVREM_I16 : RTLIB::UDIVREM_I16;
5560b57cec5SDimitry Andric     break;
5570b57cec5SDimitry Andric   case MVT::i32:
5580b57cec5SDimitry Andric     LC = IsSigned ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
5590b57cec5SDimitry Andric     break;
5600b57cec5SDimitry Andric   }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   SDValue InChain = DAG.getEntryNode();
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   TargetLowering::ArgListTy Args;
5650b57cec5SDimitry Andric   TargetLowering::ArgListEntry Entry;
5660b57cec5SDimitry Andric   for (SDValue const &Value : Op->op_values()) {
5670b57cec5SDimitry Andric     Entry.Node = Value;
5680b57cec5SDimitry Andric     Entry.Ty = Value.getValueType().getTypeForEVT(*DAG.getContext());
5690b57cec5SDimitry Andric     Entry.IsSExt = IsSigned;
5700b57cec5SDimitry Andric     Entry.IsZExt = !IsSigned;
5710b57cec5SDimitry Andric     Args.push_back(Entry);
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   SDValue Callee = DAG.getExternalSymbol(getLibcallName(LC),
5750b57cec5SDimitry Andric                                          getPointerTy(DAG.getDataLayout()));
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   Type *RetTy = (Type *)StructType::get(Ty, Ty);
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   SDLoc dl(Op);
5800b57cec5SDimitry Andric   TargetLowering::CallLoweringInfo CLI(DAG);
5810b57cec5SDimitry Andric   CLI.setDebugLoc(dl)
5820b57cec5SDimitry Andric       .setChain(InChain)
5830b57cec5SDimitry Andric       .setLibCallee(getLibcallCallingConv(LC), RetTy, Callee, std::move(Args))
5840b57cec5SDimitry Andric       .setInRegister()
5850b57cec5SDimitry Andric       .setSExtResult(IsSigned)
5860b57cec5SDimitry Andric       .setZExtResult(!IsSigned);
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   std::pair<SDValue, SDValue> CallInfo = LowerCallTo(CLI);
5890b57cec5SDimitry Andric   return CallInfo.first;
5900b57cec5SDimitry Andric }
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerGlobalAddress(SDValue Op,
5930b57cec5SDimitry Andric                                               SelectionDAG &DAG) const {
5940b57cec5SDimitry Andric   auto DL = DAG.getDataLayout();
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric   const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
5970b57cec5SDimitry Andric   int64_t Offset = cast<GlobalAddressSDNode>(Op)->getOffset();
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   // Create the TargetGlobalAddress node, folding in the constant offset.
6000b57cec5SDimitry Andric   SDValue Result =
6010b57cec5SDimitry Andric       DAG.getTargetGlobalAddress(GV, SDLoc(Op), getPointerTy(DL), Offset);
6020b57cec5SDimitry Andric   return DAG.getNode(AVRISD::WRAPPER, SDLoc(Op), getPointerTy(DL), Result);
6030b57cec5SDimitry Andric }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerBlockAddress(SDValue Op,
6060b57cec5SDimitry Andric                                              SelectionDAG &DAG) const {
6070b57cec5SDimitry Andric   auto DL = DAG.getDataLayout();
6080b57cec5SDimitry Andric   const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress();
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   SDValue Result = DAG.getTargetBlockAddress(BA, getPointerTy(DL));
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   return DAG.getNode(AVRISD::WRAPPER, SDLoc(Op), getPointerTy(DL), Result);
6130b57cec5SDimitry Andric }
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric /// IntCCToAVRCC - Convert a DAG integer condition code to an AVR CC.
6160b57cec5SDimitry Andric static AVRCC::CondCodes intCCToAVRCC(ISD::CondCode CC) {
6170b57cec5SDimitry Andric   switch (CC) {
6180b57cec5SDimitry Andric   default:
6190b57cec5SDimitry Andric     llvm_unreachable("Unknown condition code!");
6200b57cec5SDimitry Andric   case ISD::SETEQ:
6210b57cec5SDimitry Andric     return AVRCC::COND_EQ;
6220b57cec5SDimitry Andric   case ISD::SETNE:
6230b57cec5SDimitry Andric     return AVRCC::COND_NE;
6240b57cec5SDimitry Andric   case ISD::SETGE:
6250b57cec5SDimitry Andric     return AVRCC::COND_GE;
6260b57cec5SDimitry Andric   case ISD::SETLT:
6270b57cec5SDimitry Andric     return AVRCC::COND_LT;
6280b57cec5SDimitry Andric   case ISD::SETUGE:
6290b57cec5SDimitry Andric     return AVRCC::COND_SH;
6300b57cec5SDimitry Andric   case ISD::SETULT:
6310b57cec5SDimitry Andric     return AVRCC::COND_LO;
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric }
6340b57cec5SDimitry Andric 
635e8d8bef9SDimitry Andric /// Returns appropriate CP/CPI/CPC nodes code for the given 8/16-bit operands.
636e8d8bef9SDimitry Andric SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS,
637e8d8bef9SDimitry Andric                                      SelectionDAG &DAG, SDLoc DL) const {
638e8d8bef9SDimitry Andric   assert((LHS.getSimpleValueType() == RHS.getSimpleValueType()) &&
639e8d8bef9SDimitry Andric          "LHS and RHS have different types");
640e8d8bef9SDimitry Andric   assert(((LHS.getSimpleValueType() == MVT::i16) ||
641349cc55cSDimitry Andric           (LHS.getSimpleValueType() == MVT::i8)) &&
642349cc55cSDimitry Andric          "invalid comparison type");
643e8d8bef9SDimitry Andric 
644e8d8bef9SDimitry Andric   SDValue Cmp;
645e8d8bef9SDimitry Andric 
646fe6060f1SDimitry Andric   if (LHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(RHS)) {
6471db9f3b2SDimitry Andric     uint64_t Imm = RHS->getAsZExtVal();
64806c3fb27SDimitry Andric     // Generate a CPI/CPC pair if RHS is a 16-bit constant. Use the zero
64906c3fb27SDimitry Andric     // register for the constant RHS if its lower or higher byte is zero.
650e8d8bef9SDimitry Andric     SDValue LHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS,
651e8d8bef9SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
652e8d8bef9SDimitry Andric     SDValue LHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS,
653e8d8bef9SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
65406c3fb27SDimitry Andric     SDValue RHSlo = (Imm & 0xff) == 0
65506c3fb27SDimitry Andric                         ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)
65606c3fb27SDimitry Andric                         : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS,
65706c3fb27SDimitry Andric                                       DAG.getIntPtrConstant(0, DL));
65806c3fb27SDimitry Andric     SDValue RHShi = (Imm & 0xff00) == 0
65906c3fb27SDimitry Andric                         ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)
66006c3fb27SDimitry Andric                         : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS,
66106c3fb27SDimitry Andric                                       DAG.getIntPtrConstant(1, DL));
66206c3fb27SDimitry Andric     Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHSlo, RHSlo);
66306c3fb27SDimitry Andric     Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp);
66406c3fb27SDimitry Andric   } else if (RHS.getSimpleValueType() == MVT::i16 && isa<ConstantSDNode>(LHS)) {
66506c3fb27SDimitry Andric     // Generate a CPI/CPC pair if LHS is a 16-bit constant. Use the zero
66606c3fb27SDimitry Andric     // register for the constant LHS if its lower or higher byte is zero.
6671db9f3b2SDimitry Andric     uint64_t Imm = LHS->getAsZExtVal();
66806c3fb27SDimitry Andric     SDValue LHSlo = (Imm & 0xff) == 0
66906c3fb27SDimitry Andric                         ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)
67006c3fb27SDimitry Andric                         : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS,
67106c3fb27SDimitry Andric                                       DAG.getIntPtrConstant(0, DL));
67206c3fb27SDimitry Andric     SDValue LHShi = (Imm & 0xff00) == 0
67306c3fb27SDimitry Andric                         ? DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8)
67406c3fb27SDimitry Andric                         : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS,
67506c3fb27SDimitry Andric                                       DAG.getIntPtrConstant(1, DL));
676e8d8bef9SDimitry Andric     SDValue RHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS,
677e8d8bef9SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
678e8d8bef9SDimitry Andric     SDValue RHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, RHS,
679e8d8bef9SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
680e8d8bef9SDimitry Andric     Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHSlo, RHSlo);
681e8d8bef9SDimitry Andric     Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp);
682e8d8bef9SDimitry Andric   } else {
683e8d8bef9SDimitry Andric     // Generate ordinary 16-bit comparison.
684e8d8bef9SDimitry Andric     Cmp = DAG.getNode(AVRISD::CMP, DL, MVT::Glue, LHS, RHS);
685e8d8bef9SDimitry Andric   }
686e8d8bef9SDimitry Andric 
687e8d8bef9SDimitry Andric   return Cmp;
688e8d8bef9SDimitry Andric }
689e8d8bef9SDimitry Andric 
6900b57cec5SDimitry Andric /// Returns appropriate AVR CMP/CMPC nodes and corresponding condition code for
6910b57cec5SDimitry Andric /// the given operands.
6920b57cec5SDimitry Andric SDValue AVRTargetLowering::getAVRCmp(SDValue LHS, SDValue RHS, ISD::CondCode CC,
6930b57cec5SDimitry Andric                                      SDValue &AVRcc, SelectionDAG &DAG,
6940b57cec5SDimitry Andric                                      SDLoc DL) const {
6950b57cec5SDimitry Andric   SDValue Cmp;
6960b57cec5SDimitry Andric   EVT VT = LHS.getValueType();
6970b57cec5SDimitry Andric   bool UseTest = false;
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   switch (CC) {
7000b57cec5SDimitry Andric   default:
7010b57cec5SDimitry Andric     break;
7020b57cec5SDimitry Andric   case ISD::SETLE: {
7030b57cec5SDimitry Andric     // Swap operands and reverse the branching condition.
7040b57cec5SDimitry Andric     std::swap(LHS, RHS);
7050b57cec5SDimitry Andric     CC = ISD::SETGE;
7060b57cec5SDimitry Andric     break;
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric   case ISD::SETGT: {
7090b57cec5SDimitry Andric     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
7100b57cec5SDimitry Andric       switch (C->getSExtValue()) {
7110b57cec5SDimitry Andric       case -1: {
7120b57cec5SDimitry Andric         // When doing lhs > -1 use a tst instruction on the top part of lhs
7130b57cec5SDimitry Andric         // and use brpl instead of using a chain of cp/cpc.
7140b57cec5SDimitry Andric         UseTest = true;
7150b57cec5SDimitry Andric         AVRcc = DAG.getConstant(AVRCC::COND_PL, DL, MVT::i8);
7160b57cec5SDimitry Andric         break;
7170b57cec5SDimitry Andric       }
7180b57cec5SDimitry Andric       case 0: {
7190b57cec5SDimitry Andric         // Turn lhs > 0 into 0 < lhs since 0 can be materialized with
7200b57cec5SDimitry Andric         // __zero_reg__ in lhs.
7210b57cec5SDimitry Andric         RHS = LHS;
7220b57cec5SDimitry Andric         LHS = DAG.getConstant(0, DL, VT);
7230b57cec5SDimitry Andric         CC = ISD::SETLT;
7240b57cec5SDimitry Andric         break;
7250b57cec5SDimitry Andric       }
7260b57cec5SDimitry Andric       default: {
7270b57cec5SDimitry Andric         // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows
7280b57cec5SDimitry Andric         // us to  fold the constant into the cmp instruction.
7290b57cec5SDimitry Andric         RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT);
7300b57cec5SDimitry Andric         CC = ISD::SETGE;
7310b57cec5SDimitry Andric         break;
7320b57cec5SDimitry Andric       }
7330b57cec5SDimitry Andric       }
7340b57cec5SDimitry Andric       break;
7350b57cec5SDimitry Andric     }
7360b57cec5SDimitry Andric     // Swap operands and reverse the branching condition.
7370b57cec5SDimitry Andric     std::swap(LHS, RHS);
7380b57cec5SDimitry Andric     CC = ISD::SETLT;
7390b57cec5SDimitry Andric     break;
7400b57cec5SDimitry Andric   }
7410b57cec5SDimitry Andric   case ISD::SETLT: {
7420b57cec5SDimitry Andric     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
7430b57cec5SDimitry Andric       switch (C->getSExtValue()) {
7440b57cec5SDimitry Andric       case 1: {
7450b57cec5SDimitry Andric         // Turn lhs < 1 into 0 >= lhs since 0 can be materialized with
7460b57cec5SDimitry Andric         // __zero_reg__ in lhs.
7470b57cec5SDimitry Andric         RHS = LHS;
7480b57cec5SDimitry Andric         LHS = DAG.getConstant(0, DL, VT);
7490b57cec5SDimitry Andric         CC = ISD::SETGE;
7500b57cec5SDimitry Andric         break;
7510b57cec5SDimitry Andric       }
7520b57cec5SDimitry Andric       case 0: {
7530b57cec5SDimitry Andric         // When doing lhs < 0 use a tst instruction on the top part of lhs
7540b57cec5SDimitry Andric         // and use brmi instead of using a chain of cp/cpc.
7550b57cec5SDimitry Andric         UseTest = true;
7560b57cec5SDimitry Andric         AVRcc = DAG.getConstant(AVRCC::COND_MI, DL, MVT::i8);
7570b57cec5SDimitry Andric         break;
7580b57cec5SDimitry Andric       }
7590b57cec5SDimitry Andric       }
7600b57cec5SDimitry Andric     }
7610b57cec5SDimitry Andric     break;
7620b57cec5SDimitry Andric   }
7630b57cec5SDimitry Andric   case ISD::SETULE: {
7640b57cec5SDimitry Andric     // Swap operands and reverse the branching condition.
7650b57cec5SDimitry Andric     std::swap(LHS, RHS);
7660b57cec5SDimitry Andric     CC = ISD::SETUGE;
7670b57cec5SDimitry Andric     break;
7680b57cec5SDimitry Andric   }
7690b57cec5SDimitry Andric   case ISD::SETUGT: {
7700b57cec5SDimitry Andric     // Turn lhs < rhs with lhs constant into rhs >= lhs+1, this allows us to
7710b57cec5SDimitry Andric     // fold the constant into the cmp instruction.
7720b57cec5SDimitry Andric     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(RHS)) {
7730b57cec5SDimitry Andric       RHS = DAG.getConstant(C->getSExtValue() + 1, DL, VT);
7740b57cec5SDimitry Andric       CC = ISD::SETUGE;
7750b57cec5SDimitry Andric       break;
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric     // Swap operands and reverse the branching condition.
7780b57cec5SDimitry Andric     std::swap(LHS, RHS);
7790b57cec5SDimitry Andric     CC = ISD::SETULT;
7800b57cec5SDimitry Andric     break;
7810b57cec5SDimitry Andric   }
7820b57cec5SDimitry Andric   }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric   // Expand 32 and 64 bit comparisons with custom CMP and CMPC nodes instead of
7850b57cec5SDimitry Andric   // using the default and/or/xor expansion code which is much longer.
7860b57cec5SDimitry Andric   if (VT == MVT::i32) {
7870b57cec5SDimitry Andric     SDValue LHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS,
7880b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
7890b57cec5SDimitry Andric     SDValue LHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS,
7900b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
7910b57cec5SDimitry Andric     SDValue RHSlo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS,
7920b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
7930b57cec5SDimitry Andric     SDValue RHShi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS,
7940b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric     if (UseTest) {
7970b57cec5SDimitry Andric       // When using tst we only care about the highest part.
7980b57cec5SDimitry Andric       SDValue Top = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHShi,
7990b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
8000b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue, Top);
8010b57cec5SDimitry Andric     } else {
802e8d8bef9SDimitry Andric       Cmp = getAVRCmp(LHSlo, RHSlo, DAG, DL);
8030b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHShi, RHShi, Cmp);
8040b57cec5SDimitry Andric     }
8050b57cec5SDimitry Andric   } else if (VT == MVT::i64) {
8060b57cec5SDimitry Andric     SDValue LHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, LHS,
8070b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
8080b57cec5SDimitry Andric     SDValue LHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, LHS,
8090b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
8100b57cec5SDimitry Andric 
8110b57cec5SDimitry Andric     SDValue LHS0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_0,
8120b57cec5SDimitry Andric                                DAG.getIntPtrConstant(0, DL));
8130b57cec5SDimitry Andric     SDValue LHS1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_0,
8140b57cec5SDimitry Andric                                DAG.getIntPtrConstant(1, DL));
8150b57cec5SDimitry Andric     SDValue LHS2 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_1,
8160b57cec5SDimitry Andric                                DAG.getIntPtrConstant(0, DL));
8170b57cec5SDimitry Andric     SDValue LHS3 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, LHS_1,
8180b57cec5SDimitry Andric                                DAG.getIntPtrConstant(1, DL));
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric     SDValue RHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, RHS,
8210b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(0, DL));
8220b57cec5SDimitry Andric     SDValue RHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, RHS,
8230b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric     SDValue RHS0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_0,
8260b57cec5SDimitry Andric                                DAG.getIntPtrConstant(0, DL));
8270b57cec5SDimitry Andric     SDValue RHS1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_0,
8280b57cec5SDimitry Andric                                DAG.getIntPtrConstant(1, DL));
8290b57cec5SDimitry Andric     SDValue RHS2 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_1,
8300b57cec5SDimitry Andric                                DAG.getIntPtrConstant(0, DL));
8310b57cec5SDimitry Andric     SDValue RHS3 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i16, RHS_1,
8320b57cec5SDimitry Andric                                DAG.getIntPtrConstant(1, DL));
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric     if (UseTest) {
8350b57cec5SDimitry Andric       // When using tst we only care about the highest part.
8360b57cec5SDimitry Andric       SDValue Top = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8, LHS3,
8370b57cec5SDimitry Andric                                 DAG.getIntPtrConstant(1, DL));
8380b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue, Top);
8390b57cec5SDimitry Andric     } else {
840e8d8bef9SDimitry Andric       Cmp = getAVRCmp(LHS0, RHS0, DAG, DL);
8410b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS1, RHS1, Cmp);
8420b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS2, RHS2, Cmp);
8430b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::CMPC, DL, MVT::Glue, LHS3, RHS3, Cmp);
8440b57cec5SDimitry Andric     }
8450b57cec5SDimitry Andric   } else if (VT == MVT::i8 || VT == MVT::i16) {
8460b57cec5SDimitry Andric     if (UseTest) {
8470b57cec5SDimitry Andric       // When using tst we only care about the highest part.
8480b57cec5SDimitry Andric       Cmp = DAG.getNode(AVRISD::TST, DL, MVT::Glue,
8490b57cec5SDimitry Andric                         (VT == MVT::i8)
8500b57cec5SDimitry Andric                             ? LHS
8510b57cec5SDimitry Andric                             : DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i8,
8520b57cec5SDimitry Andric                                           LHS, DAG.getIntPtrConstant(1, DL)));
8530b57cec5SDimitry Andric     } else {
854e8d8bef9SDimitry Andric       Cmp = getAVRCmp(LHS, RHS, DAG, DL);
8550b57cec5SDimitry Andric     }
8560b57cec5SDimitry Andric   } else {
8570b57cec5SDimitry Andric     llvm_unreachable("Invalid comparison size");
8580b57cec5SDimitry Andric   }
8590b57cec5SDimitry Andric 
8600b57cec5SDimitry Andric   // When using a test instruction AVRcc is already set.
8610b57cec5SDimitry Andric   if (!UseTest) {
8620b57cec5SDimitry Andric     AVRcc = DAG.getConstant(intCCToAVRCC(CC), DL, MVT::i8);
8630b57cec5SDimitry Andric   }
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   return Cmp;
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
8690b57cec5SDimitry Andric   SDValue Chain = Op.getOperand(0);
8700b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
8710b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(2);
8720b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(3);
8730b57cec5SDimitry Andric   SDValue Dest = Op.getOperand(4);
8740b57cec5SDimitry Andric   SDLoc dl(Op);
8750b57cec5SDimitry Andric 
8760b57cec5SDimitry Andric   SDValue TargetCC;
8770b57cec5SDimitry Andric   SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, dl);
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric   return DAG.getNode(AVRISD::BRCOND, dl, MVT::Other, Chain, Dest, TargetCC,
8800b57cec5SDimitry Andric                      Cmp);
8810b57cec5SDimitry Andric }
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
8840b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(0);
8850b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(1);
8860b57cec5SDimitry Andric   SDValue TrueV = Op.getOperand(2);
8870b57cec5SDimitry Andric   SDValue FalseV = Op.getOperand(3);
8880b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
8890b57cec5SDimitry Andric   SDLoc dl(Op);
8900b57cec5SDimitry Andric 
8910b57cec5SDimitry Andric   SDValue TargetCC;
8920b57cec5SDimitry Andric   SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, dl);
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric   SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
8950b57cec5SDimitry Andric   SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
8960b57cec5SDimitry Andric 
8970b57cec5SDimitry Andric   return DAG.getNode(AVRISD::SELECT_CC, dl, VTs, Ops);
8980b57cec5SDimitry Andric }
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const {
9010b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(0);
9020b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(1);
9030b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
9040b57cec5SDimitry Andric   SDLoc DL(Op);
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   SDValue TargetCC;
9070b57cec5SDimitry Andric   SDValue Cmp = getAVRCmp(LHS, RHS, CC, TargetCC, DAG, DL);
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   SDValue TrueV = DAG.getConstant(1, DL, Op.getValueType());
9100b57cec5SDimitry Andric   SDValue FalseV = DAG.getConstant(0, DL, Op.getValueType());
9110b57cec5SDimitry Andric   SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
9120b57cec5SDimitry Andric   SDValue Ops[] = {TrueV, FalseV, TargetCC, Cmp};
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   return DAG.getNode(AVRISD::SELECT_CC, DL, VTs, Ops);
9150b57cec5SDimitry Andric }
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
9180b57cec5SDimitry Andric   const MachineFunction &MF = DAG.getMachineFunction();
9190b57cec5SDimitry Andric   const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
9200b57cec5SDimitry Andric   const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
9210b57cec5SDimitry Andric   auto DL = DAG.getDataLayout();
9220b57cec5SDimitry Andric   SDLoc dl(Op);
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   // Vastart just stores the address of the VarArgsFrameIndex slot into the
9250b57cec5SDimitry Andric   // memory location argument.
9260b57cec5SDimitry Andric   SDValue FI = DAG.getFrameIndex(AFI->getVarArgsFrameIndex(), getPointerTy(DL));
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric   return DAG.getStore(Op.getOperand(0), dl, FI, Op.getOperand(1),
929e8d8bef9SDimitry Andric                       MachinePointerInfo(SV));
9300b57cec5SDimitry Andric }
9310b57cec5SDimitry Andric 
932bdd1243dSDimitry Andric // Modify the existing ISD::INLINEASM node to add the implicit zero register.
933bdd1243dSDimitry Andric SDValue AVRTargetLowering::LowerINLINEASM(SDValue Op, SelectionDAG &DAG) const {
934bdd1243dSDimitry Andric   SDValue ZeroReg = DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8);
935bdd1243dSDimitry Andric   if (Op.getOperand(Op.getNumOperands() - 1) == ZeroReg ||
936bdd1243dSDimitry Andric       Op.getOperand(Op.getNumOperands() - 2) == ZeroReg) {
937bdd1243dSDimitry Andric     // Zero register has already been added. Don't add it again.
938bdd1243dSDimitry Andric     // If this isn't handled, we get called over and over again.
939bdd1243dSDimitry Andric     return Op;
940bdd1243dSDimitry Andric   }
941bdd1243dSDimitry Andric 
942bdd1243dSDimitry Andric   // Get a list of operands to the new INLINEASM node. This is mostly a copy,
943bdd1243dSDimitry Andric   // with some edits.
944bdd1243dSDimitry Andric   // Add the following operands at the end (but before the glue node, if it's
945bdd1243dSDimitry Andric   // there):
946bdd1243dSDimitry Andric   //  - The flags of the implicit zero register operand.
947bdd1243dSDimitry Andric   //  - The implicit zero register operand itself.
948bdd1243dSDimitry Andric   SDLoc dl(Op);
949bdd1243dSDimitry Andric   SmallVector<SDValue, 8> Ops;
950bdd1243dSDimitry Andric   SDNode *N = Op.getNode();
951bdd1243dSDimitry Andric   SDValue Glue;
952bdd1243dSDimitry Andric   for (unsigned I = 0; I < N->getNumOperands(); I++) {
953bdd1243dSDimitry Andric     SDValue Operand = N->getOperand(I);
954bdd1243dSDimitry Andric     if (Operand.getValueType() == MVT::Glue) {
955bdd1243dSDimitry Andric       // The glue operand always needs to be at the end, so we need to treat it
956bdd1243dSDimitry Andric       // specially.
957bdd1243dSDimitry Andric       Glue = Operand;
958bdd1243dSDimitry Andric     } else {
959bdd1243dSDimitry Andric       Ops.push_back(Operand);
960bdd1243dSDimitry Andric     }
961bdd1243dSDimitry Andric   }
9625f757f3fSDimitry Andric   InlineAsm::Flag Flags(InlineAsm::Kind::RegUse, 1);
963bdd1243dSDimitry Andric   Ops.push_back(DAG.getTargetConstant(Flags, dl, MVT::i32));
964bdd1243dSDimitry Andric   Ops.push_back(ZeroReg);
965bdd1243dSDimitry Andric   if (Glue) {
966bdd1243dSDimitry Andric     Ops.push_back(Glue);
967bdd1243dSDimitry Andric   }
968bdd1243dSDimitry Andric 
969bdd1243dSDimitry Andric   // Replace the current INLINEASM node with a new one that has the zero
970bdd1243dSDimitry Andric   // register as implicit parameter.
971bdd1243dSDimitry Andric   SDValue New = DAG.getNode(N->getOpcode(), dl, N->getVTList(), Ops);
972bdd1243dSDimitry Andric   DAG.ReplaceAllUsesOfValueWith(Op, New);
973bdd1243dSDimitry Andric   DAG.ReplaceAllUsesOfValueWith(Op.getValue(1), New.getValue(1));
974bdd1243dSDimitry Andric 
975bdd1243dSDimitry Andric   return New;
976bdd1243dSDimitry Andric }
977bdd1243dSDimitry Andric 
9780b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
9790b57cec5SDimitry Andric   switch (Op.getOpcode()) {
9800b57cec5SDimitry Andric   default:
9810b57cec5SDimitry Andric     llvm_unreachable("Don't know how to custom lower this!");
9820b57cec5SDimitry Andric   case ISD::SHL:
9830b57cec5SDimitry Andric   case ISD::SRA:
9840b57cec5SDimitry Andric   case ISD::SRL:
9850b57cec5SDimitry Andric   case ISD::ROTL:
9860b57cec5SDimitry Andric   case ISD::ROTR:
9870b57cec5SDimitry Andric     return LowerShifts(Op, DAG);
9880b57cec5SDimitry Andric   case ISD::GlobalAddress:
9890b57cec5SDimitry Andric     return LowerGlobalAddress(Op, DAG);
9900b57cec5SDimitry Andric   case ISD::BlockAddress:
9910b57cec5SDimitry Andric     return LowerBlockAddress(Op, DAG);
9920b57cec5SDimitry Andric   case ISD::BR_CC:
9930b57cec5SDimitry Andric     return LowerBR_CC(Op, DAG);
9940b57cec5SDimitry Andric   case ISD::SELECT_CC:
9950b57cec5SDimitry Andric     return LowerSELECT_CC(Op, DAG);
9960b57cec5SDimitry Andric   case ISD::SETCC:
9970b57cec5SDimitry Andric     return LowerSETCC(Op, DAG);
9980b57cec5SDimitry Andric   case ISD::VASTART:
9990b57cec5SDimitry Andric     return LowerVASTART(Op, DAG);
10000b57cec5SDimitry Andric   case ISD::SDIVREM:
10010b57cec5SDimitry Andric   case ISD::UDIVREM:
10020b57cec5SDimitry Andric     return LowerDivRem(Op, DAG);
1003bdd1243dSDimitry Andric   case ISD::INLINEASM:
1004bdd1243dSDimitry Andric     return LowerINLINEASM(Op, DAG);
10050b57cec5SDimitry Andric   }
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric   return SDValue();
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric /// Replace a node with an illegal result type
10110b57cec5SDimitry Andric /// with a new node built out of custom code.
10120b57cec5SDimitry Andric void AVRTargetLowering::ReplaceNodeResults(SDNode *N,
10130b57cec5SDimitry Andric                                            SmallVectorImpl<SDValue> &Results,
10140b57cec5SDimitry Andric                                            SelectionDAG &DAG) const {
10150b57cec5SDimitry Andric   SDLoc DL(N);
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric   switch (N->getOpcode()) {
10180b57cec5SDimitry Andric   case ISD::ADD: {
10190b57cec5SDimitry Andric     // Convert add (x, imm) into sub (x, -imm).
10200b57cec5SDimitry Andric     if (const ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) {
10210b57cec5SDimitry Andric       SDValue Sub = DAG.getNode(
10220b57cec5SDimitry Andric           ISD::SUB, DL, N->getValueType(0), N->getOperand(0),
10230b57cec5SDimitry Andric           DAG.getConstant(-C->getAPIntValue(), DL, C->getValueType(0)));
10240b57cec5SDimitry Andric       Results.push_back(Sub);
10250b57cec5SDimitry Andric     }
10260b57cec5SDimitry Andric     break;
10270b57cec5SDimitry Andric   }
10280b57cec5SDimitry Andric   default: {
10290b57cec5SDimitry Andric     SDValue Res = LowerOperation(SDValue(N, 0), DAG);
10300b57cec5SDimitry Andric 
10310b57cec5SDimitry Andric     for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
10320b57cec5SDimitry Andric       Results.push_back(Res.getValue(I));
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric     break;
10350b57cec5SDimitry Andric   }
10360b57cec5SDimitry Andric   }
10370b57cec5SDimitry Andric }
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric /// Return true if the addressing mode represented
10400b57cec5SDimitry Andric /// by AM is legal for this target, for a load/store of the specified type.
10410b57cec5SDimitry Andric bool AVRTargetLowering::isLegalAddressingMode(const DataLayout &DL,
10420b57cec5SDimitry Andric                                               const AddrMode &AM, Type *Ty,
1043349cc55cSDimitry Andric                                               unsigned AS,
1044349cc55cSDimitry Andric                                               Instruction *I) const {
10450b57cec5SDimitry Andric   int64_t Offs = AM.BaseOffs;
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   // Allow absolute addresses.
10480b57cec5SDimitry Andric   if (AM.BaseGV && !AM.HasBaseReg && AM.Scale == 0 && Offs == 0) {
10490b57cec5SDimitry Andric     return true;
10500b57cec5SDimitry Andric   }
10510b57cec5SDimitry Andric 
10520b57cec5SDimitry Andric   // Flash memory instructions only allow zero offsets.
10530b57cec5SDimitry Andric   if (isa<PointerType>(Ty) && AS == AVR::ProgramMemory) {
10540b57cec5SDimitry Andric     return false;
10550b57cec5SDimitry Andric   }
10560b57cec5SDimitry Andric 
10570b57cec5SDimitry Andric   // Allow reg+<6bit> offset.
10580b57cec5SDimitry Andric   if (Offs < 0)
10590b57cec5SDimitry Andric     Offs = -Offs;
106004eeddc0SDimitry Andric   if (AM.BaseGV == nullptr && AM.HasBaseReg && AM.Scale == 0 &&
106104eeddc0SDimitry Andric       isUInt<6>(Offs)) {
10620b57cec5SDimitry Andric     return true;
10630b57cec5SDimitry Andric   }
10640b57cec5SDimitry Andric 
10650b57cec5SDimitry Andric   return false;
10660b57cec5SDimitry Andric }
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric /// Returns true by value, base pointer and
10690b57cec5SDimitry Andric /// offset pointer and addressing mode by reference if the node's address
10700b57cec5SDimitry Andric /// can be legally represented as pre-indexed load / store address.
10710b57cec5SDimitry Andric bool AVRTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base,
10720b57cec5SDimitry Andric                                                   SDValue &Offset,
10730b57cec5SDimitry Andric                                                   ISD::MemIndexedMode &AM,
10740b57cec5SDimitry Andric                                                   SelectionDAG &DAG) const {
10750b57cec5SDimitry Andric   EVT VT;
10760b57cec5SDimitry Andric   const SDNode *Op;
10770b57cec5SDimitry Andric   SDLoc DL(N);
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
10800b57cec5SDimitry Andric     VT = LD->getMemoryVT();
10810b57cec5SDimitry Andric     Op = LD->getBasePtr().getNode();
10820b57cec5SDimitry Andric     if (LD->getExtensionType() != ISD::NON_EXTLOAD)
10830b57cec5SDimitry Andric       return false;
10840b57cec5SDimitry Andric     if (AVR::isProgramMemoryAccess(LD)) {
10850b57cec5SDimitry Andric       return false;
10860b57cec5SDimitry Andric     }
10870b57cec5SDimitry Andric   } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
10880b57cec5SDimitry Andric     VT = ST->getMemoryVT();
10890b57cec5SDimitry Andric     Op = ST->getBasePtr().getNode();
10900b57cec5SDimitry Andric     if (AVR::isProgramMemoryAccess(ST)) {
10910b57cec5SDimitry Andric       return false;
10920b57cec5SDimitry Andric     }
10930b57cec5SDimitry Andric   } else {
10940b57cec5SDimitry Andric     return false;
10950b57cec5SDimitry Andric   }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric   if (VT != MVT::i8 && VT != MVT::i16) {
10980b57cec5SDimitry Andric     return false;
10990b57cec5SDimitry Andric   }
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   if (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB) {
11020b57cec5SDimitry Andric     return false;
11030b57cec5SDimitry Andric   }
11040b57cec5SDimitry Andric 
11050b57cec5SDimitry Andric   if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) {
11060b57cec5SDimitry Andric     int RHSC = RHS->getSExtValue();
11070b57cec5SDimitry Andric     if (Op->getOpcode() == ISD::SUB)
11080b57cec5SDimitry Andric       RHSC = -RHSC;
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric     if ((VT == MVT::i16 && RHSC != -2) || (VT == MVT::i8 && RHSC != -1)) {
11110b57cec5SDimitry Andric       return false;
11120b57cec5SDimitry Andric     }
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric     Base = Op->getOperand(0);
11150b57cec5SDimitry Andric     Offset = DAG.getConstant(RHSC, DL, MVT::i8);
11160b57cec5SDimitry Andric     AM = ISD::PRE_DEC;
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric     return true;
11190b57cec5SDimitry Andric   }
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric   return false;
11220b57cec5SDimitry Andric }
11230b57cec5SDimitry Andric 
11240b57cec5SDimitry Andric /// Returns true by value, base pointer and
11250b57cec5SDimitry Andric /// offset pointer and addressing mode by reference if this node can be
11260b57cec5SDimitry Andric /// combined with a load / store to form a post-indexed load / store.
11270b57cec5SDimitry Andric bool AVRTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
11280b57cec5SDimitry Andric                                                    SDValue &Base,
11290b57cec5SDimitry Andric                                                    SDValue &Offset,
11300b57cec5SDimitry Andric                                                    ISD::MemIndexedMode &AM,
11310b57cec5SDimitry Andric                                                    SelectionDAG &DAG) const {
11320b57cec5SDimitry Andric   EVT VT;
11330b57cec5SDimitry Andric   SDLoc DL(N);
11340b57cec5SDimitry Andric 
11350b57cec5SDimitry Andric   if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) {
11360b57cec5SDimitry Andric     VT = LD->getMemoryVT();
11370b57cec5SDimitry Andric     if (LD->getExtensionType() != ISD::NON_EXTLOAD)
11380b57cec5SDimitry Andric       return false;
11390b57cec5SDimitry Andric   } else if (const StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) {
11400b57cec5SDimitry Andric     VT = ST->getMemoryVT();
114106c3fb27SDimitry Andric     // We can not store to program memory.
114206c3fb27SDimitry Andric     if (AVR::isProgramMemoryAccess(ST))
11430b57cec5SDimitry Andric       return false;
114406c3fb27SDimitry Andric     // Since the high byte need to be stored first, we can not emit
114506c3fb27SDimitry Andric     // i16 post increment store like:
114606c3fb27SDimitry Andric     // st X+, r24
114706c3fb27SDimitry Andric     // st X+, r25
114806c3fb27SDimitry Andric     if (VT == MVT::i16 && !Subtarget.hasLowByteFirst())
114906c3fb27SDimitry Andric       return false;
11500b57cec5SDimitry Andric   } else {
11510b57cec5SDimitry Andric     return false;
11520b57cec5SDimitry Andric   }
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   if (VT != MVT::i8 && VT != MVT::i16) {
11550b57cec5SDimitry Andric     return false;
11560b57cec5SDimitry Andric   }
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric   if (Op->getOpcode() != ISD::ADD && Op->getOpcode() != ISD::SUB) {
11590b57cec5SDimitry Andric     return false;
11600b57cec5SDimitry Andric   }
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   if (const ConstantSDNode *RHS = dyn_cast<ConstantSDNode>(Op->getOperand(1))) {
11630b57cec5SDimitry Andric     int RHSC = RHS->getSExtValue();
11640b57cec5SDimitry Andric     if (Op->getOpcode() == ISD::SUB)
11650b57cec5SDimitry Andric       RHSC = -RHSC;
11660b57cec5SDimitry Andric     if ((VT == MVT::i16 && RHSC != 2) || (VT == MVT::i8 && RHSC != 1)) {
11670b57cec5SDimitry Andric       return false;
11680b57cec5SDimitry Andric     }
11690b57cec5SDimitry Andric 
117006c3fb27SDimitry Andric     // FIXME: We temporarily disable post increment load from program memory,
117106c3fb27SDimitry Andric     //        due to bug https://github.com/llvm/llvm-project/issues/59914.
117206c3fb27SDimitry Andric     if (const LoadSDNode *LD = dyn_cast<LoadSDNode>(N))
117306c3fb27SDimitry Andric       if (AVR::isProgramMemoryAccess(LD))
117406c3fb27SDimitry Andric         return false;
117506c3fb27SDimitry Andric 
11760b57cec5SDimitry Andric     Base = Op->getOperand(0);
11770b57cec5SDimitry Andric     Offset = DAG.getConstant(RHSC, DL, MVT::i8);
11780b57cec5SDimitry Andric     AM = ISD::POST_INC;
11790b57cec5SDimitry Andric 
11800b57cec5SDimitry Andric     return true;
11810b57cec5SDimitry Andric   }
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric   return false;
11840b57cec5SDimitry Andric }
11850b57cec5SDimitry Andric 
11860b57cec5SDimitry Andric bool AVRTargetLowering::isOffsetFoldingLegal(
11870b57cec5SDimitry Andric     const GlobalAddressSDNode *GA) const {
11880b57cec5SDimitry Andric   return true;
11890b57cec5SDimitry Andric }
11900b57cec5SDimitry Andric 
11910b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11920b57cec5SDimitry Andric //             Formal Arguments Calling Convention Implementation
11930b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11940b57cec5SDimitry Andric 
11950b57cec5SDimitry Andric #include "AVRGenCallingConv.inc"
11960b57cec5SDimitry Andric 
11975ffd83dbSDimitry Andric /// Registers for calling conventions, ordered in reverse as required by ABI.
11985ffd83dbSDimitry Andric /// Both arrays must be of the same length.
119981ad6265SDimitry Andric static const MCPhysReg RegList8AVR[] = {
12005ffd83dbSDimitry Andric     AVR::R25, AVR::R24, AVR::R23, AVR::R22, AVR::R21, AVR::R20,
12015ffd83dbSDimitry Andric     AVR::R19, AVR::R18, AVR::R17, AVR::R16, AVR::R15, AVR::R14,
12025ffd83dbSDimitry Andric     AVR::R13, AVR::R12, AVR::R11, AVR::R10, AVR::R9,  AVR::R8};
120381ad6265SDimitry Andric static const MCPhysReg RegList8Tiny[] = {AVR::R25, AVR::R24, AVR::R23,
120481ad6265SDimitry Andric                                          AVR::R22, AVR::R21, AVR::R20};
120581ad6265SDimitry Andric static const MCPhysReg RegList16AVR[] = {
1206349cc55cSDimitry Andric     AVR::R26R25, AVR::R25R24, AVR::R24R23, AVR::R23R22, AVR::R22R21,
1207349cc55cSDimitry Andric     AVR::R21R20, AVR::R20R19, AVR::R19R18, AVR::R18R17, AVR::R17R16,
1208349cc55cSDimitry Andric     AVR::R16R15, AVR::R15R14, AVR::R14R13, AVR::R13R12, AVR::R12R11,
1209349cc55cSDimitry Andric     AVR::R11R10, AVR::R10R9,  AVR::R9R8};
121081ad6265SDimitry Andric static const MCPhysReg RegList16Tiny[] = {AVR::R26R25, AVR::R25R24,
121181ad6265SDimitry Andric                                           AVR::R24R23, AVR::R23R22,
121281ad6265SDimitry Andric                                           AVR::R22R21, AVR::R21R20};
12130b57cec5SDimitry Andric 
1214bdd1243dSDimitry Andric static_assert(std::size(RegList8AVR) == std::size(RegList16AVR),
121581ad6265SDimitry Andric               "8-bit and 16-bit register arrays must be of equal length");
1216bdd1243dSDimitry Andric static_assert(std::size(RegList8Tiny) == std::size(RegList16Tiny),
12175ffd83dbSDimitry Andric               "8-bit and 16-bit register arrays must be of equal length");
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric /// Analyze incoming and outgoing function arguments. We need custom C++ code
12205ffd83dbSDimitry Andric /// to handle special constraints in the ABI.
12215ffd83dbSDimitry Andric /// In addition, all pieces of a certain argument have to be passed either
12225ffd83dbSDimitry Andric /// using registers or the stack but never mixing both.
12235ffd83dbSDimitry Andric template <typename ArgT>
122481ad6265SDimitry Andric static void analyzeArguments(TargetLowering::CallLoweringInfo *CLI,
122581ad6265SDimitry Andric                              const Function *F, const DataLayout *TD,
122681ad6265SDimitry Andric                              const SmallVectorImpl<ArgT> &Args,
122781ad6265SDimitry Andric                              SmallVectorImpl<CCValAssign> &ArgLocs,
122881ad6265SDimitry Andric                              CCState &CCInfo, bool Tiny) {
122981ad6265SDimitry Andric   // Choose the proper register list for argument passing according to the ABI.
123081ad6265SDimitry Andric   ArrayRef<MCPhysReg> RegList8;
123181ad6265SDimitry Andric   ArrayRef<MCPhysReg> RegList16;
123281ad6265SDimitry Andric   if (Tiny) {
1233*0fca6ea1SDimitry Andric     RegList8 = ArrayRef(RegList8Tiny);
1234*0fca6ea1SDimitry Andric     RegList16 = ArrayRef(RegList16Tiny);
123581ad6265SDimitry Andric   } else {
1236*0fca6ea1SDimitry Andric     RegList8 = ArrayRef(RegList8AVR);
1237*0fca6ea1SDimitry Andric     RegList16 = ArrayRef(RegList16AVR);
123881ad6265SDimitry Andric   }
123981ad6265SDimitry Andric 
12405ffd83dbSDimitry Andric   unsigned NumArgs = Args.size();
12415ffd83dbSDimitry Andric   // This is the index of the last used register, in RegList*.
12425ffd83dbSDimitry Andric   // -1 means R26 (R26 is never actually used in CC).
12435ffd83dbSDimitry Andric   int RegLastIdx = -1;
12445ffd83dbSDimitry Andric   // Once a value is passed to the stack it will always be used
12455ffd83dbSDimitry Andric   bool UseStack = false;
12465ffd83dbSDimitry Andric   for (unsigned i = 0; i != NumArgs;) {
12475ffd83dbSDimitry Andric     MVT VT = Args[i].VT;
12485ffd83dbSDimitry Andric     // We have to count the number of bytes for each function argument, that is
12495ffd83dbSDimitry Andric     // those Args with the same OrigArgIndex. This is important in case the
12505ffd83dbSDimitry Andric     // function takes an aggregate type.
12515ffd83dbSDimitry Andric     // Current argument will be between [i..j).
12525ffd83dbSDimitry Andric     unsigned ArgIndex = Args[i].OrigArgIndex;
12535ffd83dbSDimitry Andric     unsigned TotalBytes = VT.getStoreSize();
12545ffd83dbSDimitry Andric     unsigned j = i + 1;
12555ffd83dbSDimitry Andric     for (; j != NumArgs; ++j) {
12565ffd83dbSDimitry Andric       if (Args[j].OrigArgIndex != ArgIndex)
12575ffd83dbSDimitry Andric         break;
12585ffd83dbSDimitry Andric       TotalBytes += Args[j].VT.getStoreSize();
12590b57cec5SDimitry Andric     }
12605ffd83dbSDimitry Andric     // Round up to even number of bytes.
12615ffd83dbSDimitry Andric     TotalBytes = alignTo(TotalBytes, 2);
12625ffd83dbSDimitry Andric     // Skip zero sized arguments
12635ffd83dbSDimitry Andric     if (TotalBytes == 0)
12645ffd83dbSDimitry Andric       continue;
12655ffd83dbSDimitry Andric     // The index of the first register to be used
12665ffd83dbSDimitry Andric     unsigned RegIdx = RegLastIdx + TotalBytes;
12675ffd83dbSDimitry Andric     RegLastIdx = RegIdx;
12685ffd83dbSDimitry Andric     // If there are not enough registers, use the stack
126981ad6265SDimitry Andric     if (RegIdx >= RegList8.size()) {
12705ffd83dbSDimitry Andric       UseStack = true;
12710b57cec5SDimitry Andric     }
12725ffd83dbSDimitry Andric     for (; i != j; ++i) {
12735ffd83dbSDimitry Andric       MVT VT = Args[i].VT;
12740b57cec5SDimitry Andric 
12755ffd83dbSDimitry Andric       if (UseStack) {
12765ffd83dbSDimitry Andric         auto evt = EVT(VT).getTypeForEVT(CCInfo.getContext());
12775ffd83dbSDimitry Andric         unsigned Offset = CCInfo.AllocateStack(TD->getTypeAllocSize(evt),
12785ffd83dbSDimitry Andric                                                TD->getABITypeAlign(evt));
12790b57cec5SDimitry Andric         CCInfo.addLoc(
12805ffd83dbSDimitry Andric             CCValAssign::getMem(i, VT, Offset, VT, CCValAssign::Full));
12810b57cec5SDimitry Andric       } else {
12825ffd83dbSDimitry Andric         unsigned Reg;
12835ffd83dbSDimitry Andric         if (VT == MVT::i8) {
12845ffd83dbSDimitry Andric           Reg = CCInfo.AllocateReg(RegList8[RegIdx]);
12855ffd83dbSDimitry Andric         } else if (VT == MVT::i16) {
12865ffd83dbSDimitry Andric           Reg = CCInfo.AllocateReg(RegList16[RegIdx]);
12870b57cec5SDimitry Andric         } else {
12885ffd83dbSDimitry Andric           llvm_unreachable(
12895ffd83dbSDimitry Andric               "calling convention can only manage i8 and i16 types");
12905ffd83dbSDimitry Andric         }
12915ffd83dbSDimitry Andric         assert(Reg && "register not available in calling convention");
12925ffd83dbSDimitry Andric         CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full));
12935ffd83dbSDimitry Andric         // Registers inside a particular argument are sorted in increasing order
12945ffd83dbSDimitry Andric         // (remember the array is reversed).
12955ffd83dbSDimitry Andric         RegIdx -= VT.getStoreSize();
12965ffd83dbSDimitry Andric       }
12975ffd83dbSDimitry Andric     }
12980b57cec5SDimitry Andric   }
12990b57cec5SDimitry Andric }
13000b57cec5SDimitry Andric 
13015ffd83dbSDimitry Andric /// Count the total number of bytes needed to pass or return these arguments.
13025ffd83dbSDimitry Andric template <typename ArgT>
1303349cc55cSDimitry Andric static unsigned
1304349cc55cSDimitry Andric getTotalArgumentsSizeInBytes(const SmallVectorImpl<ArgT> &Args) {
13055ffd83dbSDimitry Andric   unsigned TotalBytes = 0;
13065ffd83dbSDimitry Andric 
13075ffd83dbSDimitry Andric   for (const ArgT &Arg : Args) {
13085ffd83dbSDimitry Andric     TotalBytes += Arg.VT.getStoreSize();
13090b57cec5SDimitry Andric   }
13105ffd83dbSDimitry Andric   return TotalBytes;
13110b57cec5SDimitry Andric }
13125ffd83dbSDimitry Andric 
13135ffd83dbSDimitry Andric /// Analyze incoming and outgoing value of returning from a function.
13145ffd83dbSDimitry Andric /// The algorithm is similar to analyzeArguments, but there can only be
13155ffd83dbSDimitry Andric /// one value, possibly an aggregate, and it is limited to 8 bytes.
13165ffd83dbSDimitry Andric template <typename ArgT>
13175ffd83dbSDimitry Andric static void analyzeReturnValues(const SmallVectorImpl<ArgT> &Args,
131881ad6265SDimitry Andric                                 CCState &CCInfo, bool Tiny) {
13195ffd83dbSDimitry Andric   unsigned NumArgs = Args.size();
13205ffd83dbSDimitry Andric   unsigned TotalBytes = getTotalArgumentsSizeInBytes(Args);
13215ffd83dbSDimitry Andric   // CanLowerReturn() guarantees this assertion.
1322bdd1243dSDimitry Andric   if (Tiny)
1323bdd1243dSDimitry Andric     assert(TotalBytes <= 4 &&
1324bdd1243dSDimitry Andric            "return values greater than 4 bytes cannot be lowered on AVRTiny");
1325bdd1243dSDimitry Andric   else
1326349cc55cSDimitry Andric     assert(TotalBytes <= 8 &&
1327bdd1243dSDimitry Andric            "return values greater than 8 bytes cannot be lowered on AVR");
13285ffd83dbSDimitry Andric 
132981ad6265SDimitry Andric   // Choose the proper register list for argument passing according to the ABI.
133081ad6265SDimitry Andric   ArrayRef<MCPhysReg> RegList8;
133181ad6265SDimitry Andric   ArrayRef<MCPhysReg> RegList16;
133281ad6265SDimitry Andric   if (Tiny) {
1333*0fca6ea1SDimitry Andric     RegList8 = ArrayRef(RegList8Tiny);
1334*0fca6ea1SDimitry Andric     RegList16 = ArrayRef(RegList16Tiny);
133581ad6265SDimitry Andric   } else {
1336*0fca6ea1SDimitry Andric     RegList8 = ArrayRef(RegList8AVR);
1337*0fca6ea1SDimitry Andric     RegList16 = ArrayRef(RegList16AVR);
133881ad6265SDimitry Andric   }
133981ad6265SDimitry Andric 
13405ffd83dbSDimitry Andric   // GCC-ABI says that the size is rounded up to the next even number,
13415ffd83dbSDimitry Andric   // but actually once it is more than 4 it will always round up to 8.
13425ffd83dbSDimitry Andric   if (TotalBytes > 4) {
13435ffd83dbSDimitry Andric     TotalBytes = 8;
13445ffd83dbSDimitry Andric   } else {
13455ffd83dbSDimitry Andric     TotalBytes = alignTo(TotalBytes, 2);
13465ffd83dbSDimitry Andric   }
13475ffd83dbSDimitry Andric 
13485ffd83dbSDimitry Andric   // The index of the first register to use.
13495ffd83dbSDimitry Andric   int RegIdx = TotalBytes - 1;
13505ffd83dbSDimitry Andric   for (unsigned i = 0; i != NumArgs; ++i) {
13515ffd83dbSDimitry Andric     MVT VT = Args[i].VT;
13525ffd83dbSDimitry Andric     unsigned Reg;
13535ffd83dbSDimitry Andric     if (VT == MVT::i8) {
13545ffd83dbSDimitry Andric       Reg = CCInfo.AllocateReg(RegList8[RegIdx]);
13555ffd83dbSDimitry Andric     } else if (VT == MVT::i16) {
13565ffd83dbSDimitry Andric       Reg = CCInfo.AllocateReg(RegList16[RegIdx]);
13575ffd83dbSDimitry Andric     } else {
13585ffd83dbSDimitry Andric       llvm_unreachable("calling convention can only manage i8 and i16 types");
13595ffd83dbSDimitry Andric     }
13605ffd83dbSDimitry Andric     assert(Reg && "register not available in calling convention");
13615ffd83dbSDimitry Andric     CCInfo.addLoc(CCValAssign::getReg(i, VT, Reg, VT, CCValAssign::Full));
13625ffd83dbSDimitry Andric     // Registers sort in increasing order
13635ffd83dbSDimitry Andric     RegIdx -= VT.getStoreSize();
13640b57cec5SDimitry Andric   }
13650b57cec5SDimitry Andric }
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerFormalArguments(
13680b57cec5SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
13695ffd83dbSDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
13705ffd83dbSDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
13710b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
13720b57cec5SDimitry Andric   MachineFrameInfo &MFI = MF.getFrameInfo();
13730b57cec5SDimitry Andric   auto DL = DAG.getDataLayout();
13740b57cec5SDimitry Andric 
13750b57cec5SDimitry Andric   // Assign locations to all of the incoming arguments.
13760b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
13770b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
13780b57cec5SDimitry Andric                  *DAG.getContext());
13790b57cec5SDimitry Andric 
13805ffd83dbSDimitry Andric   // Variadic functions do not need all the analysis below.
13815ffd83dbSDimitry Andric   if (isVarArg) {
13825ffd83dbSDimitry Andric     CCInfo.AnalyzeFormalArguments(Ins, ArgCC_AVR_Vararg);
13835ffd83dbSDimitry Andric   } else {
138481ad6265SDimitry Andric     analyzeArguments(nullptr, &MF.getFunction(), &DL, Ins, ArgLocs, CCInfo,
138581ad6265SDimitry Andric                      Subtarget.hasTinyEncoding());
13865ffd83dbSDimitry Andric   }
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric   SDValue ArgValue;
13890b57cec5SDimitry Andric   for (CCValAssign &VA : ArgLocs) {
13900b57cec5SDimitry Andric 
13910b57cec5SDimitry Andric     // Arguments stored on registers.
13920b57cec5SDimitry Andric     if (VA.isRegLoc()) {
13930b57cec5SDimitry Andric       EVT RegVT = VA.getLocVT();
13940b57cec5SDimitry Andric       const TargetRegisterClass *RC;
13950b57cec5SDimitry Andric       if (RegVT == MVT::i8) {
13960b57cec5SDimitry Andric         RC = &AVR::GPR8RegClass;
13970b57cec5SDimitry Andric       } else if (RegVT == MVT::i16) {
13980b57cec5SDimitry Andric         RC = &AVR::DREGSRegClass;
13990b57cec5SDimitry Andric       } else {
14000b57cec5SDimitry Andric         llvm_unreachable("Unknown argument type!");
14010b57cec5SDimitry Andric       }
14020b57cec5SDimitry Andric 
140304eeddc0SDimitry Andric       Register Reg = MF.addLiveIn(VA.getLocReg(), RC);
14040b57cec5SDimitry Andric       ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, RegVT);
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric       // :NOTE: Clang should not promote any i8 into i16 but for safety the
14070b57cec5SDimitry Andric       // following code will handle zexts or sexts generated by other
14080b57cec5SDimitry Andric       // front ends. Otherwise:
14090b57cec5SDimitry Andric       // If this is an 8 bit value, it is really passed promoted
14100b57cec5SDimitry Andric       // to 16 bits. Insert an assert[sz]ext to capture this, then
14110b57cec5SDimitry Andric       // truncate to the right size.
14120b57cec5SDimitry Andric       switch (VA.getLocInfo()) {
14130b57cec5SDimitry Andric       default:
14140b57cec5SDimitry Andric         llvm_unreachable("Unknown loc info!");
14150b57cec5SDimitry Andric       case CCValAssign::Full:
14160b57cec5SDimitry Andric         break;
14170b57cec5SDimitry Andric       case CCValAssign::BCvt:
14180b57cec5SDimitry Andric         ArgValue = DAG.getNode(ISD::BITCAST, dl, VA.getValVT(), ArgValue);
14190b57cec5SDimitry Andric         break;
14200b57cec5SDimitry Andric       case CCValAssign::SExt:
14210b57cec5SDimitry Andric         ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue,
14220b57cec5SDimitry Andric                                DAG.getValueType(VA.getValVT()));
14230b57cec5SDimitry Andric         ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
14240b57cec5SDimitry Andric         break;
14250b57cec5SDimitry Andric       case CCValAssign::ZExt:
14260b57cec5SDimitry Andric         ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue,
14270b57cec5SDimitry Andric                                DAG.getValueType(VA.getValVT()));
14280b57cec5SDimitry Andric         ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
14290b57cec5SDimitry Andric         break;
14300b57cec5SDimitry Andric       }
14310b57cec5SDimitry Andric 
14320b57cec5SDimitry Andric       InVals.push_back(ArgValue);
14330b57cec5SDimitry Andric     } else {
1434349cc55cSDimitry Andric       // Only arguments passed on the stack should make it here.
14350b57cec5SDimitry Andric       assert(VA.isMemLoc());
14360b57cec5SDimitry Andric 
14370b57cec5SDimitry Andric       EVT LocVT = VA.getLocVT();
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric       // Create the frame index object for this incoming parameter.
14400b57cec5SDimitry Andric       int FI = MFI.CreateFixedObject(LocVT.getSizeInBits() / 8,
14410b57cec5SDimitry Andric                                      VA.getLocMemOffset(), true);
14420b57cec5SDimitry Andric 
14430b57cec5SDimitry Andric       // Create the SelectionDAG nodes corresponding to a load
14440b57cec5SDimitry Andric       // from this parameter.
14450b57cec5SDimitry Andric       SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DL));
14460b57cec5SDimitry Andric       InVals.push_back(DAG.getLoad(LocVT, dl, Chain, FIN,
1447e8d8bef9SDimitry Andric                                    MachinePointerInfo::getFixedStack(MF, FI)));
14480b57cec5SDimitry Andric     }
14490b57cec5SDimitry Andric   }
14500b57cec5SDimitry Andric 
14510b57cec5SDimitry Andric   // If the function takes variable number of arguments, make a frame index for
14520b57cec5SDimitry Andric   // the start of the first vararg value... for expansion of llvm.va_start.
14530b57cec5SDimitry Andric   if (isVarArg) {
145406c3fb27SDimitry Andric     unsigned StackSize = CCInfo.getStackSize();
14550b57cec5SDimitry Andric     AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric     AFI->setVarArgsFrameIndex(MFI.CreateFixedObject(2, StackSize, true));
14580b57cec5SDimitry Andric   }
14590b57cec5SDimitry Andric 
14600b57cec5SDimitry Andric   return Chain;
14610b57cec5SDimitry Andric }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14640b57cec5SDimitry Andric //                  Call Calling Convention Implementation
14650b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
14680b57cec5SDimitry Andric                                      SmallVectorImpl<SDValue> &InVals) const {
14690b57cec5SDimitry Andric   SelectionDAG &DAG = CLI.DAG;
14700b57cec5SDimitry Andric   SDLoc &DL = CLI.DL;
14710b57cec5SDimitry Andric   SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
14720b57cec5SDimitry Andric   SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;
14730b57cec5SDimitry Andric   SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
14740b57cec5SDimitry Andric   SDValue Chain = CLI.Chain;
14750b57cec5SDimitry Andric   SDValue Callee = CLI.Callee;
14760b57cec5SDimitry Andric   bool &isTailCall = CLI.IsTailCall;
14770b57cec5SDimitry Andric   CallingConv::ID CallConv = CLI.CallConv;
14780b57cec5SDimitry Andric   bool isVarArg = CLI.IsVarArg;
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
14810b57cec5SDimitry Andric 
14820b57cec5SDimitry Andric   // AVR does not yet support tail call optimization.
14830b57cec5SDimitry Andric   isTailCall = false;
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   // Analyze operands of the call, assigning locations to each operand.
14860b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
14870b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
14880b57cec5SDimitry Andric                  *DAG.getContext());
14890b57cec5SDimitry Andric 
14900b57cec5SDimitry Andric   // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
14910b57cec5SDimitry Andric   // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
14920b57cec5SDimitry Andric   // node so that legalize doesn't hack it.
14930b57cec5SDimitry Andric   const Function *F = nullptr;
14940b57cec5SDimitry Andric   if (const GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
14950b57cec5SDimitry Andric     const GlobalValue *GV = G->getGlobal();
149681ad6265SDimitry Andric     if (isa<Function>(GV))
14970b57cec5SDimitry Andric       F = cast<Function>(GV);
14980b57cec5SDimitry Andric     Callee =
14990b57cec5SDimitry Andric         DAG.getTargetGlobalAddress(GV, DL, getPointerTy(DAG.getDataLayout()));
15000b57cec5SDimitry Andric   } else if (const ExternalSymbolSDNode *ES =
15010b57cec5SDimitry Andric                  dyn_cast<ExternalSymbolSDNode>(Callee)) {
15020b57cec5SDimitry Andric     Callee = DAG.getTargetExternalSymbol(ES->getSymbol(),
15030b57cec5SDimitry Andric                                          getPointerTy(DAG.getDataLayout()));
15040b57cec5SDimitry Andric   }
15050b57cec5SDimitry Andric 
15065ffd83dbSDimitry Andric   // Variadic functions do not need all the analysis below.
15075ffd83dbSDimitry Andric   if (isVarArg) {
15085ffd83dbSDimitry Andric     CCInfo.AnalyzeCallOperands(Outs, ArgCC_AVR_Vararg);
15095ffd83dbSDimitry Andric   } else {
151081ad6265SDimitry Andric     analyzeArguments(&CLI, F, &DAG.getDataLayout(), Outs, ArgLocs, CCInfo,
151181ad6265SDimitry Andric                      Subtarget.hasTinyEncoding());
15125ffd83dbSDimitry Andric   }
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   // Get a count of how many bytes are to be pushed on the stack.
151506c3fb27SDimitry Andric   unsigned NumBytes = CCInfo.getStackSize();
15160b57cec5SDimitry Andric 
15170b57cec5SDimitry Andric   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, DL);
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric   SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass;
15200b57cec5SDimitry Andric 
15210b57cec5SDimitry Andric   // First, walk the register assignments, inserting copies.
15220b57cec5SDimitry Andric   unsigned AI, AE;
15230b57cec5SDimitry Andric   bool HasStackArgs = false;
15240b57cec5SDimitry Andric   for (AI = 0, AE = ArgLocs.size(); AI != AE; ++AI) {
15250b57cec5SDimitry Andric     CCValAssign &VA = ArgLocs[AI];
15260b57cec5SDimitry Andric     EVT RegVT = VA.getLocVT();
15270b57cec5SDimitry Andric     SDValue Arg = OutVals[AI];
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric     // Promote the value if needed. With Clang this should not happen.
15300b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
15310b57cec5SDimitry Andric     default:
15320b57cec5SDimitry Andric       llvm_unreachable("Unknown loc info!");
15330b57cec5SDimitry Andric     case CCValAssign::Full:
15340b57cec5SDimitry Andric       break;
15350b57cec5SDimitry Andric     case CCValAssign::SExt:
15360b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::SIGN_EXTEND, DL, RegVT, Arg);
15370b57cec5SDimitry Andric       break;
15380b57cec5SDimitry Andric     case CCValAssign::ZExt:
15390b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ZERO_EXTEND, DL, RegVT, Arg);
15400b57cec5SDimitry Andric       break;
15410b57cec5SDimitry Andric     case CCValAssign::AExt:
15420b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ANY_EXTEND, DL, RegVT, Arg);
15430b57cec5SDimitry Andric       break;
15440b57cec5SDimitry Andric     case CCValAssign::BCvt:
15450b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::BITCAST, DL, RegVT, Arg);
15460b57cec5SDimitry Andric       break;
15470b57cec5SDimitry Andric     }
15480b57cec5SDimitry Andric 
15490b57cec5SDimitry Andric     // Stop when we encounter a stack argument, we need to process them
15500b57cec5SDimitry Andric     // in reverse order in the loop below.
15510b57cec5SDimitry Andric     if (VA.isMemLoc()) {
15520b57cec5SDimitry Andric       HasStackArgs = true;
15530b57cec5SDimitry Andric       break;
15540b57cec5SDimitry Andric     }
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric     // Arguments that can be passed on registers must be kept in the RegsToPass
15570b57cec5SDimitry Andric     // vector.
15580b57cec5SDimitry Andric     RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
15590b57cec5SDimitry Andric   }
15600b57cec5SDimitry Andric 
1561fe6060f1SDimitry Andric   // Second, stack arguments have to walked.
1562fe6060f1SDimitry Andric   // Previously this code created chained stores but those chained stores appear
1563fe6060f1SDimitry Andric   // to be unchained in the legalization phase. Therefore, do not attempt to
1564fe6060f1SDimitry Andric   // chain them here. In fact, chaining them here somehow causes the first and
1565fe6060f1SDimitry Andric   // second store to be reversed which is the exact opposite of the intended
1566fe6060f1SDimitry Andric   // effect.
15670b57cec5SDimitry Andric   if (HasStackArgs) {
1568fe6060f1SDimitry Andric     SmallVector<SDValue, 8> MemOpChains;
1569fe6060f1SDimitry Andric     for (; AI != AE; AI++) {
1570fe6060f1SDimitry Andric       CCValAssign &VA = ArgLocs[AI];
1571fe6060f1SDimitry Andric       SDValue Arg = OutVals[AI];
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric       assert(VA.isMemLoc());
15740b57cec5SDimitry Andric 
15750b57cec5SDimitry Andric       // SP points to one stack slot further so add one to adjust it.
15760b57cec5SDimitry Andric       SDValue PtrOff = DAG.getNode(
15770b57cec5SDimitry Andric           ISD::ADD, DL, getPointerTy(DAG.getDataLayout()),
15780b57cec5SDimitry Andric           DAG.getRegister(AVR::SP, getPointerTy(DAG.getDataLayout())),
15790b57cec5SDimitry Andric           DAG.getIntPtrConstant(VA.getLocMemOffset() + 1, DL));
15800b57cec5SDimitry Andric 
1581fe6060f1SDimitry Andric       MemOpChains.push_back(
15820b57cec5SDimitry Andric           DAG.getStore(Chain, DL, Arg, PtrOff,
1583fe6060f1SDimitry Andric                        MachinePointerInfo::getStack(MF, VA.getLocMemOffset())));
15840b57cec5SDimitry Andric     }
1585fe6060f1SDimitry Andric 
1586fe6060f1SDimitry Andric     if (!MemOpChains.empty())
1587fe6060f1SDimitry Andric       Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
15880b57cec5SDimitry Andric   }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric   // Build a sequence of copy-to-reg nodes chained together with token chain and
159106c3fb27SDimitry Andric   // flag operands which copy the outgoing args into registers.  The InGlue in
15920b57cec5SDimitry Andric   // necessary since all emited instructions must be stuck together.
159306c3fb27SDimitry Andric   SDValue InGlue;
15940b57cec5SDimitry Andric   for (auto Reg : RegsToPass) {
159506c3fb27SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, InGlue);
159606c3fb27SDimitry Andric     InGlue = Chain.getValue(1);
15970b57cec5SDimitry Andric   }
15980b57cec5SDimitry Andric 
15990b57cec5SDimitry Andric   // Returns a chain & a flag for retval copy to use.
16000b57cec5SDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
16010b57cec5SDimitry Andric   SmallVector<SDValue, 8> Ops;
16020b57cec5SDimitry Andric   Ops.push_back(Chain);
16030b57cec5SDimitry Andric   Ops.push_back(Callee);
16040b57cec5SDimitry Andric 
16050b57cec5SDimitry Andric   // Add argument registers to the end of the list so that they are known live
16060b57cec5SDimitry Andric   // into the call.
16070b57cec5SDimitry Andric   for (auto Reg : RegsToPass) {
16080b57cec5SDimitry Andric     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
16090b57cec5SDimitry Andric   }
16100b57cec5SDimitry Andric 
1611bdd1243dSDimitry Andric   // The zero register (usually R1) must be passed as an implicit register so
1612bdd1243dSDimitry Andric   // that this register is correctly zeroed in interrupts.
1613bdd1243dSDimitry Andric   Ops.push_back(DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8));
1614bdd1243dSDimitry Andric 
16150b57cec5SDimitry Andric   // Add a register mask operand representing the call-preserved registers.
16160b57cec5SDimitry Andric   const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
16170b57cec5SDimitry Andric   const uint32_t *Mask =
16180b57cec5SDimitry Andric       TRI->getCallPreservedMask(DAG.getMachineFunction(), CallConv);
16190b57cec5SDimitry Andric   assert(Mask && "Missing call preserved mask for calling convention");
16200b57cec5SDimitry Andric   Ops.push_back(DAG.getRegisterMask(Mask));
16210b57cec5SDimitry Andric 
162206c3fb27SDimitry Andric   if (InGlue.getNode()) {
162306c3fb27SDimitry Andric     Ops.push_back(InGlue);
16240b57cec5SDimitry Andric   }
16250b57cec5SDimitry Andric 
16260b57cec5SDimitry Andric   Chain = DAG.getNode(AVRISD::CALL, DL, NodeTys, Ops);
162706c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
16280b57cec5SDimitry Andric 
16290b57cec5SDimitry Andric   // Create the CALLSEQ_END node.
163006c3fb27SDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, DL);
16310b57cec5SDimitry Andric 
16320b57cec5SDimitry Andric   if (!Ins.empty()) {
163306c3fb27SDimitry Andric     InGlue = Chain.getValue(1);
16340b57cec5SDimitry Andric   }
16350b57cec5SDimitry Andric 
16360b57cec5SDimitry Andric   // Handle result values, copying them out of physregs into vregs that we
16370b57cec5SDimitry Andric   // return.
163806c3fb27SDimitry Andric   return LowerCallResult(Chain, InGlue, CallConv, isVarArg, Ins, DL, DAG,
16390b57cec5SDimitry Andric                          InVals);
16400b57cec5SDimitry Andric }
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric /// Lower the result values of a call into the
16430b57cec5SDimitry Andric /// appropriate copies out of appropriate physical registers.
16440b57cec5SDimitry Andric ///
16450b57cec5SDimitry Andric SDValue AVRTargetLowering::LowerCallResult(
164606c3fb27SDimitry Andric     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool isVarArg,
1647349cc55cSDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
1648349cc55cSDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric   // Assign locations to each value returned by this call.
16510b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
16520b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
16530b57cec5SDimitry Andric                  *DAG.getContext());
16540b57cec5SDimitry Andric 
16550b57cec5SDimitry Andric   // Handle runtime calling convs.
16565ffd83dbSDimitry Andric   if (CallConv == CallingConv::AVR_BUILTIN) {
16575ffd83dbSDimitry Andric     CCInfo.AnalyzeCallResult(Ins, RetCC_AVR_BUILTIN);
16585ffd83dbSDimitry Andric   } else {
165981ad6265SDimitry Andric     analyzeReturnValues(Ins, CCInfo, Subtarget.hasTinyEncoding());
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric   // Copy all of the result registers out of their specified physreg.
16630b57cec5SDimitry Andric   for (CCValAssign const &RVLoc : RVLocs) {
16640b57cec5SDimitry Andric     Chain = DAG.getCopyFromReg(Chain, dl, RVLoc.getLocReg(), RVLoc.getValVT(),
166506c3fb27SDimitry Andric                                InGlue)
16660b57cec5SDimitry Andric                 .getValue(1);
166706c3fb27SDimitry Andric     InGlue = Chain.getValue(2);
16680b57cec5SDimitry Andric     InVals.push_back(Chain.getValue(0));
16690b57cec5SDimitry Andric   }
16700b57cec5SDimitry Andric 
16710b57cec5SDimitry Andric   return Chain;
16720b57cec5SDimitry Andric }
16730b57cec5SDimitry Andric 
16740b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16750b57cec5SDimitry Andric //               Return Value Calling Convention Implementation
16760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
16770b57cec5SDimitry Andric 
16785ffd83dbSDimitry Andric bool AVRTargetLowering::CanLowerReturn(
16795ffd83dbSDimitry Andric     CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
16805ffd83dbSDimitry Andric     const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const {
16815ffd83dbSDimitry Andric   if (CallConv == CallingConv::AVR_BUILTIN) {
16820b57cec5SDimitry Andric     SmallVector<CCValAssign, 16> RVLocs;
16830b57cec5SDimitry Andric     CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
16845ffd83dbSDimitry Andric     return CCInfo.CheckReturn(Outs, RetCC_AVR_BUILTIN);
16855ffd83dbSDimitry Andric   }
16860b57cec5SDimitry Andric 
16875ffd83dbSDimitry Andric   unsigned TotalBytes = getTotalArgumentsSizeInBytes(Outs);
1688bdd1243dSDimitry Andric   return TotalBytes <= (unsigned)(Subtarget.hasTinyEncoding() ? 4 : 8);
16890b57cec5SDimitry Andric }
16900b57cec5SDimitry Andric 
16910b57cec5SDimitry Andric SDValue
16920b57cec5SDimitry Andric AVRTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
16930b57cec5SDimitry Andric                                bool isVarArg,
16940b57cec5SDimitry Andric                                const SmallVectorImpl<ISD::OutputArg> &Outs,
16950b57cec5SDimitry Andric                                const SmallVectorImpl<SDValue> &OutVals,
16960b57cec5SDimitry Andric                                const SDLoc &dl, SelectionDAG &DAG) const {
16970b57cec5SDimitry Andric   // CCValAssign - represent the assignment of the return value to locations.
16980b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
16990b57cec5SDimitry Andric 
17000b57cec5SDimitry Andric   // CCState - Info about the registers and stack slot.
17010b57cec5SDimitry Andric   CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
17020b57cec5SDimitry Andric                  *DAG.getContext());
17030b57cec5SDimitry Andric 
17040b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
17050b57cec5SDimitry Andric 
17065ffd83dbSDimitry Andric   // Analyze return values.
17075ffd83dbSDimitry Andric   if (CallConv == CallingConv::AVR_BUILTIN) {
17085ffd83dbSDimitry Andric     CCInfo.AnalyzeReturn(Outs, RetCC_AVR_BUILTIN);
17095ffd83dbSDimitry Andric   } else {
171081ad6265SDimitry Andric     analyzeReturnValues(Outs, CCInfo, Subtarget.hasTinyEncoding());
17110b57cec5SDimitry Andric   }
17120b57cec5SDimitry Andric 
171306c3fb27SDimitry Andric   SDValue Glue;
17140b57cec5SDimitry Andric   SmallVector<SDValue, 4> RetOps(1, Chain);
17150b57cec5SDimitry Andric   // Copy the result values into the output registers.
17165ffd83dbSDimitry Andric   for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) {
17170b57cec5SDimitry Andric     CCValAssign &VA = RVLocs[i];
17180b57cec5SDimitry Andric     assert(VA.isRegLoc() && "Can only return in registers!");
17190b57cec5SDimitry Andric 
172006c3fb27SDimitry Andric     Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), OutVals[i], Glue);
17210b57cec5SDimitry Andric 
17220b57cec5SDimitry Andric     // Guarantee that all emitted copies are stuck together with flags.
172306c3fb27SDimitry Andric     Glue = Chain.getValue(1);
17240b57cec5SDimitry Andric     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
17250b57cec5SDimitry Andric   }
17260b57cec5SDimitry Andric 
17270b57cec5SDimitry Andric   // Don't emit the ret/reti instruction when the naked attribute is present in
17280b57cec5SDimitry Andric   // the function being compiled.
1729349cc55cSDimitry Andric   if (MF.getFunction().getAttributes().hasFnAttr(Attribute::Naked)) {
17300b57cec5SDimitry Andric     return Chain;
17310b57cec5SDimitry Andric   }
17320b57cec5SDimitry Andric 
17335ffd83dbSDimitry Andric   const AVRMachineFunctionInfo *AFI = MF.getInfo<AVRMachineFunctionInfo>();
17345ffd83dbSDimitry Andric 
1735bdd1243dSDimitry Andric   if (!AFI->isInterruptOrSignalHandler()) {
1736bdd1243dSDimitry Andric     // The return instruction has an implicit zero register operand: it must
1737bdd1243dSDimitry Andric     // contain zero on return.
1738bdd1243dSDimitry Andric     // This is not needed in interrupts however, where the zero register is
1739bdd1243dSDimitry Andric     // handled specially (only pushed/popped when needed).
1740bdd1243dSDimitry Andric     RetOps.push_back(DAG.getRegister(Subtarget.getZeroRegister(), MVT::i8));
1741bdd1243dSDimitry Andric   }
1742bdd1243dSDimitry Andric 
17430b57cec5SDimitry Andric   unsigned RetOpc =
174406c3fb27SDimitry Andric       AFI->isInterruptOrSignalHandler() ? AVRISD::RETI_GLUE : AVRISD::RET_GLUE;
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric   RetOps[0] = Chain; // Update chain.
17470b57cec5SDimitry Andric 
174806c3fb27SDimitry Andric   if (Glue.getNode()) {
174906c3fb27SDimitry Andric     RetOps.push_back(Glue);
17500b57cec5SDimitry Andric   }
17510b57cec5SDimitry Andric 
17520b57cec5SDimitry Andric   return DAG.getNode(RetOpc, dl, MVT::Other, RetOps);
17530b57cec5SDimitry Andric }
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
17560b57cec5SDimitry Andric //  Custom Inserters
17570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
17580b57cec5SDimitry Andric 
17590b57cec5SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
176006c3fb27SDimitry Andric                                                   MachineBasicBlock *BB,
176106c3fb27SDimitry Andric                                                   bool Tiny) const {
17620b57cec5SDimitry Andric   unsigned Opc;
17630b57cec5SDimitry Andric   const TargetRegisterClass *RC;
17640b57cec5SDimitry Andric   bool HasRepeatedOperand = false;
17650b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
17660b57cec5SDimitry Andric   MachineRegisterInfo &RI = F->getRegInfo();
17670b57cec5SDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
17680b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric   switch (MI.getOpcode()) {
17710b57cec5SDimitry Andric   default:
17720b57cec5SDimitry Andric     llvm_unreachable("Invalid shift opcode!");
17730b57cec5SDimitry Andric   case AVR::Lsl8:
17740b57cec5SDimitry Andric     Opc = AVR::ADDRdRr; // LSL is an alias of ADD Rd, Rd
17750b57cec5SDimitry Andric     RC = &AVR::GPR8RegClass;
17760b57cec5SDimitry Andric     HasRepeatedOperand = true;
17770b57cec5SDimitry Andric     break;
17780b57cec5SDimitry Andric   case AVR::Lsl16:
17790b57cec5SDimitry Andric     Opc = AVR::LSLWRd;
17800b57cec5SDimitry Andric     RC = &AVR::DREGSRegClass;
17810b57cec5SDimitry Andric     break;
17820b57cec5SDimitry Andric   case AVR::Asr8:
17830b57cec5SDimitry Andric     Opc = AVR::ASRRd;
17840b57cec5SDimitry Andric     RC = &AVR::GPR8RegClass;
17850b57cec5SDimitry Andric     break;
17860b57cec5SDimitry Andric   case AVR::Asr16:
17870b57cec5SDimitry Andric     Opc = AVR::ASRWRd;
17880b57cec5SDimitry Andric     RC = &AVR::DREGSRegClass;
17890b57cec5SDimitry Andric     break;
17900b57cec5SDimitry Andric   case AVR::Lsr8:
17910b57cec5SDimitry Andric     Opc = AVR::LSRRd;
17920b57cec5SDimitry Andric     RC = &AVR::GPR8RegClass;
17930b57cec5SDimitry Andric     break;
17940b57cec5SDimitry Andric   case AVR::Lsr16:
17950b57cec5SDimitry Andric     Opc = AVR::LSRWRd;
17960b57cec5SDimitry Andric     RC = &AVR::DREGSRegClass;
17970b57cec5SDimitry Andric     break;
17980b57cec5SDimitry Andric   case AVR::Rol8:
179906c3fb27SDimitry Andric     Opc = Tiny ? AVR::ROLBRdR17 : AVR::ROLBRdR1;
18000b57cec5SDimitry Andric     RC = &AVR::GPR8RegClass;
18010b57cec5SDimitry Andric     break;
18020b57cec5SDimitry Andric   case AVR::Rol16:
18030b57cec5SDimitry Andric     Opc = AVR::ROLWRd;
18040b57cec5SDimitry Andric     RC = &AVR::DREGSRegClass;
18050b57cec5SDimitry Andric     break;
18060b57cec5SDimitry Andric   case AVR::Ror8:
1807480093f4SDimitry Andric     Opc = AVR::RORBRd;
18080b57cec5SDimitry Andric     RC = &AVR::GPR8RegClass;
18090b57cec5SDimitry Andric     break;
18100b57cec5SDimitry Andric   case AVR::Ror16:
18110b57cec5SDimitry Andric     Opc = AVR::RORWRd;
18120b57cec5SDimitry Andric     RC = &AVR::DREGSRegClass;
18130b57cec5SDimitry Andric     break;
18140b57cec5SDimitry Andric   }
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
18170b57cec5SDimitry Andric 
18180b57cec5SDimitry Andric   MachineFunction::iterator I;
1819349cc55cSDimitry Andric   for (I = BB->getIterator(); I != F->end() && &(*I) != BB; ++I)
1820349cc55cSDimitry Andric     ;
1821349cc55cSDimitry Andric   if (I != F->end())
1822349cc55cSDimitry Andric     ++I;
18230b57cec5SDimitry Andric 
18240b57cec5SDimitry Andric   // Create loop block.
18250b57cec5SDimitry Andric   MachineBasicBlock *LoopBB = F->CreateMachineBasicBlock(LLVM_BB);
1826e8d8bef9SDimitry Andric   MachineBasicBlock *CheckBB = F->CreateMachineBasicBlock(LLVM_BB);
18270b57cec5SDimitry Andric   MachineBasicBlock *RemBB = F->CreateMachineBasicBlock(LLVM_BB);
18280b57cec5SDimitry Andric 
18290b57cec5SDimitry Andric   F->insert(I, LoopBB);
1830e8d8bef9SDimitry Andric   F->insert(I, CheckBB);
18310b57cec5SDimitry Andric   F->insert(I, RemBB);
18320b57cec5SDimitry Andric 
18330b57cec5SDimitry Andric   // Update machine-CFG edges by transferring all successors of the current
18340b57cec5SDimitry Andric   // block to the block containing instructions after shift.
18350b57cec5SDimitry Andric   RemBB->splice(RemBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)),
18360b57cec5SDimitry Andric                 BB->end());
18370b57cec5SDimitry Andric   RemBB->transferSuccessorsAndUpdatePHIs(BB);
18380b57cec5SDimitry Andric 
1839e8d8bef9SDimitry Andric   // Add edges BB => LoopBB => CheckBB => RemBB, CheckBB => LoopBB.
1840e8d8bef9SDimitry Andric   BB->addSuccessor(CheckBB);
1841e8d8bef9SDimitry Andric   LoopBB->addSuccessor(CheckBB);
1842e8d8bef9SDimitry Andric   CheckBB->addSuccessor(LoopBB);
1843e8d8bef9SDimitry Andric   CheckBB->addSuccessor(RemBB);
18440b57cec5SDimitry Andric 
1845e8d8bef9SDimitry Andric   Register ShiftAmtReg = RI.createVirtualRegister(&AVR::GPR8RegClass);
1846e8d8bef9SDimitry Andric   Register ShiftAmtReg2 = RI.createVirtualRegister(&AVR::GPR8RegClass);
18478bcb0991SDimitry Andric   Register ShiftReg = RI.createVirtualRegister(RC);
18488bcb0991SDimitry Andric   Register ShiftReg2 = RI.createVirtualRegister(RC);
18498bcb0991SDimitry Andric   Register ShiftAmtSrcReg = MI.getOperand(2).getReg();
18508bcb0991SDimitry Andric   Register SrcReg = MI.getOperand(1).getReg();
18518bcb0991SDimitry Andric   Register DstReg = MI.getOperand(0).getReg();
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   // BB:
1854e8d8bef9SDimitry Andric   // rjmp CheckBB
1855e8d8bef9SDimitry Andric   BuildMI(BB, dl, TII.get(AVR::RJMPk)).addMBB(CheckBB);
18560b57cec5SDimitry Andric 
18570b57cec5SDimitry Andric   // LoopBB:
18580b57cec5SDimitry Andric   // ShiftReg2 = shift ShiftReg
18590b57cec5SDimitry Andric   auto ShiftMI = BuildMI(LoopBB, dl, TII.get(Opc), ShiftReg2).addReg(ShiftReg);
18600b57cec5SDimitry Andric   if (HasRepeatedOperand)
18610b57cec5SDimitry Andric     ShiftMI.addReg(ShiftReg);
18620b57cec5SDimitry Andric 
1863e8d8bef9SDimitry Andric   // CheckBB:
1864e8d8bef9SDimitry Andric   // ShiftReg = phi [%SrcReg, BB], [%ShiftReg2, LoopBB]
1865e8d8bef9SDimitry Andric   // ShiftAmt = phi [%N,      BB], [%ShiftAmt2, LoopBB]
18660b57cec5SDimitry Andric   // DestReg  = phi [%SrcReg, BB], [%ShiftReg,  LoopBB]
1867e8d8bef9SDimitry Andric   // ShiftAmt2 = ShiftAmt - 1;
1868e8d8bef9SDimitry Andric   // if (ShiftAmt2 >= 0) goto LoopBB;
1869e8d8bef9SDimitry Andric   BuildMI(CheckBB, dl, TII.get(AVR::PHI), ShiftReg)
18700b57cec5SDimitry Andric       .addReg(SrcReg)
18710b57cec5SDimitry Andric       .addMBB(BB)
18720b57cec5SDimitry Andric       .addReg(ShiftReg2)
18730b57cec5SDimitry Andric       .addMBB(LoopBB);
1874e8d8bef9SDimitry Andric   BuildMI(CheckBB, dl, TII.get(AVR::PHI), ShiftAmtReg)
1875e8d8bef9SDimitry Andric       .addReg(ShiftAmtSrcReg)
1876e8d8bef9SDimitry Andric       .addMBB(BB)
1877e8d8bef9SDimitry Andric       .addReg(ShiftAmtReg2)
1878e8d8bef9SDimitry Andric       .addMBB(LoopBB);
1879e8d8bef9SDimitry Andric   BuildMI(CheckBB, dl, TII.get(AVR::PHI), DstReg)
1880e8d8bef9SDimitry Andric       .addReg(SrcReg)
1881e8d8bef9SDimitry Andric       .addMBB(BB)
1882e8d8bef9SDimitry Andric       .addReg(ShiftReg2)
1883e8d8bef9SDimitry Andric       .addMBB(LoopBB);
1884e8d8bef9SDimitry Andric 
1885349cc55cSDimitry Andric   BuildMI(CheckBB, dl, TII.get(AVR::DECRd), ShiftAmtReg2).addReg(ShiftAmtReg);
1886e8d8bef9SDimitry Andric   BuildMI(CheckBB, dl, TII.get(AVR::BRPLk)).addMBB(LoopBB);
18870b57cec5SDimitry Andric 
18880b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
18890b57cec5SDimitry Andric   return RemBB;
18900b57cec5SDimitry Andric }
18910b57cec5SDimitry Andric 
1892bdd1243dSDimitry Andric // Do a multibyte AVR shift. Insert shift instructions and put the output
1893bdd1243dSDimitry Andric // registers in the Regs array.
1894bdd1243dSDimitry Andric // Because AVR does not have a normal shift instruction (only a single bit shift
1895bdd1243dSDimitry Andric // instruction), we have to emulate this behavior with other instructions.
1896bdd1243dSDimitry Andric // It first tries large steps (moving registers around) and then smaller steps
1897bdd1243dSDimitry Andric // like single bit shifts.
1898bdd1243dSDimitry Andric // Large shifts actually reduce the number of shifted registers, so the below
1899bdd1243dSDimitry Andric // algorithms have to work independently of the number of registers that are
1900bdd1243dSDimitry Andric // shifted.
1901bdd1243dSDimitry Andric // For more information and background, see this blogpost:
1902bdd1243dSDimitry Andric // https://aykevl.nl/2021/02/avr-bitshift
1903bdd1243dSDimitry Andric static void insertMultibyteShift(MachineInstr &MI, MachineBasicBlock *BB,
1904bdd1243dSDimitry Andric                                  MutableArrayRef<std::pair<Register, int>> Regs,
1905bdd1243dSDimitry Andric                                  ISD::NodeType Opc, int64_t ShiftAmt) {
1906bdd1243dSDimitry Andric   const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
1907bdd1243dSDimitry Andric   const AVRSubtarget &STI = BB->getParent()->getSubtarget<AVRSubtarget>();
1908bdd1243dSDimitry Andric   MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
1909bdd1243dSDimitry Andric   const DebugLoc &dl = MI.getDebugLoc();
1910bdd1243dSDimitry Andric 
1911bdd1243dSDimitry Andric   const bool ShiftLeft = Opc == ISD::SHL;
1912bdd1243dSDimitry Andric   const bool ArithmeticShift = Opc == ISD::SRA;
1913bdd1243dSDimitry Andric 
1914bdd1243dSDimitry Andric   // Zero a register, for use in later operations.
1915bdd1243dSDimitry Andric   Register ZeroReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1916bdd1243dSDimitry Andric   BuildMI(*BB, MI, dl, TII.get(AVR::COPY), ZeroReg)
1917bdd1243dSDimitry Andric       .addReg(STI.getZeroRegister());
1918bdd1243dSDimitry Andric 
1919bdd1243dSDimitry Andric   // Do a shift modulo 6 or 7. This is a bit more complicated than most shifts
1920bdd1243dSDimitry Andric   // and is hard to compose with the rest, so these are special cased.
1921bdd1243dSDimitry Andric   // The basic idea is to shift one or two bits in the opposite direction and
1922bdd1243dSDimitry Andric   // then move registers around to get the correct end result.
1923bdd1243dSDimitry Andric   if (ShiftLeft && (ShiftAmt % 8) >= 6) {
1924bdd1243dSDimitry Andric     // Left shift modulo 6 or 7.
1925bdd1243dSDimitry Andric 
1926bdd1243dSDimitry Andric     // Create a slice of the registers we're going to modify, to ease working
1927bdd1243dSDimitry Andric     // with them.
1928bdd1243dSDimitry Andric     size_t ShiftRegsOffset = ShiftAmt / 8;
1929bdd1243dSDimitry Andric     size_t ShiftRegsSize = Regs.size() - ShiftRegsOffset;
1930bdd1243dSDimitry Andric     MutableArrayRef<std::pair<Register, int>> ShiftRegs =
1931bdd1243dSDimitry Andric         Regs.slice(ShiftRegsOffset, ShiftRegsSize);
1932bdd1243dSDimitry Andric 
1933bdd1243dSDimitry Andric     // Shift one to the right, keeping the least significant bit as the carry
1934bdd1243dSDimitry Andric     // bit.
1935bdd1243dSDimitry Andric     insertMultibyteShift(MI, BB, ShiftRegs, ISD::SRL, 1);
1936bdd1243dSDimitry Andric 
1937bdd1243dSDimitry Andric     // Rotate the least significant bit from the carry bit into a new register
1938bdd1243dSDimitry Andric     // (that starts out zero).
1939bdd1243dSDimitry Andric     Register LowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1940bdd1243dSDimitry Andric     BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), LowByte).addReg(ZeroReg);
1941bdd1243dSDimitry Andric 
1942bdd1243dSDimitry Andric     // Shift one more to the right if this is a modulo-6 shift.
1943bdd1243dSDimitry Andric     if (ShiftAmt % 8 == 6) {
1944bdd1243dSDimitry Andric       insertMultibyteShift(MI, BB, ShiftRegs, ISD::SRL, 1);
1945bdd1243dSDimitry Andric       Register NewLowByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1946bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), NewLowByte).addReg(LowByte);
1947bdd1243dSDimitry Andric       LowByte = NewLowByte;
1948bdd1243dSDimitry Andric     }
1949bdd1243dSDimitry Andric 
1950bdd1243dSDimitry Andric     // Move all registers to the left, zeroing the bottom registers as needed.
1951bdd1243dSDimitry Andric     for (size_t I = 0; I < Regs.size(); I++) {
1952bdd1243dSDimitry Andric       int ShiftRegsIdx = I + 1;
1953bdd1243dSDimitry Andric       if (ShiftRegsIdx < (int)ShiftRegs.size()) {
1954bdd1243dSDimitry Andric         Regs[I] = ShiftRegs[ShiftRegsIdx];
1955bdd1243dSDimitry Andric       } else if (ShiftRegsIdx == (int)ShiftRegs.size()) {
1956bdd1243dSDimitry Andric         Regs[I] = std::pair(LowByte, 0);
1957bdd1243dSDimitry Andric       } else {
1958bdd1243dSDimitry Andric         Regs[I] = std::pair(ZeroReg, 0);
1959bdd1243dSDimitry Andric       }
1960bdd1243dSDimitry Andric     }
1961bdd1243dSDimitry Andric 
1962bdd1243dSDimitry Andric     return;
1963bdd1243dSDimitry Andric   }
1964bdd1243dSDimitry Andric 
1965bdd1243dSDimitry Andric   // Right shift modulo 6 or 7.
1966bdd1243dSDimitry Andric   if (!ShiftLeft && (ShiftAmt % 8) >= 6) {
1967bdd1243dSDimitry Andric     // Create a view on the registers we're going to modify, to ease working
1968bdd1243dSDimitry Andric     // with them.
1969bdd1243dSDimitry Andric     size_t ShiftRegsSize = Regs.size() - (ShiftAmt / 8);
1970bdd1243dSDimitry Andric     MutableArrayRef<std::pair<Register, int>> ShiftRegs =
1971bdd1243dSDimitry Andric         Regs.slice(0, ShiftRegsSize);
1972bdd1243dSDimitry Andric 
1973bdd1243dSDimitry Andric     // Shift one to the left.
1974bdd1243dSDimitry Andric     insertMultibyteShift(MI, BB, ShiftRegs, ISD::SHL, 1);
1975bdd1243dSDimitry Andric 
1976bdd1243dSDimitry Andric     // Sign or zero extend the most significant register into a new register.
1977bdd1243dSDimitry Andric     // The HighByte is the byte that still has one (or two) bits from the
1978bdd1243dSDimitry Andric     // original value. The ExtByte is purely a zero/sign extend byte (all bits
1979bdd1243dSDimitry Andric     // are either 0 or 1).
1980bdd1243dSDimitry Andric     Register HighByte = MRI.createVirtualRegister(&AVR::GPR8RegClass);
1981bdd1243dSDimitry Andric     Register ExtByte = 0;
1982bdd1243dSDimitry Andric     if (ArithmeticShift) {
1983bdd1243dSDimitry Andric       // Sign-extend bit that was shifted out last.
1984bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::SBCRdRr), HighByte)
1985bdd1243dSDimitry Andric           .addReg(HighByte, RegState::Undef)
1986bdd1243dSDimitry Andric           .addReg(HighByte, RegState::Undef);
1987bdd1243dSDimitry Andric       ExtByte = HighByte;
1988bdd1243dSDimitry Andric       // The highest bit of the original value is the same as the zero-extend
1989bdd1243dSDimitry Andric       // byte, so HighByte and ExtByte are the same.
1990bdd1243dSDimitry Andric     } else {
1991bdd1243dSDimitry Andric       // Use the zero register for zero extending.
1992bdd1243dSDimitry Andric       ExtByte = ZeroReg;
1993bdd1243dSDimitry Andric       // Rotate most significant bit into a new register (that starts out zero).
1994bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), HighByte)
1995bdd1243dSDimitry Andric           .addReg(ExtByte)
1996bdd1243dSDimitry Andric           .addReg(ExtByte);
1997bdd1243dSDimitry Andric     }
1998bdd1243dSDimitry Andric 
1999bdd1243dSDimitry Andric     // Shift one more to the left for modulo 6 shifts.
2000bdd1243dSDimitry Andric     if (ShiftAmt % 8 == 6) {
2001bdd1243dSDimitry Andric       insertMultibyteShift(MI, BB, ShiftRegs, ISD::SHL, 1);
2002bdd1243dSDimitry Andric       // Shift the topmost bit into the HighByte.
2003bdd1243dSDimitry Andric       Register NewExt = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2004bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), NewExt)
2005bdd1243dSDimitry Andric           .addReg(HighByte)
2006bdd1243dSDimitry Andric           .addReg(HighByte);
2007bdd1243dSDimitry Andric       HighByte = NewExt;
2008bdd1243dSDimitry Andric     }
2009bdd1243dSDimitry Andric 
2010bdd1243dSDimitry Andric     // Move all to the right, while sign or zero extending.
2011bdd1243dSDimitry Andric     for (int I = Regs.size() - 1; I >= 0; I--) {
2012bdd1243dSDimitry Andric       int ShiftRegsIdx = I - (Regs.size() - ShiftRegs.size()) - 1;
2013bdd1243dSDimitry Andric       if (ShiftRegsIdx >= 0) {
2014bdd1243dSDimitry Andric         Regs[I] = ShiftRegs[ShiftRegsIdx];
2015bdd1243dSDimitry Andric       } else if (ShiftRegsIdx == -1) {
2016bdd1243dSDimitry Andric         Regs[I] = std::pair(HighByte, 0);
2017bdd1243dSDimitry Andric       } else {
2018bdd1243dSDimitry Andric         Regs[I] = std::pair(ExtByte, 0);
2019bdd1243dSDimitry Andric       }
2020bdd1243dSDimitry Andric     }
2021bdd1243dSDimitry Andric 
2022bdd1243dSDimitry Andric     return;
2023bdd1243dSDimitry Andric   }
2024bdd1243dSDimitry Andric 
2025bdd1243dSDimitry Andric   // For shift amounts of at least one register, simply rename the registers and
2026bdd1243dSDimitry Andric   // zero the bottom registers.
2027bdd1243dSDimitry Andric   while (ShiftLeft && ShiftAmt >= 8) {
2028bdd1243dSDimitry Andric     // Move all registers one to the left.
2029bdd1243dSDimitry Andric     for (size_t I = 0; I < Regs.size() - 1; I++) {
2030bdd1243dSDimitry Andric       Regs[I] = Regs[I + 1];
2031bdd1243dSDimitry Andric     }
2032bdd1243dSDimitry Andric 
2033bdd1243dSDimitry Andric     // Zero the least significant register.
2034bdd1243dSDimitry Andric     Regs[Regs.size() - 1] = std::pair(ZeroReg, 0);
2035bdd1243dSDimitry Andric 
2036bdd1243dSDimitry Andric     // Continue shifts with the leftover registers.
2037bdd1243dSDimitry Andric     Regs = Regs.drop_back(1);
2038bdd1243dSDimitry Andric 
2039bdd1243dSDimitry Andric     ShiftAmt -= 8;
2040bdd1243dSDimitry Andric   }
2041bdd1243dSDimitry Andric 
2042bdd1243dSDimitry Andric   // And again, the same for right shifts.
2043bdd1243dSDimitry Andric   Register ShrExtendReg = 0;
2044bdd1243dSDimitry Andric   if (!ShiftLeft && ShiftAmt >= 8) {
2045bdd1243dSDimitry Andric     if (ArithmeticShift) {
2046bdd1243dSDimitry Andric       // Sign extend the most significant register into ShrExtendReg.
2047bdd1243dSDimitry Andric       ShrExtendReg = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2048bdd1243dSDimitry Andric       Register Tmp = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2049bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::ADDRdRr), Tmp)
2050bdd1243dSDimitry Andric           .addReg(Regs[0].first, 0, Regs[0].second)
2051bdd1243dSDimitry Andric           .addReg(Regs[0].first, 0, Regs[0].second);
2052bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::SBCRdRr), ShrExtendReg)
2053bdd1243dSDimitry Andric           .addReg(Tmp)
2054bdd1243dSDimitry Andric           .addReg(Tmp);
2055bdd1243dSDimitry Andric     } else {
2056bdd1243dSDimitry Andric       ShrExtendReg = ZeroReg;
2057bdd1243dSDimitry Andric     }
2058bdd1243dSDimitry Andric     for (; ShiftAmt >= 8; ShiftAmt -= 8) {
2059bdd1243dSDimitry Andric       // Move all registers one to the right.
2060bdd1243dSDimitry Andric       for (size_t I = Regs.size() - 1; I != 0; I--) {
2061bdd1243dSDimitry Andric         Regs[I] = Regs[I - 1];
2062bdd1243dSDimitry Andric       }
2063bdd1243dSDimitry Andric 
2064bdd1243dSDimitry Andric       // Zero or sign extend the most significant register.
2065bdd1243dSDimitry Andric       Regs[0] = std::pair(ShrExtendReg, 0);
2066bdd1243dSDimitry Andric 
2067bdd1243dSDimitry Andric       // Continue shifts with the leftover registers.
2068bdd1243dSDimitry Andric       Regs = Regs.drop_front(1);
2069bdd1243dSDimitry Andric     }
2070bdd1243dSDimitry Andric   }
2071bdd1243dSDimitry Andric 
2072bdd1243dSDimitry Andric   // The bigger shifts are already handled above.
2073bdd1243dSDimitry Andric   assert((ShiftAmt < 8) && "Unexpect shift amount");
2074bdd1243dSDimitry Andric 
2075bdd1243dSDimitry Andric   // Shift by four bits, using a complicated swap/eor/andi/eor sequence.
2076bdd1243dSDimitry Andric   // It only works for logical shifts because the bits shifted in are all
2077bdd1243dSDimitry Andric   // zeroes.
2078bdd1243dSDimitry Andric   // To shift a single byte right, it produces code like this:
2079bdd1243dSDimitry Andric   //   swap r0
2080bdd1243dSDimitry Andric   //   andi r0, 0x0f
2081bdd1243dSDimitry Andric   // For a two-byte (16-bit) shift, it adds the following instructions to shift
2082bdd1243dSDimitry Andric   // the upper byte into the lower byte:
2083bdd1243dSDimitry Andric   //   swap r1
2084bdd1243dSDimitry Andric   //   eor r0, r1
2085bdd1243dSDimitry Andric   //   andi r1, 0x0f
2086bdd1243dSDimitry Andric   //   eor r0, r1
2087bdd1243dSDimitry Andric   // For bigger shifts, it repeats the above sequence. For example, for a 3-byte
2088bdd1243dSDimitry Andric   // (24-bit) shift it adds:
2089bdd1243dSDimitry Andric   //   swap r2
2090bdd1243dSDimitry Andric   //   eor r1, r2
2091bdd1243dSDimitry Andric   //   andi r2, 0x0f
2092bdd1243dSDimitry Andric   //   eor r1, r2
2093bdd1243dSDimitry Andric   if (!ArithmeticShift && ShiftAmt >= 4) {
2094bdd1243dSDimitry Andric     Register Prev = 0;
2095bdd1243dSDimitry Andric     for (size_t I = 0; I < Regs.size(); I++) {
2096bdd1243dSDimitry Andric       size_t Idx = ShiftLeft ? I : Regs.size() - I - 1;
2097bdd1243dSDimitry Andric       Register SwapReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2098bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::SWAPRd), SwapReg)
2099bdd1243dSDimitry Andric           .addReg(Regs[Idx].first, 0, Regs[Idx].second);
2100bdd1243dSDimitry Andric       if (I != 0) {
2101bdd1243dSDimitry Andric         Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2102bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(AVR::EORRdRr), R)
2103bdd1243dSDimitry Andric             .addReg(Prev)
2104bdd1243dSDimitry Andric             .addReg(SwapReg);
2105bdd1243dSDimitry Andric         Prev = R;
2106bdd1243dSDimitry Andric       }
2107bdd1243dSDimitry Andric       Register AndReg = MRI.createVirtualRegister(&AVR::LD8RegClass);
2108bdd1243dSDimitry Andric       BuildMI(*BB, MI, dl, TII.get(AVR::ANDIRdK), AndReg)
2109bdd1243dSDimitry Andric           .addReg(SwapReg)
2110bdd1243dSDimitry Andric           .addImm(ShiftLeft ? 0xf0 : 0x0f);
2111bdd1243dSDimitry Andric       if (I != 0) {
2112bdd1243dSDimitry Andric         Register R = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2113bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(AVR::EORRdRr), R)
2114bdd1243dSDimitry Andric             .addReg(Prev)
2115bdd1243dSDimitry Andric             .addReg(AndReg);
2116bdd1243dSDimitry Andric         size_t PrevIdx = ShiftLeft ? Idx - 1 : Idx + 1;
2117bdd1243dSDimitry Andric         Regs[PrevIdx] = std::pair(R, 0);
2118bdd1243dSDimitry Andric       }
2119bdd1243dSDimitry Andric       Prev = AndReg;
2120bdd1243dSDimitry Andric       Regs[Idx] = std::pair(AndReg, 0);
2121bdd1243dSDimitry Andric     }
2122bdd1243dSDimitry Andric     ShiftAmt -= 4;
2123bdd1243dSDimitry Andric   }
2124bdd1243dSDimitry Andric 
2125bdd1243dSDimitry Andric   // Shift by one. This is the fallback that always works, and the shift
2126bdd1243dSDimitry Andric   // operation that is used for 1, 2, and 3 bit shifts.
2127bdd1243dSDimitry Andric   while (ShiftLeft && ShiftAmt) {
2128bdd1243dSDimitry Andric     // Shift one to the left.
2129bdd1243dSDimitry Andric     for (ssize_t I = Regs.size() - 1; I >= 0; I--) {
2130bdd1243dSDimitry Andric       Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2131bdd1243dSDimitry Andric       Register In = Regs[I].first;
2132bdd1243dSDimitry Andric       Register InSubreg = Regs[I].second;
2133bdd1243dSDimitry Andric       if (I == (ssize_t)Regs.size() - 1) { // first iteration
2134bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(AVR::ADDRdRr), Out)
2135bdd1243dSDimitry Andric             .addReg(In, 0, InSubreg)
2136bdd1243dSDimitry Andric             .addReg(In, 0, InSubreg);
2137bdd1243dSDimitry Andric       } else {
2138bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(AVR::ADCRdRr), Out)
2139bdd1243dSDimitry Andric             .addReg(In, 0, InSubreg)
2140bdd1243dSDimitry Andric             .addReg(In, 0, InSubreg);
2141bdd1243dSDimitry Andric       }
2142bdd1243dSDimitry Andric       Regs[I] = std::pair(Out, 0);
2143bdd1243dSDimitry Andric     }
2144bdd1243dSDimitry Andric     ShiftAmt--;
2145bdd1243dSDimitry Andric   }
2146bdd1243dSDimitry Andric   while (!ShiftLeft && ShiftAmt) {
2147bdd1243dSDimitry Andric     // Shift one to the right.
2148bdd1243dSDimitry Andric     for (size_t I = 0; I < Regs.size(); I++) {
2149bdd1243dSDimitry Andric       Register Out = MRI.createVirtualRegister(&AVR::GPR8RegClass);
2150bdd1243dSDimitry Andric       Register In = Regs[I].first;
2151bdd1243dSDimitry Andric       Register InSubreg = Regs[I].second;
2152bdd1243dSDimitry Andric       if (I == 0) {
2153bdd1243dSDimitry Andric         unsigned Opc = ArithmeticShift ? AVR::ASRRd : AVR::LSRRd;
2154bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(Opc), Out).addReg(In, 0, InSubreg);
2155bdd1243dSDimitry Andric       } else {
2156bdd1243dSDimitry Andric         BuildMI(*BB, MI, dl, TII.get(AVR::RORRd), Out).addReg(In, 0, InSubreg);
2157bdd1243dSDimitry Andric       }
2158bdd1243dSDimitry Andric       Regs[I] = std::pair(Out, 0);
2159bdd1243dSDimitry Andric     }
2160bdd1243dSDimitry Andric     ShiftAmt--;
2161bdd1243dSDimitry Andric   }
2162bdd1243dSDimitry Andric 
2163bdd1243dSDimitry Andric   if (ShiftAmt != 0) {
2164bdd1243dSDimitry Andric     llvm_unreachable("don't know how to shift!"); // sanity check
2165bdd1243dSDimitry Andric   }
2166bdd1243dSDimitry Andric }
2167bdd1243dSDimitry Andric 
2168bdd1243dSDimitry Andric // Do a wide (32-bit) shift.
2169bdd1243dSDimitry Andric MachineBasicBlock *
2170bdd1243dSDimitry Andric AVRTargetLowering::insertWideShift(MachineInstr &MI,
2171bdd1243dSDimitry Andric                                    MachineBasicBlock *BB) const {
2172bdd1243dSDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
2173bdd1243dSDimitry Andric   const DebugLoc &dl = MI.getDebugLoc();
2174bdd1243dSDimitry Andric 
2175bdd1243dSDimitry Andric   // How much to shift to the right (meaning: a negative number indicates a left
2176bdd1243dSDimitry Andric   // shift).
2177bdd1243dSDimitry Andric   int64_t ShiftAmt = MI.getOperand(4).getImm();
2178bdd1243dSDimitry Andric   ISD::NodeType Opc;
2179bdd1243dSDimitry Andric   switch (MI.getOpcode()) {
2180bdd1243dSDimitry Andric   case AVR::Lsl32:
2181bdd1243dSDimitry Andric     Opc = ISD::SHL;
2182bdd1243dSDimitry Andric     break;
2183bdd1243dSDimitry Andric   case AVR::Lsr32:
2184bdd1243dSDimitry Andric     Opc = ISD::SRL;
2185bdd1243dSDimitry Andric     break;
2186bdd1243dSDimitry Andric   case AVR::Asr32:
2187bdd1243dSDimitry Andric     Opc = ISD::SRA;
2188bdd1243dSDimitry Andric     break;
2189bdd1243dSDimitry Andric   }
2190bdd1243dSDimitry Andric 
2191bdd1243dSDimitry Andric   // Read the input registers, with the most significant register at index 0.
2192bdd1243dSDimitry Andric   std::array<std::pair<Register, int>, 4> Registers = {
2193bdd1243dSDimitry Andric       std::pair(MI.getOperand(3).getReg(), AVR::sub_hi),
2194bdd1243dSDimitry Andric       std::pair(MI.getOperand(3).getReg(), AVR::sub_lo),
2195bdd1243dSDimitry Andric       std::pair(MI.getOperand(2).getReg(), AVR::sub_hi),
2196bdd1243dSDimitry Andric       std::pair(MI.getOperand(2).getReg(), AVR::sub_lo),
2197bdd1243dSDimitry Andric   };
2198bdd1243dSDimitry Andric 
2199bdd1243dSDimitry Andric   // Do the shift. The registers are modified in-place.
2200bdd1243dSDimitry Andric   insertMultibyteShift(MI, BB, Registers, Opc, ShiftAmt);
2201bdd1243dSDimitry Andric 
2202bdd1243dSDimitry Andric   // Combine the 8-bit registers into 16-bit register pairs.
2203bdd1243dSDimitry Andric   // This done either from LSB to MSB or from MSB to LSB, depending on the
2204bdd1243dSDimitry Andric   // shift. It's an optimization so that the register allocator will use the
2205bdd1243dSDimitry Andric   // fewest movs possible (which order we use isn't a correctness issue, just an
2206bdd1243dSDimitry Andric   // optimization issue).
2207bdd1243dSDimitry Andric   //   - lsl prefers starting from the most significant byte (2nd case).
2208bdd1243dSDimitry Andric   //   - lshr prefers starting from the least significant byte (1st case).
2209bdd1243dSDimitry Andric   //   - for ashr it depends on the number of shifted bytes.
2210bdd1243dSDimitry Andric   // Some shift operations still don't get the most optimal mov sequences even
2211bdd1243dSDimitry Andric   // with this distinction. TODO: figure out why and try to fix it (but we're
2212bdd1243dSDimitry Andric   // already equal to or faster than avr-gcc in all cases except ashr 8).
2213bdd1243dSDimitry Andric   if (Opc != ISD::SHL &&
2214bdd1243dSDimitry Andric       (Opc != ISD::SRA || (ShiftAmt < 16 || ShiftAmt >= 22))) {
2215bdd1243dSDimitry Andric     // Use the resulting registers starting with the least significant byte.
2216bdd1243dSDimitry Andric     BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(0).getReg())
2217bdd1243dSDimitry Andric         .addReg(Registers[3].first, 0, Registers[3].second)
2218bdd1243dSDimitry Andric         .addImm(AVR::sub_lo)
2219bdd1243dSDimitry Andric         .addReg(Registers[2].first, 0, Registers[2].second)
2220bdd1243dSDimitry Andric         .addImm(AVR::sub_hi);
2221bdd1243dSDimitry Andric     BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(1).getReg())
2222bdd1243dSDimitry Andric         .addReg(Registers[1].first, 0, Registers[1].second)
2223bdd1243dSDimitry Andric         .addImm(AVR::sub_lo)
2224bdd1243dSDimitry Andric         .addReg(Registers[0].first, 0, Registers[0].second)
2225bdd1243dSDimitry Andric         .addImm(AVR::sub_hi);
2226bdd1243dSDimitry Andric   } else {
2227bdd1243dSDimitry Andric     // Use the resulting registers starting with the most significant byte.
2228bdd1243dSDimitry Andric     BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(1).getReg())
2229bdd1243dSDimitry Andric         .addReg(Registers[0].first, 0, Registers[0].second)
2230bdd1243dSDimitry Andric         .addImm(AVR::sub_hi)
2231bdd1243dSDimitry Andric         .addReg(Registers[1].first, 0, Registers[1].second)
2232bdd1243dSDimitry Andric         .addImm(AVR::sub_lo);
2233bdd1243dSDimitry Andric     BuildMI(*BB, MI, dl, TII.get(AVR::REG_SEQUENCE), MI.getOperand(0).getReg())
2234bdd1243dSDimitry Andric         .addReg(Registers[2].first, 0, Registers[2].second)
2235bdd1243dSDimitry Andric         .addImm(AVR::sub_hi)
2236bdd1243dSDimitry Andric         .addReg(Registers[3].first, 0, Registers[3].second)
2237bdd1243dSDimitry Andric         .addImm(AVR::sub_lo);
2238bdd1243dSDimitry Andric   }
2239bdd1243dSDimitry Andric 
2240bdd1243dSDimitry Andric   // Remove the pseudo instruction.
2241bdd1243dSDimitry Andric   MI.eraseFromParent();
2242bdd1243dSDimitry Andric   return BB;
2243bdd1243dSDimitry Andric }
2244bdd1243dSDimitry Andric 
22450b57cec5SDimitry Andric static bool isCopyMulResult(MachineBasicBlock::iterator const &I) {
22460b57cec5SDimitry Andric   if (I->getOpcode() == AVR::COPY) {
22478bcb0991SDimitry Andric     Register SrcReg = I->getOperand(1).getReg();
22480b57cec5SDimitry Andric     return (SrcReg == AVR::R0 || SrcReg == AVR::R1);
22490b57cec5SDimitry Andric   }
22500b57cec5SDimitry Andric 
22510b57cec5SDimitry Andric   return false;
22520b57cec5SDimitry Andric }
22530b57cec5SDimitry Andric 
22540b57cec5SDimitry Andric // The mul instructions wreak havock on our zero_reg R1. We need to clear it
22550b57cec5SDimitry Andric // after the result has been evacuated. This is probably not the best way to do
22560b57cec5SDimitry Andric // it, but it works for now.
22570b57cec5SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertMul(MachineInstr &MI,
22580b57cec5SDimitry Andric                                                 MachineBasicBlock *BB) const {
22590b57cec5SDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
22600b57cec5SDimitry Andric   MachineBasicBlock::iterator I(MI);
22610b57cec5SDimitry Andric   ++I; // in any case insert *after* the mul instruction
22620b57cec5SDimitry Andric   if (isCopyMulResult(I))
22630b57cec5SDimitry Andric     ++I;
22640b57cec5SDimitry Andric   if (isCopyMulResult(I))
22650b57cec5SDimitry Andric     ++I;
22660b57cec5SDimitry Andric   BuildMI(*BB, I, MI.getDebugLoc(), TII.get(AVR::EORRdRr), AVR::R1)
22670b57cec5SDimitry Andric       .addReg(AVR::R1)
22680b57cec5SDimitry Andric       .addReg(AVR::R1);
22690b57cec5SDimitry Andric   return BB;
22700b57cec5SDimitry Andric }
22710b57cec5SDimitry Andric 
2272bdd1243dSDimitry Andric // Insert a read from the zero register.
227304eeddc0SDimitry Andric MachineBasicBlock *
2274bdd1243dSDimitry Andric AVRTargetLowering::insertCopyZero(MachineInstr &MI,
2275bdd1243dSDimitry Andric                                   MachineBasicBlock *BB) const {
227604eeddc0SDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
227704eeddc0SDimitry Andric   MachineBasicBlock::iterator I(MI);
227804eeddc0SDimitry Andric   BuildMI(*BB, I, MI.getDebugLoc(), TII.get(AVR::COPY))
227904eeddc0SDimitry Andric       .add(MI.getOperand(0))
2280bdd1243dSDimitry Andric       .addReg(Subtarget.getZeroRegister());
228104eeddc0SDimitry Andric   MI.eraseFromParent();
228204eeddc0SDimitry Andric   return BB;
228304eeddc0SDimitry Andric }
228404eeddc0SDimitry Andric 
228581ad6265SDimitry Andric // Lower atomicrmw operation to disable interrupts, do operation, and restore
228681ad6265SDimitry Andric // interrupts. This works because all AVR microcontrollers are single core.
228781ad6265SDimitry Andric MachineBasicBlock *AVRTargetLowering::insertAtomicArithmeticOp(
228881ad6265SDimitry Andric     MachineInstr &MI, MachineBasicBlock *BB, unsigned Opcode, int Width) const {
228981ad6265SDimitry Andric   MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();
229081ad6265SDimitry Andric   const TargetInstrInfo &TII = *Subtarget.getInstrInfo();
229181ad6265SDimitry Andric   MachineBasicBlock::iterator I(MI);
229281ad6265SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
229381ad6265SDimitry Andric 
229481ad6265SDimitry Andric   // Example instruction sequence, for an atomic 8-bit add:
229581ad6265SDimitry Andric   //   ldi r25, 5
229681ad6265SDimitry Andric   //   in r0, SREG
229781ad6265SDimitry Andric   //   cli
229881ad6265SDimitry Andric   //   ld r24, X
229981ad6265SDimitry Andric   //   add r25, r24
230081ad6265SDimitry Andric   //   st X, r25
230181ad6265SDimitry Andric   //   out SREG, r0
230281ad6265SDimitry Andric 
230381ad6265SDimitry Andric   const TargetRegisterClass *RC =
230481ad6265SDimitry Andric       (Width == 8) ? &AVR::GPR8RegClass : &AVR::DREGSRegClass;
230581ad6265SDimitry Andric   unsigned LoadOpcode = (Width == 8) ? AVR::LDRdPtr : AVR::LDWRdPtr;
230681ad6265SDimitry Andric   unsigned StoreOpcode = (Width == 8) ? AVR::STPtrRr : AVR::STWPtrRr;
230781ad6265SDimitry Andric 
230881ad6265SDimitry Andric   // Disable interrupts.
2309bdd1243dSDimitry Andric   BuildMI(*BB, I, dl, TII.get(AVR::INRdA), Subtarget.getTmpRegister())
231081ad6265SDimitry Andric       .addImm(Subtarget.getIORegSREG());
231181ad6265SDimitry Andric   BuildMI(*BB, I, dl, TII.get(AVR::BCLRs)).addImm(7);
231281ad6265SDimitry Andric 
231381ad6265SDimitry Andric   // Load the original value.
231481ad6265SDimitry Andric   BuildMI(*BB, I, dl, TII.get(LoadOpcode), MI.getOperand(0).getReg())
231581ad6265SDimitry Andric       .add(MI.getOperand(1));
231681ad6265SDimitry Andric 
231781ad6265SDimitry Andric   // Do the arithmetic operation.
231881ad6265SDimitry Andric   Register Result = MRI.createVirtualRegister(RC);
231981ad6265SDimitry Andric   BuildMI(*BB, I, dl, TII.get(Opcode), Result)
232081ad6265SDimitry Andric       .addReg(MI.getOperand(0).getReg())
232181ad6265SDimitry Andric       .add(MI.getOperand(2));
232281ad6265SDimitry Andric 
232381ad6265SDimitry Andric   // Store the result.
232481ad6265SDimitry Andric   BuildMI(*BB, I, dl, TII.get(StoreOpcode))
232581ad6265SDimitry Andric       .add(MI.getOperand(1))
232681ad6265SDimitry Andric       .addReg(Result);
232781ad6265SDimitry Andric 
232881ad6265SDimitry Andric   // Restore interrupts.
232981ad6265SDimitry Andric   BuildMI(*BB, I, dl, TII.get(AVR::OUTARr))
233081ad6265SDimitry Andric       .addImm(Subtarget.getIORegSREG())
2331bdd1243dSDimitry Andric       .addReg(Subtarget.getTmpRegister());
233281ad6265SDimitry Andric 
233381ad6265SDimitry Andric   // Remove the pseudo instruction.
233481ad6265SDimitry Andric   MI.eraseFromParent();
233581ad6265SDimitry Andric   return BB;
233681ad6265SDimitry Andric }
233781ad6265SDimitry Andric 
23380b57cec5SDimitry Andric MachineBasicBlock *
23390b57cec5SDimitry Andric AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
23400b57cec5SDimitry Andric                                                MachineBasicBlock *MBB) const {
23410b57cec5SDimitry Andric   int Opc = MI.getOpcode();
234206c3fb27SDimitry Andric   const AVRSubtarget &STI = MBB->getParent()->getSubtarget<AVRSubtarget>();
23430b57cec5SDimitry Andric 
23440b57cec5SDimitry Andric   // Pseudo shift instructions with a non constant shift amount are expanded
23450b57cec5SDimitry Andric   // into a loop.
23460b57cec5SDimitry Andric   switch (Opc) {
23470b57cec5SDimitry Andric   case AVR::Lsl8:
23480b57cec5SDimitry Andric   case AVR::Lsl16:
23490b57cec5SDimitry Andric   case AVR::Lsr8:
23500b57cec5SDimitry Andric   case AVR::Lsr16:
23510b57cec5SDimitry Andric   case AVR::Rol8:
23520b57cec5SDimitry Andric   case AVR::Rol16:
23530b57cec5SDimitry Andric   case AVR::Ror8:
23540b57cec5SDimitry Andric   case AVR::Ror16:
23550b57cec5SDimitry Andric   case AVR::Asr8:
23560b57cec5SDimitry Andric   case AVR::Asr16:
235706c3fb27SDimitry Andric     return insertShift(MI, MBB, STI.hasTinyEncoding());
2358bdd1243dSDimitry Andric   case AVR::Lsl32:
2359bdd1243dSDimitry Andric   case AVR::Lsr32:
2360bdd1243dSDimitry Andric   case AVR::Asr32:
2361bdd1243dSDimitry Andric     return insertWideShift(MI, MBB);
23620b57cec5SDimitry Andric   case AVR::MULRdRr:
23630b57cec5SDimitry Andric   case AVR::MULSRdRr:
23640b57cec5SDimitry Andric     return insertMul(MI, MBB);
2365bdd1243dSDimitry Andric   case AVR::CopyZero:
2366bdd1243dSDimitry Andric     return insertCopyZero(MI, MBB);
236781ad6265SDimitry Andric   case AVR::AtomicLoadAdd8:
236881ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ADDRdRr, 8);
236981ad6265SDimitry Andric   case AVR::AtomicLoadAdd16:
237081ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ADDWRdRr, 16);
237181ad6265SDimitry Andric   case AVR::AtomicLoadSub8:
237281ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::SUBRdRr, 8);
237381ad6265SDimitry Andric   case AVR::AtomicLoadSub16:
237481ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::SUBWRdRr, 16);
237581ad6265SDimitry Andric   case AVR::AtomicLoadAnd8:
237681ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ANDRdRr, 8);
237781ad6265SDimitry Andric   case AVR::AtomicLoadAnd16:
237881ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ANDWRdRr, 16);
237981ad6265SDimitry Andric   case AVR::AtomicLoadOr8:
238081ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ORRdRr, 8);
238181ad6265SDimitry Andric   case AVR::AtomicLoadOr16:
238281ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::ORWRdRr, 16);
238381ad6265SDimitry Andric   case AVR::AtomicLoadXor8:
238481ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::EORRdRr, 8);
238581ad6265SDimitry Andric   case AVR::AtomicLoadXor16:
238681ad6265SDimitry Andric     return insertAtomicArithmeticOp(MI, MBB, AVR::EORWRdRr, 16);
23870b57cec5SDimitry Andric   }
23880b57cec5SDimitry Andric 
23890b57cec5SDimitry Andric   assert((Opc == AVR::Select16 || Opc == AVR::Select8) &&
23900b57cec5SDimitry Andric          "Unexpected instr type to insert");
23910b57cec5SDimitry Andric 
23920b57cec5SDimitry Andric   const AVRInstrInfo &TII = (const AVRInstrInfo &)*MI.getParent()
23930b57cec5SDimitry Andric                                 ->getParent()
23940b57cec5SDimitry Andric                                 ->getSubtarget()
23950b57cec5SDimitry Andric                                 .getInstrInfo();
23960b57cec5SDimitry Andric   DebugLoc dl = MI.getDebugLoc();
23970b57cec5SDimitry Andric 
23980b57cec5SDimitry Andric   // To "insert" a SELECT instruction, we insert the diamond
23990b57cec5SDimitry Andric   // control-flow pattern. The incoming instruction knows the
24000b57cec5SDimitry Andric   // destination vreg to set, the condition code register to branch
24010b57cec5SDimitry Andric   // on, the true/false values to select between, and a branch opcode
24020b57cec5SDimitry Andric   // to use.
24030b57cec5SDimitry Andric 
24040b57cec5SDimitry Andric   MachineFunction *MF = MBB->getParent();
24050b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = MBB->getBasicBlock();
24060b57cec5SDimitry Andric   MachineBasicBlock *FallThrough = MBB->getFallThrough();
24070b57cec5SDimitry Andric 
24080b57cec5SDimitry Andric   // If the current basic block falls through to another basic block,
24090b57cec5SDimitry Andric   // we must insert an unconditional branch to the fallthrough destination
24100b57cec5SDimitry Andric   // if we are to insert basic blocks at the prior fallthrough point.
24110b57cec5SDimitry Andric   if (FallThrough != nullptr) {
24120b57cec5SDimitry Andric     BuildMI(MBB, dl, TII.get(AVR::RJMPk)).addMBB(FallThrough);
24130b57cec5SDimitry Andric   }
24140b57cec5SDimitry Andric 
24150b57cec5SDimitry Andric   MachineBasicBlock *trueMBB = MF->CreateMachineBasicBlock(LLVM_BB);
24160b57cec5SDimitry Andric   MachineBasicBlock *falseMBB = MF->CreateMachineBasicBlock(LLVM_BB);
24170b57cec5SDimitry Andric 
24180b57cec5SDimitry Andric   MachineFunction::iterator I;
2419349cc55cSDimitry Andric   for (I = MF->begin(); I != MF->end() && &(*I) != MBB; ++I)
2420349cc55cSDimitry Andric     ;
2421349cc55cSDimitry Andric   if (I != MF->end())
2422349cc55cSDimitry Andric     ++I;
24230b57cec5SDimitry Andric   MF->insert(I, trueMBB);
24240b57cec5SDimitry Andric   MF->insert(I, falseMBB);
24250b57cec5SDimitry Andric 
24265f757f3fSDimitry Andric   // Set the call frame size on entry to the new basic blocks.
24275f757f3fSDimitry Andric   unsigned CallFrameSize = TII.getCallFrameSizeAt(MI);
24285f757f3fSDimitry Andric   trueMBB->setCallFrameSize(CallFrameSize);
24295f757f3fSDimitry Andric   falseMBB->setCallFrameSize(CallFrameSize);
24305f757f3fSDimitry Andric 
24310b57cec5SDimitry Andric   // Transfer remaining instructions and all successors of the current
24320b57cec5SDimitry Andric   // block to the block which will contain the Phi node for the
24330b57cec5SDimitry Andric   // select.
24340b57cec5SDimitry Andric   trueMBB->splice(trueMBB->begin(), MBB,
24350b57cec5SDimitry Andric                   std::next(MachineBasicBlock::iterator(MI)), MBB->end());
24360b57cec5SDimitry Andric   trueMBB->transferSuccessorsAndUpdatePHIs(MBB);
24370b57cec5SDimitry Andric 
24380b57cec5SDimitry Andric   AVRCC::CondCodes CC = (AVRCC::CondCodes)MI.getOperand(3).getImm();
24390b57cec5SDimitry Andric   BuildMI(MBB, dl, TII.getBrCond(CC)).addMBB(trueMBB);
24400b57cec5SDimitry Andric   BuildMI(MBB, dl, TII.get(AVR::RJMPk)).addMBB(falseMBB);
24410b57cec5SDimitry Andric   MBB->addSuccessor(falseMBB);
24420b57cec5SDimitry Andric   MBB->addSuccessor(trueMBB);
24430b57cec5SDimitry Andric 
24440b57cec5SDimitry Andric   // Unconditionally flow back to the true block
24450b57cec5SDimitry Andric   BuildMI(falseMBB, dl, TII.get(AVR::RJMPk)).addMBB(trueMBB);
24460b57cec5SDimitry Andric   falseMBB->addSuccessor(trueMBB);
24470b57cec5SDimitry Andric 
24480b57cec5SDimitry Andric   // Set up the Phi node to determine where we came from
2449349cc55cSDimitry Andric   BuildMI(*trueMBB, trueMBB->begin(), dl, TII.get(AVR::PHI),
2450349cc55cSDimitry Andric           MI.getOperand(0).getReg())
24510b57cec5SDimitry Andric       .addReg(MI.getOperand(1).getReg())
24520b57cec5SDimitry Andric       .addMBB(MBB)
24530b57cec5SDimitry Andric       .addReg(MI.getOperand(2).getReg())
24540b57cec5SDimitry Andric       .addMBB(falseMBB);
24550b57cec5SDimitry Andric 
24560b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
24570b57cec5SDimitry Andric   return trueMBB;
24580b57cec5SDimitry Andric }
24590b57cec5SDimitry Andric 
24600b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
24610b57cec5SDimitry Andric //  Inline Asm Support
24620b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric AVRTargetLowering::ConstraintType
24650b57cec5SDimitry Andric AVRTargetLowering::getConstraintType(StringRef Constraint) const {
24660b57cec5SDimitry Andric   if (Constraint.size() == 1) {
24670b57cec5SDimitry Andric     // See http://www.nongnu.org/avr-libc/user-manual/inline_asm.html
24680b57cec5SDimitry Andric     switch (Constraint[0]) {
24690b57cec5SDimitry Andric     default:
24700b57cec5SDimitry Andric       break;
24710b57cec5SDimitry Andric     case 'a': // Simple upper registers
24720b57cec5SDimitry Andric     case 'b': // Base pointer registers pairs
24730b57cec5SDimitry Andric     case 'd': // Upper register
24740b57cec5SDimitry Andric     case 'l': // Lower registers
24750b57cec5SDimitry Andric     case 'e': // Pointer register pairs
24760b57cec5SDimitry Andric     case 'q': // Stack pointer register
24770b57cec5SDimitry Andric     case 'r': // Any register
24780b57cec5SDimitry Andric     case 'w': // Special upper register pairs
24790b57cec5SDimitry Andric       return C_RegisterClass;
24800b57cec5SDimitry Andric     case 't': // Temporary register
2481349cc55cSDimitry Andric     case 'x':
2482349cc55cSDimitry Andric     case 'X': // Pointer register pair X
2483349cc55cSDimitry Andric     case 'y':
2484349cc55cSDimitry Andric     case 'Y': // Pointer register pair Y
2485349cc55cSDimitry Andric     case 'z':
2486349cc55cSDimitry Andric     case 'Z': // Pointer register pair Z
24870b57cec5SDimitry Andric       return C_Register;
24880b57cec5SDimitry Andric     case 'Q': // A memory address based on Y or Z pointer with displacement.
24890b57cec5SDimitry Andric       return C_Memory;
24900b57cec5SDimitry Andric     case 'G': // Floating point constant
24910b57cec5SDimitry Andric     case 'I': // 6-bit positive integer constant
24920b57cec5SDimitry Andric     case 'J': // 6-bit negative integer constant
24930b57cec5SDimitry Andric     case 'K': // Integer constant (Range: 2)
24940b57cec5SDimitry Andric     case 'L': // Integer constant (Range: 0)
24950b57cec5SDimitry Andric     case 'M': // 8-bit integer constant
24960b57cec5SDimitry Andric     case 'N': // Integer constant (Range: -1)
24970b57cec5SDimitry Andric     case 'O': // Integer constant (Range: 8, 16, 24)
24980b57cec5SDimitry Andric     case 'P': // Integer constant (Range: 1)
24990b57cec5SDimitry Andric     case 'R': // Integer constant (Range: -6 to 5)x
25000b57cec5SDimitry Andric       return C_Immediate;
25010b57cec5SDimitry Andric     }
25020b57cec5SDimitry Andric   }
25030b57cec5SDimitry Andric 
25040b57cec5SDimitry Andric   return TargetLowering::getConstraintType(Constraint);
25050b57cec5SDimitry Andric }
25060b57cec5SDimitry Andric 
25075f757f3fSDimitry Andric InlineAsm::ConstraintCode
25080b57cec5SDimitry Andric AVRTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const {
25090b57cec5SDimitry Andric   // Not sure if this is actually the right thing to do, but we got to do
25100b57cec5SDimitry Andric   // *something* [agnat]
25110b57cec5SDimitry Andric   switch (ConstraintCode[0]) {
25120b57cec5SDimitry Andric   case 'Q':
25135f757f3fSDimitry Andric     return InlineAsm::ConstraintCode::Q;
25140b57cec5SDimitry Andric   }
25150b57cec5SDimitry Andric   return TargetLowering::getInlineAsmMemConstraint(ConstraintCode);
25160b57cec5SDimitry Andric }
25170b57cec5SDimitry Andric 
25180b57cec5SDimitry Andric AVRTargetLowering::ConstraintWeight
25190b57cec5SDimitry Andric AVRTargetLowering::getSingleConstraintMatchWeight(
25200b57cec5SDimitry Andric     AsmOperandInfo &info, const char *constraint) const {
25210b57cec5SDimitry Andric   ConstraintWeight weight = CW_Invalid;
25220b57cec5SDimitry Andric   Value *CallOperandVal = info.CallOperandVal;
25230b57cec5SDimitry Andric 
25240b57cec5SDimitry Andric   // If we don't have a value, we can't do a match,
25250b57cec5SDimitry Andric   // but allow it at the lowest weight.
25260b57cec5SDimitry Andric   // (this behaviour has been copied from the ARM backend)
25270b57cec5SDimitry Andric   if (!CallOperandVal) {
25280b57cec5SDimitry Andric     return CW_Default;
25290b57cec5SDimitry Andric   }
25300b57cec5SDimitry Andric 
25310b57cec5SDimitry Andric   // Look at the constraint type.
25320b57cec5SDimitry Andric   switch (*constraint) {
25330b57cec5SDimitry Andric   default:
25340b57cec5SDimitry Andric     weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint);
25350b57cec5SDimitry Andric     break;
25360b57cec5SDimitry Andric   case 'd':
25370b57cec5SDimitry Andric   case 'r':
25380b57cec5SDimitry Andric   case 'l':
25390b57cec5SDimitry Andric     weight = CW_Register;
25400b57cec5SDimitry Andric     break;
25410b57cec5SDimitry Andric   case 'a':
25420b57cec5SDimitry Andric   case 'b':
25430b57cec5SDimitry Andric   case 'e':
25440b57cec5SDimitry Andric   case 'q':
25450b57cec5SDimitry Andric   case 't':
25460b57cec5SDimitry Andric   case 'w':
2547349cc55cSDimitry Andric   case 'x':
2548349cc55cSDimitry Andric   case 'X':
2549349cc55cSDimitry Andric   case 'y':
2550349cc55cSDimitry Andric   case 'Y':
2551349cc55cSDimitry Andric   case 'z':
2552349cc55cSDimitry Andric   case 'Z':
25530b57cec5SDimitry Andric     weight = CW_SpecificReg;
25540b57cec5SDimitry Andric     break;
25550b57cec5SDimitry Andric   case 'G':
25560b57cec5SDimitry Andric     if (const ConstantFP *C = dyn_cast<ConstantFP>(CallOperandVal)) {
25570b57cec5SDimitry Andric       if (C->isZero()) {
25580b57cec5SDimitry Andric         weight = CW_Constant;
25590b57cec5SDimitry Andric       }
25600b57cec5SDimitry Andric     }
25610b57cec5SDimitry Andric     break;
25620b57cec5SDimitry Andric   case 'I':
25630b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25640b57cec5SDimitry Andric       if (isUInt<6>(C->getZExtValue())) {
25650b57cec5SDimitry Andric         weight = CW_Constant;
25660b57cec5SDimitry Andric       }
25670b57cec5SDimitry Andric     }
25680b57cec5SDimitry Andric     break;
25690b57cec5SDimitry Andric   case 'J':
25700b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25710b57cec5SDimitry Andric       if ((C->getSExtValue() >= -63) && (C->getSExtValue() <= 0)) {
25720b57cec5SDimitry Andric         weight = CW_Constant;
25730b57cec5SDimitry Andric       }
25740b57cec5SDimitry Andric     }
25750b57cec5SDimitry Andric     break;
25760b57cec5SDimitry Andric   case 'K':
25770b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25780b57cec5SDimitry Andric       if (C->getZExtValue() == 2) {
25790b57cec5SDimitry Andric         weight = CW_Constant;
25800b57cec5SDimitry Andric       }
25810b57cec5SDimitry Andric     }
25820b57cec5SDimitry Andric     break;
25830b57cec5SDimitry Andric   case 'L':
25840b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25850b57cec5SDimitry Andric       if (C->getZExtValue() == 0) {
25860b57cec5SDimitry Andric         weight = CW_Constant;
25870b57cec5SDimitry Andric       }
25880b57cec5SDimitry Andric     }
25890b57cec5SDimitry Andric     break;
25900b57cec5SDimitry Andric   case 'M':
25910b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25920b57cec5SDimitry Andric       if (isUInt<8>(C->getZExtValue())) {
25930b57cec5SDimitry Andric         weight = CW_Constant;
25940b57cec5SDimitry Andric       }
25950b57cec5SDimitry Andric     }
25960b57cec5SDimitry Andric     break;
25970b57cec5SDimitry Andric   case 'N':
25980b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
25990b57cec5SDimitry Andric       if (C->getSExtValue() == -1) {
26000b57cec5SDimitry Andric         weight = CW_Constant;
26010b57cec5SDimitry Andric       }
26020b57cec5SDimitry Andric     }
26030b57cec5SDimitry Andric     break;
26040b57cec5SDimitry Andric   case 'O':
26050b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
26060b57cec5SDimitry Andric       if ((C->getZExtValue() == 8) || (C->getZExtValue() == 16) ||
26070b57cec5SDimitry Andric           (C->getZExtValue() == 24)) {
26080b57cec5SDimitry Andric         weight = CW_Constant;
26090b57cec5SDimitry Andric       }
26100b57cec5SDimitry Andric     }
26110b57cec5SDimitry Andric     break;
26120b57cec5SDimitry Andric   case 'P':
26130b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
26140b57cec5SDimitry Andric       if (C->getZExtValue() == 1) {
26150b57cec5SDimitry Andric         weight = CW_Constant;
26160b57cec5SDimitry Andric       }
26170b57cec5SDimitry Andric     }
26180b57cec5SDimitry Andric     break;
26190b57cec5SDimitry Andric   case 'R':
26200b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) {
26210b57cec5SDimitry Andric       if ((C->getSExtValue() >= -6) && (C->getSExtValue() <= 5)) {
26220b57cec5SDimitry Andric         weight = CW_Constant;
26230b57cec5SDimitry Andric       }
26240b57cec5SDimitry Andric     }
26250b57cec5SDimitry Andric     break;
26260b57cec5SDimitry Andric   case 'Q':
26270b57cec5SDimitry Andric     weight = CW_Memory;
26280b57cec5SDimitry Andric     break;
26290b57cec5SDimitry Andric   }
26300b57cec5SDimitry Andric 
26310b57cec5SDimitry Andric   return weight;
26320b57cec5SDimitry Andric }
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
26350b57cec5SDimitry Andric AVRTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
26360b57cec5SDimitry Andric                                                 StringRef Constraint,
26370b57cec5SDimitry Andric                                                 MVT VT) const {
26380b57cec5SDimitry Andric   if (Constraint.size() == 1) {
26390b57cec5SDimitry Andric     switch (Constraint[0]) {
26400b57cec5SDimitry Andric     case 'a': // Simple upper registers r16..r23.
2641fe6060f1SDimitry Andric       if (VT == MVT::i8)
26420b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::LD8loRegClass);
2643fe6060f1SDimitry Andric       else if (VT == MVT::i16)
2644fe6060f1SDimitry Andric         return std::make_pair(0U, &AVR::DREGSLD8loRegClass);
2645fe6060f1SDimitry Andric       break;
26460b57cec5SDimitry Andric     case 'b': // Base pointer registers: y, z.
2647fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26480b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::PTRDISPREGSRegClass);
2649fe6060f1SDimitry Andric       break;
26500b57cec5SDimitry Andric     case 'd': // Upper registers r16..r31.
2651fe6060f1SDimitry Andric       if (VT == MVT::i8)
26520b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::LD8RegClass);
2653fe6060f1SDimitry Andric       else if (VT == MVT::i16)
2654fe6060f1SDimitry Andric         return std::make_pair(0U, &AVR::DLDREGSRegClass);
2655fe6060f1SDimitry Andric       break;
26560b57cec5SDimitry Andric     case 'l': // Lower registers r0..r15.
2657fe6060f1SDimitry Andric       if (VT == MVT::i8)
26580b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::GPR8loRegClass);
2659fe6060f1SDimitry Andric       else if (VT == MVT::i16)
2660fe6060f1SDimitry Andric         return std::make_pair(0U, &AVR::DREGSloRegClass);
2661fe6060f1SDimitry Andric       break;
26620b57cec5SDimitry Andric     case 'e': // Pointer register pairs: x, y, z.
2663fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26640b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::PTRREGSRegClass);
2665fe6060f1SDimitry Andric       break;
26660b57cec5SDimitry Andric     case 'q': // Stack pointer register: SPH:SPL.
26670b57cec5SDimitry Andric       return std::make_pair(0U, &AVR::GPRSPRegClass);
26680b57cec5SDimitry Andric     case 'r': // Any register: r0..r31.
26690b57cec5SDimitry Andric       if (VT == MVT::i8)
26700b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::GPR8RegClass);
2671fe6060f1SDimitry Andric       else if (VT == MVT::i16)
26720b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::DREGSRegClass);
2673fe6060f1SDimitry Andric       break;
26740b57cec5SDimitry Andric     case 't': // Temporary register: r0.
2675fe6060f1SDimitry Andric       if (VT == MVT::i8)
2676bdd1243dSDimitry Andric         return std::make_pair(unsigned(Subtarget.getTmpRegister()),
2677bdd1243dSDimitry Andric                               &AVR::GPR8RegClass);
2678fe6060f1SDimitry Andric       break;
26790b57cec5SDimitry Andric     case 'w': // Special upper register pairs: r24, r26, r28, r30.
2680fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26810b57cec5SDimitry Andric         return std::make_pair(0U, &AVR::IWREGSRegClass);
2682fe6060f1SDimitry Andric       break;
26830b57cec5SDimitry Andric     case 'x': // Pointer register pair X: r27:r26.
26840b57cec5SDimitry Andric     case 'X':
2685fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26860b57cec5SDimitry Andric         return std::make_pair(unsigned(AVR::R27R26), &AVR::PTRREGSRegClass);
2687fe6060f1SDimitry Andric       break;
26880b57cec5SDimitry Andric     case 'y': // Pointer register pair Y: r29:r28.
26890b57cec5SDimitry Andric     case 'Y':
2690fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26910b57cec5SDimitry Andric         return std::make_pair(unsigned(AVR::R29R28), &AVR::PTRREGSRegClass);
2692fe6060f1SDimitry Andric       break;
26930b57cec5SDimitry Andric     case 'z': // Pointer register pair Z: r31:r30.
26940b57cec5SDimitry Andric     case 'Z':
2695fe6060f1SDimitry Andric       if (VT == MVT::i8 || VT == MVT::i16)
26960b57cec5SDimitry Andric         return std::make_pair(unsigned(AVR::R31R30), &AVR::PTRREGSRegClass);
2697fe6060f1SDimitry Andric       break;
26980b57cec5SDimitry Andric     default:
26990b57cec5SDimitry Andric       break;
27000b57cec5SDimitry Andric     }
27010b57cec5SDimitry Andric   }
27020b57cec5SDimitry Andric 
27030b57cec5SDimitry Andric   return TargetLowering::getRegForInlineAsmConstraint(
27040b57cec5SDimitry Andric       Subtarget.getRegisterInfo(), Constraint, VT);
27050b57cec5SDimitry Andric }
27060b57cec5SDimitry Andric 
27070b57cec5SDimitry Andric void AVRTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
27085f757f3fSDimitry Andric                                                      StringRef Constraint,
27090b57cec5SDimitry Andric                                                      std::vector<SDValue> &Ops,
27100b57cec5SDimitry Andric                                                      SelectionDAG &DAG) const {
271104eeddc0SDimitry Andric   SDValue Result;
27120b57cec5SDimitry Andric   SDLoc DL(Op);
27130b57cec5SDimitry Andric   EVT Ty = Op.getValueType();
27140b57cec5SDimitry Andric 
27150b57cec5SDimitry Andric   // Currently only support length 1 constraints.
27165f757f3fSDimitry Andric   if (Constraint.size() != 1) {
27170b57cec5SDimitry Andric     return;
27180b57cec5SDimitry Andric   }
27190b57cec5SDimitry Andric 
27200b57cec5SDimitry Andric   char ConstraintLetter = Constraint[0];
27210b57cec5SDimitry Andric   switch (ConstraintLetter) {
27220b57cec5SDimitry Andric   default:
27230b57cec5SDimitry Andric     break;
27240b57cec5SDimitry Andric   // Deal with integers first:
27250b57cec5SDimitry Andric   case 'I':
27260b57cec5SDimitry Andric   case 'J':
27270b57cec5SDimitry Andric   case 'K':
27280b57cec5SDimitry Andric   case 'L':
27290b57cec5SDimitry Andric   case 'M':
27300b57cec5SDimitry Andric   case 'N':
27310b57cec5SDimitry Andric   case 'O':
27320b57cec5SDimitry Andric   case 'P':
27330b57cec5SDimitry Andric   case 'R': {
27340b57cec5SDimitry Andric     const ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
27350b57cec5SDimitry Andric     if (!C) {
27360b57cec5SDimitry Andric       return;
27370b57cec5SDimitry Andric     }
27380b57cec5SDimitry Andric 
27390b57cec5SDimitry Andric     int64_t CVal64 = C->getSExtValue();
27400b57cec5SDimitry Andric     uint64_t CUVal64 = C->getZExtValue();
27410b57cec5SDimitry Andric     switch (ConstraintLetter) {
27420b57cec5SDimitry Andric     case 'I': // 0..63
27430b57cec5SDimitry Andric       if (!isUInt<6>(CUVal64))
27440b57cec5SDimitry Andric         return;
27450b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27460b57cec5SDimitry Andric       break;
27470b57cec5SDimitry Andric     case 'J': // -63..0
27480b57cec5SDimitry Andric       if (CVal64 < -63 || CVal64 > 0)
27490b57cec5SDimitry Andric         return;
27500b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CVal64, DL, Ty);
27510b57cec5SDimitry Andric       break;
27520b57cec5SDimitry Andric     case 'K': // 2
27530b57cec5SDimitry Andric       if (CUVal64 != 2)
27540b57cec5SDimitry Andric         return;
27550b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27560b57cec5SDimitry Andric       break;
27570b57cec5SDimitry Andric     case 'L': // 0
27580b57cec5SDimitry Andric       if (CUVal64 != 0)
27590b57cec5SDimitry Andric         return;
27600b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27610b57cec5SDimitry Andric       break;
27620b57cec5SDimitry Andric     case 'M': // 0..255
27630b57cec5SDimitry Andric       if (!isUInt<8>(CUVal64))
27640b57cec5SDimitry Andric         return;
27650b57cec5SDimitry Andric       // i8 type may be printed as a negative number,
27660b57cec5SDimitry Andric       // e.g. 254 would be printed as -2,
27670b57cec5SDimitry Andric       // so we force it to i16 at least.
27680b57cec5SDimitry Andric       if (Ty.getSimpleVT() == MVT::i8) {
27690b57cec5SDimitry Andric         Ty = MVT::i16;
27700b57cec5SDimitry Andric       }
27710b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27720b57cec5SDimitry Andric       break;
27730b57cec5SDimitry Andric     case 'N': // -1
27740b57cec5SDimitry Andric       if (CVal64 != -1)
27750b57cec5SDimitry Andric         return;
27760b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CVal64, DL, Ty);
27770b57cec5SDimitry Andric       break;
27780b57cec5SDimitry Andric     case 'O': // 8, 16, 24
27790b57cec5SDimitry Andric       if (CUVal64 != 8 && CUVal64 != 16 && CUVal64 != 24)
27800b57cec5SDimitry Andric         return;
27810b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27820b57cec5SDimitry Andric       break;
27830b57cec5SDimitry Andric     case 'P': // 1
27840b57cec5SDimitry Andric       if (CUVal64 != 1)
27850b57cec5SDimitry Andric         return;
27860b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CUVal64, DL, Ty);
27870b57cec5SDimitry Andric       break;
27880b57cec5SDimitry Andric     case 'R': // -6..5
27890b57cec5SDimitry Andric       if (CVal64 < -6 || CVal64 > 5)
27900b57cec5SDimitry Andric         return;
27910b57cec5SDimitry Andric       Result = DAG.getTargetConstant(CVal64, DL, Ty);
27920b57cec5SDimitry Andric       break;
27930b57cec5SDimitry Andric     }
27940b57cec5SDimitry Andric 
27950b57cec5SDimitry Andric     break;
27960b57cec5SDimitry Andric   }
27970b57cec5SDimitry Andric   case 'G':
27980b57cec5SDimitry Andric     const ConstantFPSDNode *FC = dyn_cast<ConstantFPSDNode>(Op);
27990b57cec5SDimitry Andric     if (!FC || !FC->isZero())
28000b57cec5SDimitry Andric       return;
28010b57cec5SDimitry Andric     // Soften float to i8 0
28020b57cec5SDimitry Andric     Result = DAG.getTargetConstant(0, DL, MVT::i8);
28030b57cec5SDimitry Andric     break;
28040b57cec5SDimitry Andric   }
28050b57cec5SDimitry Andric 
28060b57cec5SDimitry Andric   if (Result.getNode()) {
28070b57cec5SDimitry Andric     Ops.push_back(Result);
28080b57cec5SDimitry Andric     return;
28090b57cec5SDimitry Andric   }
28100b57cec5SDimitry Andric 
28110b57cec5SDimitry Andric   return TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
28120b57cec5SDimitry Andric }
28130b57cec5SDimitry Andric 
2814480093f4SDimitry Andric Register AVRTargetLowering::getRegisterByName(const char *RegName, LLT VT,
28158bcb0991SDimitry Andric                                               const MachineFunction &MF) const {
28168bcb0991SDimitry Andric   Register Reg;
28170b57cec5SDimitry Andric 
2818480093f4SDimitry Andric   if (VT == LLT::scalar(8)) {
28190b57cec5SDimitry Andric     Reg = StringSwitch<unsigned>(RegName)
2820fe6060f1SDimitry Andric               .Case("r0", AVR::R0)
2821fe6060f1SDimitry Andric               .Case("r1", AVR::R1)
28220b57cec5SDimitry Andric               .Default(0);
28230b57cec5SDimitry Andric   } else {
28240b57cec5SDimitry Andric     Reg = StringSwitch<unsigned>(RegName)
2825fe6060f1SDimitry Andric               .Case("r0", AVR::R1R0)
2826fe6060f1SDimitry Andric               .Case("sp", AVR::SP)
28270b57cec5SDimitry Andric               .Default(0);
28280b57cec5SDimitry Andric   }
28290b57cec5SDimitry Andric 
28300b57cec5SDimitry Andric   if (Reg)
28310b57cec5SDimitry Andric     return Reg;
28320b57cec5SDimitry Andric 
2833fe6060f1SDimitry Andric   report_fatal_error(
2834fe6060f1SDimitry Andric       Twine("Invalid register name \"" + StringRef(RegName) + "\"."));
28350b57cec5SDimitry Andric }
28360b57cec5SDimitry Andric 
28370b57cec5SDimitry Andric } // end of namespace llvm
2838