xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/BPF/BPFISelLowering.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- BPFISelLowering.cpp - BPF 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 BPF uses to lower LLVM code into a
100b57cec5SDimitry Andric // selection DAG.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "BPFISelLowering.h"
150b57cec5SDimitry Andric #include "BPF.h"
160b57cec5SDimitry Andric #include "BPFSubtarget.h"
170b57cec5SDimitry Andric #include "BPFTargetMachine.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/ValueTypes.h"
250b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
260b57cec5SDimitry Andric #include "llvm/IR/DiagnosticPrinter.h"
270b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
280b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
295f757f3fSDimitry Andric #include "llvm/Support/MathExtras.h"
300b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
315f757f3fSDimitry Andric 
320b57cec5SDimitry Andric using namespace llvm;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric #define DEBUG_TYPE "bpf-lower"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric static cl::opt<bool> BPFExpandMemcpyInOrder("bpf-expand-memcpy-in-order",
370b57cec5SDimitry Andric   cl::Hidden, cl::init(false),
380b57cec5SDimitry Andric   cl::desc("Expand memcpy into load/store pairs in order"));
390b57cec5SDimitry Andric 
405f757f3fSDimitry Andric static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg,
415f757f3fSDimitry Andric                  SDValue Val = {}) {
420b57cec5SDimitry Andric   std::string Str;
435f757f3fSDimitry Andric   if (Val) {
440b57cec5SDimitry Andric     raw_string_ostream OS(Str);
450b57cec5SDimitry Andric     Val->print(OS);
465f757f3fSDimitry Andric     OS << ' ';
475f757f3fSDimitry Andric   }
485f757f3fSDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
495f757f3fSDimitry Andric   DAG.getContext()->diagnose(DiagnosticInfoUnsupported(
505f757f3fSDimitry Andric       MF.getFunction(), Twine(Str).concat(Msg), DL.getDebugLoc()));
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
540b57cec5SDimitry Andric                                      const BPFSubtarget &STI)
550b57cec5SDimitry Andric     : TargetLowering(TM) {
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   // Set up the register classes.
580b57cec5SDimitry Andric   addRegisterClass(MVT::i64, &BPF::GPRRegClass);
590b57cec5SDimitry Andric   if (STI.getHasAlu32())
600b57cec5SDimitry Andric     addRegisterClass(MVT::i32, &BPF::GPR32RegClass);
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   // Compute derived properties from the register classes
630b57cec5SDimitry Andric   computeRegisterProperties(STI.getRegisterInfo());
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   setStackPointerRegisterToSaveRestore(BPF::R11);
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   setOperationAction(ISD::BR_CC, MVT::i64, Custom);
680b57cec5SDimitry Andric   setOperationAction(ISD::BR_JT, MVT::Other, Expand);
690b57cec5SDimitry Andric   setOperationAction(ISD::BRIND, MVT::Other, Expand);
700b57cec5SDimitry Andric   setOperationAction(ISD::BRCOND, MVT::Other, Expand);
710b57cec5SDimitry Andric 
72*0fca6ea1SDimitry Andric   setOperationAction({ISD::GlobalAddress, ISD::ConstantPool}, MVT::i64, Custom);
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Custom);
750b57cec5SDimitry Andric   setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
760b57cec5SDimitry Andric   setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
770b57cec5SDimitry Andric 
78fe6060f1SDimitry Andric   // Set unsupported atomic operations as Custom so
79fe6060f1SDimitry Andric   // we can emit better error messages than fatal error
80fe6060f1SDimitry Andric   // from selectiondag.
81fe6060f1SDimitry Andric   for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
82fe6060f1SDimitry Andric     if (VT == MVT::i32) {
83fe6060f1SDimitry Andric       if (STI.getHasAlu32())
84fe6060f1SDimitry Andric         continue;
85fe6060f1SDimitry Andric     } else {
86fe6060f1SDimitry Andric       setOperationAction(ISD::ATOMIC_LOAD_ADD, VT, Custom);
87fe6060f1SDimitry Andric     }
88fe6060f1SDimitry Andric 
89fe6060f1SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_AND, VT, Custom);
90fe6060f1SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_OR, VT, Custom);
91fe6060f1SDimitry Andric     setOperationAction(ISD::ATOMIC_LOAD_XOR, VT, Custom);
92fe6060f1SDimitry Andric     setOperationAction(ISD::ATOMIC_SWAP, VT, Custom);
93fe6060f1SDimitry Andric     setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, VT, Custom);
94fe6060f1SDimitry Andric   }
95fe6060f1SDimitry Andric 
960b57cec5SDimitry Andric   for (auto VT : { MVT::i32, MVT::i64 }) {
970b57cec5SDimitry Andric     if (VT == MVT::i32 && !STI.getHasAlu32())
980b57cec5SDimitry Andric       continue;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric     setOperationAction(ISD::SDIVREM, VT, Expand);
1010b57cec5SDimitry Andric     setOperationAction(ISD::UDIVREM, VT, Expand);
1025f757f3fSDimitry Andric     if (!STI.hasSdivSmod()) {
1035f757f3fSDimitry Andric       setOperationAction(ISD::SDIV, VT, Custom);
1045f757f3fSDimitry Andric       setOperationAction(ISD::SREM, VT, Custom);
1055f757f3fSDimitry Andric     }
1060b57cec5SDimitry Andric     setOperationAction(ISD::MULHU, VT, Expand);
1070b57cec5SDimitry Andric     setOperationAction(ISD::MULHS, VT, Expand);
1080b57cec5SDimitry Andric     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
1090b57cec5SDimitry Andric     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
1100b57cec5SDimitry Andric     setOperationAction(ISD::ROTR, VT, Expand);
1110b57cec5SDimitry Andric     setOperationAction(ISD::ROTL, VT, Expand);
1120b57cec5SDimitry Andric     setOperationAction(ISD::SHL_PARTS, VT, Expand);
1130b57cec5SDimitry Andric     setOperationAction(ISD::SRL_PARTS, VT, Expand);
1140b57cec5SDimitry Andric     setOperationAction(ISD::SRA_PARTS, VT, Expand);
1150b57cec5SDimitry Andric     setOperationAction(ISD::CTPOP, VT, Expand);
116*0fca6ea1SDimitry Andric     setOperationAction(ISD::CTTZ, VT, Expand);
117*0fca6ea1SDimitry Andric     setOperationAction(ISD::CTLZ, VT, Expand);
118*0fca6ea1SDimitry Andric     setOperationAction(ISD::CTTZ_ZERO_UNDEF, VT, Expand);
119*0fca6ea1SDimitry Andric     setOperationAction(ISD::CTLZ_ZERO_UNDEF, VT, Expand);
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric     setOperationAction(ISD::SETCC, VT, Expand);
1220b57cec5SDimitry Andric     setOperationAction(ISD::SELECT, VT, Expand);
1230b57cec5SDimitry Andric     setOperationAction(ISD::SELECT_CC, VT, Custom);
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric   if (STI.getHasAlu32()) {
1270b57cec5SDimitry Andric     setOperationAction(ISD::BSWAP, MVT::i32, Promote);
1280b57cec5SDimitry Andric     setOperationAction(ISD::BR_CC, MVT::i32,
1290b57cec5SDimitry Andric                        STI.getHasJmp32() ? Custom : Promote);
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
1335f757f3fSDimitry Andric   if (!STI.hasMovsx()) {
1340b57cec5SDimitry Andric     setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
1350b57cec5SDimitry Andric     setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
1360b57cec5SDimitry Andric     setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i32, Expand);
1375f757f3fSDimitry Andric   }
1380b57cec5SDimitry Andric 
1390b57cec5SDimitry Andric   // Extended load operations for i1 types must be promoted
1400b57cec5SDimitry Andric   for (MVT VT : MVT::integer_valuetypes()) {
1410b57cec5SDimitry Andric     setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote);
1420b57cec5SDimitry Andric     setLoadExtAction(ISD::ZEXTLOAD, VT, MVT::i1, Promote);
1430b57cec5SDimitry Andric     setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote);
1440b57cec5SDimitry Andric 
1455f757f3fSDimitry Andric     if (!STI.hasLdsx()) {
1460b57cec5SDimitry Andric       setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i8, Expand);
1470b57cec5SDimitry Andric       setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i16, Expand);
1480b57cec5SDimitry Andric       setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i32, Expand);
1490b57cec5SDimitry Andric     }
1505f757f3fSDimitry Andric   }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   setBooleanContents(ZeroOrOneBooleanContent);
1531db9f3b2SDimitry Andric   setMaxAtomicSizeInBitsSupported(64);
1540b57cec5SDimitry Andric 
1558bcb0991SDimitry Andric   // Function alignments
1568bcb0991SDimitry Andric   setMinFunctionAlignment(Align(8));
1578bcb0991SDimitry Andric   setPrefFunctionAlignment(Align(8));
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   if (BPFExpandMemcpyInOrder) {
1600b57cec5SDimitry Andric     // LLVM generic code will try to expand memcpy into load/store pairs at this
1610b57cec5SDimitry Andric     // stage which is before quite a few IR optimization passes, therefore the
1620b57cec5SDimitry Andric     // loads and stores could potentially be moved apart from each other which
1630b57cec5SDimitry Andric     // will cause trouble to memcpy pattern matcher inside kernel eBPF JIT
1640b57cec5SDimitry Andric     // compilers.
1650b57cec5SDimitry Andric     //
1660b57cec5SDimitry Andric     // When -bpf-expand-memcpy-in-order specified, we want to defer the expand
1670b57cec5SDimitry Andric     // of memcpy to later stage in IR optimization pipeline so those load/store
1680b57cec5SDimitry Andric     // pairs won't be touched and could be kept in order. Hence, we set
1690b57cec5SDimitry Andric     // MaxStoresPerMem* to zero to disable the generic getMemcpyLoadsAndStores
1700b57cec5SDimitry Andric     // code path, and ask LLVM to use target expander EmitTargetCodeForMemcpy.
1710b57cec5SDimitry Andric     MaxStoresPerMemset = MaxStoresPerMemsetOptSize = 0;
1720b57cec5SDimitry Andric     MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = 0;
1730b57cec5SDimitry Andric     MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = 0;
17481ad6265SDimitry Andric     MaxLoadsPerMemcmp = 0;
1750b57cec5SDimitry Andric   } else {
1760b57cec5SDimitry Andric     // inline memcpy() for kernel to see explicit copy
1770b57cec5SDimitry Andric     unsigned CommonMaxStores =
1780b57cec5SDimitry Andric       STI.getSelectionDAGInfo()->getCommonMaxStoresPerMemFunc();
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric     MaxStoresPerMemset = MaxStoresPerMemsetOptSize = CommonMaxStores;
1810b57cec5SDimitry Andric     MaxStoresPerMemcpy = MaxStoresPerMemcpyOptSize = CommonMaxStores;
1820b57cec5SDimitry Andric     MaxStoresPerMemmove = MaxStoresPerMemmoveOptSize = CommonMaxStores;
18381ad6265SDimitry Andric     MaxLoadsPerMemcmp = MaxLoadsPerMemcmpOptSize = CommonMaxStores;
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   // CPU/Feature control
1870b57cec5SDimitry Andric   HasAlu32 = STI.getHasAlu32();
1880b57cec5SDimitry Andric   HasJmp32 = STI.getHasJmp32();
1890b57cec5SDimitry Andric   HasJmpExt = STI.getHasJmpExt();
1905f757f3fSDimitry Andric   HasMovsx = STI.hasMovsx();
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
1940b57cec5SDimitry Andric   return false;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1975ffd83dbSDimitry Andric bool BPFTargetLowering::isTruncateFree(Type *Ty1, Type *Ty2) const {
1985ffd83dbSDimitry Andric   if (!Ty1->isIntegerTy() || !Ty2->isIntegerTy())
1995ffd83dbSDimitry Andric     return false;
2005ffd83dbSDimitry Andric   unsigned NumBits1 = Ty1->getPrimitiveSizeInBits();
2015ffd83dbSDimitry Andric   unsigned NumBits2 = Ty2->getPrimitiveSizeInBits();
2025ffd83dbSDimitry Andric   return NumBits1 > NumBits2;
2035ffd83dbSDimitry Andric }
2045ffd83dbSDimitry Andric 
2055ffd83dbSDimitry Andric bool BPFTargetLowering::isTruncateFree(EVT VT1, EVT VT2) const {
2065ffd83dbSDimitry Andric   if (!VT1.isInteger() || !VT2.isInteger())
2075ffd83dbSDimitry Andric     return false;
2085ffd83dbSDimitry Andric   unsigned NumBits1 = VT1.getSizeInBits();
2095ffd83dbSDimitry Andric   unsigned NumBits2 = VT2.getSizeInBits();
2105ffd83dbSDimitry Andric   return NumBits1 > NumBits2;
2115ffd83dbSDimitry Andric }
2125ffd83dbSDimitry Andric 
2135ffd83dbSDimitry Andric bool BPFTargetLowering::isZExtFree(Type *Ty1, Type *Ty2) const {
2145ffd83dbSDimitry Andric   if (!getHasAlu32() || !Ty1->isIntegerTy() || !Ty2->isIntegerTy())
2155ffd83dbSDimitry Andric     return false;
2165ffd83dbSDimitry Andric   unsigned NumBits1 = Ty1->getPrimitiveSizeInBits();
2175ffd83dbSDimitry Andric   unsigned NumBits2 = Ty2->getPrimitiveSizeInBits();
2185ffd83dbSDimitry Andric   return NumBits1 == 32 && NumBits2 == 64;
2195ffd83dbSDimitry Andric }
2205ffd83dbSDimitry Andric 
2215ffd83dbSDimitry Andric bool BPFTargetLowering::isZExtFree(EVT VT1, EVT VT2) const {
2225ffd83dbSDimitry Andric   if (!getHasAlu32() || !VT1.isInteger() || !VT2.isInteger())
2235ffd83dbSDimitry Andric     return false;
2245ffd83dbSDimitry Andric   unsigned NumBits1 = VT1.getSizeInBits();
2255ffd83dbSDimitry Andric   unsigned NumBits2 = VT2.getSizeInBits();
2265ffd83dbSDimitry Andric   return NumBits1 == 32 && NumBits2 == 64;
2275ffd83dbSDimitry Andric }
2285ffd83dbSDimitry Andric 
2295f757f3fSDimitry Andric bool BPFTargetLowering::isZExtFree(SDValue Val, EVT VT2) const {
2305f757f3fSDimitry Andric   EVT VT1 = Val.getValueType();
2315f757f3fSDimitry Andric   if (Val.getOpcode() == ISD::LOAD && VT1.isSimple() && VT2.isSimple()) {
2325f757f3fSDimitry Andric     MVT MT1 = VT1.getSimpleVT().SimpleTy;
2335f757f3fSDimitry Andric     MVT MT2 = VT2.getSimpleVT().SimpleTy;
2345f757f3fSDimitry Andric     if ((MT1 == MVT::i8 || MT1 == MVT::i16 || MT1 == MVT::i32) &&
2355f757f3fSDimitry Andric         (MT2 == MVT::i32 || MT2 == MVT::i64))
2365f757f3fSDimitry Andric       return true;
2375f757f3fSDimitry Andric   }
2385f757f3fSDimitry Andric   return TargetLoweringBase::isZExtFree(Val, VT2);
2395f757f3fSDimitry Andric }
2405f757f3fSDimitry Andric 
241fe6060f1SDimitry Andric BPFTargetLowering::ConstraintType
242fe6060f1SDimitry Andric BPFTargetLowering::getConstraintType(StringRef Constraint) const {
243fe6060f1SDimitry Andric   if (Constraint.size() == 1) {
244fe6060f1SDimitry Andric     switch (Constraint[0]) {
245fe6060f1SDimitry Andric     default:
246fe6060f1SDimitry Andric       break;
247fe6060f1SDimitry Andric     case 'w':
248fe6060f1SDimitry Andric       return C_RegisterClass;
249fe6060f1SDimitry Andric     }
250fe6060f1SDimitry Andric   }
251fe6060f1SDimitry Andric 
252fe6060f1SDimitry Andric   return TargetLowering::getConstraintType(Constraint);
253fe6060f1SDimitry Andric }
254fe6060f1SDimitry Andric 
2550b57cec5SDimitry Andric std::pair<unsigned, const TargetRegisterClass *>
2560b57cec5SDimitry Andric BPFTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
2570b57cec5SDimitry Andric                                                 StringRef Constraint,
2580b57cec5SDimitry Andric                                                 MVT VT) const {
2595f757f3fSDimitry Andric   if (Constraint.size() == 1) {
2600b57cec5SDimitry Andric     // GCC Constraint Letters
2610b57cec5SDimitry Andric     switch (Constraint[0]) {
2620b57cec5SDimitry Andric     case 'r': // GENERAL_REGS
2630b57cec5SDimitry Andric       return std::make_pair(0U, &BPF::GPRRegClass);
264fe6060f1SDimitry Andric     case 'w':
265fe6060f1SDimitry Andric       if (HasAlu32)
266fe6060f1SDimitry Andric         return std::make_pair(0U, &BPF::GPR32RegClass);
267fe6060f1SDimitry Andric       break;
2680b57cec5SDimitry Andric     default:
2690b57cec5SDimitry Andric       break;
2700b57cec5SDimitry Andric     }
2715f757f3fSDimitry Andric   }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
2740b57cec5SDimitry Andric }
2750b57cec5SDimitry Andric 
276fe6060f1SDimitry Andric void BPFTargetLowering::ReplaceNodeResults(
277fe6060f1SDimitry Andric   SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
2785f757f3fSDimitry Andric   const char *Msg;
279fe6060f1SDimitry Andric   uint32_t Opcode = N->getOpcode();
280fe6060f1SDimitry Andric   switch (Opcode) {
281fe6060f1SDimitry Andric   default:
2825f757f3fSDimitry Andric     report_fatal_error("unhandled custom legalization: " + Twine(Opcode));
283fe6060f1SDimitry Andric   case ISD::ATOMIC_LOAD_ADD:
284fe6060f1SDimitry Andric   case ISD::ATOMIC_LOAD_AND:
285fe6060f1SDimitry Andric   case ISD::ATOMIC_LOAD_OR:
286fe6060f1SDimitry Andric   case ISD::ATOMIC_LOAD_XOR:
287fe6060f1SDimitry Andric   case ISD::ATOMIC_SWAP:
288fe6060f1SDimitry Andric   case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS:
289fe6060f1SDimitry Andric     if (HasAlu32 || Opcode == ISD::ATOMIC_LOAD_ADD)
2905f757f3fSDimitry Andric       Msg = "unsupported atomic operation, please use 32/64 bit version";
291fe6060f1SDimitry Andric     else
2925f757f3fSDimitry Andric       Msg = "unsupported atomic operation, please use 64 bit version";
293fe6060f1SDimitry Andric     break;
294fe6060f1SDimitry Andric   }
295fe6060f1SDimitry Andric 
296fe6060f1SDimitry Andric   SDLoc DL(N);
2975f757f3fSDimitry Andric   // We'll still produce a fatal error downstream, but this diagnostic is more
2985f757f3fSDimitry Andric   // user-friendly.
2995f757f3fSDimitry Andric   fail(DL, DAG, Msg);
300fe6060f1SDimitry Andric }
301fe6060f1SDimitry Andric 
3020b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
3030b57cec5SDimitry Andric   switch (Op.getOpcode()) {
3045f757f3fSDimitry Andric   default:
3055f757f3fSDimitry Andric     report_fatal_error("unimplemented opcode: " + Twine(Op.getOpcode()));
3060b57cec5SDimitry Andric   case ISD::BR_CC:
3070b57cec5SDimitry Andric     return LowerBR_CC(Op, DAG);
3080b57cec5SDimitry Andric   case ISD::GlobalAddress:
3090b57cec5SDimitry Andric     return LowerGlobalAddress(Op, DAG);
310*0fca6ea1SDimitry Andric   case ISD::ConstantPool:
311*0fca6ea1SDimitry Andric     return LowerConstantPool(Op, DAG);
3120b57cec5SDimitry Andric   case ISD::SELECT_CC:
3130b57cec5SDimitry Andric     return LowerSELECT_CC(Op, DAG);
3145f757f3fSDimitry Andric   case ISD::SDIV:
3155f757f3fSDimitry Andric   case ISD::SREM:
3165f757f3fSDimitry Andric     return LowerSDIVSREM(Op, DAG);
3175ffd83dbSDimitry Andric   case ISD::DYNAMIC_STACKALLOC:
3185f757f3fSDimitry Andric     return LowerDYNAMIC_STACKALLOC(Op, DAG);
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric // Calling Convention Implementation
3230b57cec5SDimitry Andric #include "BPFGenCallingConv.inc"
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerFormalArguments(
3260b57cec5SDimitry Andric     SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
3270b57cec5SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
3280b57cec5SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
3290b57cec5SDimitry Andric   switch (CallConv) {
3300b57cec5SDimitry Andric   default:
3315f757f3fSDimitry Andric     report_fatal_error("unimplemented calling convention: " + Twine(CallConv));
3320b57cec5SDimitry Andric   case CallingConv::C:
3330b57cec5SDimitry Andric   case CallingConv::Fast:
3340b57cec5SDimitry Andric     break;
3350b57cec5SDimitry Andric   }
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
3380b57cec5SDimitry Andric   MachineRegisterInfo &RegInfo = MF.getRegInfo();
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   // Assign locations to all of the incoming arguments.
3410b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
3420b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
3430b57cec5SDimitry Andric   CCInfo.AnalyzeFormalArguments(Ins, getHasAlu32() ? CC_BPF32 : CC_BPF64);
3440b57cec5SDimitry Andric 
3455f757f3fSDimitry Andric   bool HasMemArgs = false;
3465f757f3fSDimitry Andric   for (size_t I = 0; I < ArgLocs.size(); ++I) {
3475f757f3fSDimitry Andric     auto &VA = ArgLocs[I];
3485f757f3fSDimitry Andric 
3490b57cec5SDimitry Andric     if (VA.isRegLoc()) {
3500b57cec5SDimitry Andric       // Arguments passed in registers
3510b57cec5SDimitry Andric       EVT RegVT = VA.getLocVT();
3520b57cec5SDimitry Andric       MVT::SimpleValueType SimpleTy = RegVT.getSimpleVT().SimpleTy;
3530b57cec5SDimitry Andric       switch (SimpleTy) {
3540b57cec5SDimitry Andric       default: {
3555f757f3fSDimitry Andric         std::string Str;
3565f757f3fSDimitry Andric         {
3575f757f3fSDimitry Andric           raw_string_ostream OS(Str);
3585f757f3fSDimitry Andric           RegVT.print(OS);
3595f757f3fSDimitry Andric         }
3605f757f3fSDimitry Andric         report_fatal_error("unhandled argument type: " + Twine(Str));
3610b57cec5SDimitry Andric       }
3620b57cec5SDimitry Andric       case MVT::i32:
3630b57cec5SDimitry Andric       case MVT::i64:
3648bcb0991SDimitry Andric         Register VReg = RegInfo.createVirtualRegister(
3658bcb0991SDimitry Andric             SimpleTy == MVT::i64 ? &BPF::GPRRegClass : &BPF::GPR32RegClass);
3660b57cec5SDimitry Andric         RegInfo.addLiveIn(VA.getLocReg(), VReg);
3670b57cec5SDimitry Andric         SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric         // If this is an value that has been promoted to wider types, insert an
3700b57cec5SDimitry Andric         // assert[sz]ext to capture this, then truncate to the right size.
3710b57cec5SDimitry Andric         if (VA.getLocInfo() == CCValAssign::SExt)
3720b57cec5SDimitry Andric           ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue,
3730b57cec5SDimitry Andric                                  DAG.getValueType(VA.getValVT()));
3740b57cec5SDimitry Andric         else if (VA.getLocInfo() == CCValAssign::ZExt)
3750b57cec5SDimitry Andric           ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue,
3760b57cec5SDimitry Andric                                  DAG.getValueType(VA.getValVT()));
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric         if (VA.getLocInfo() != CCValAssign::Full)
3790b57cec5SDimitry Andric           ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue);
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric         InVals.push_back(ArgValue);
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric         break;
3840b57cec5SDimitry Andric       }
3850b57cec5SDimitry Andric     } else {
3865f757f3fSDimitry Andric       if (VA.isMemLoc())
3875f757f3fSDimitry Andric         HasMemArgs = true;
3885f757f3fSDimitry Andric       else
3895f757f3fSDimitry Andric         report_fatal_error("unhandled argument location");
3900b57cec5SDimitry Andric       InVals.push_back(DAG.getConstant(0, DL, VA.getLocVT()));
3910b57cec5SDimitry Andric     }
3920b57cec5SDimitry Andric   }
3935f757f3fSDimitry Andric   if (HasMemArgs)
3945f757f3fSDimitry Andric     fail(DL, DAG, "stack arguments are not supported");
3955f757f3fSDimitry Andric   if (IsVarArg)
3965f757f3fSDimitry Andric     fail(DL, DAG, "variadic functions are not supported");
3975f757f3fSDimitry Andric   if (MF.getFunction().hasStructRetAttr())
3985f757f3fSDimitry Andric     fail(DL, DAG, "aggregate returns are not supported");
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   return Chain;
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
4035f757f3fSDimitry Andric const size_t BPFTargetLowering::MaxArgs = 5;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
4060b57cec5SDimitry Andric                                      SmallVectorImpl<SDValue> &InVals) const {
4070b57cec5SDimitry Andric   SelectionDAG &DAG = CLI.DAG;
4080b57cec5SDimitry Andric   auto &Outs = CLI.Outs;
4090b57cec5SDimitry Andric   auto &OutVals = CLI.OutVals;
4100b57cec5SDimitry Andric   auto &Ins = CLI.Ins;
4110b57cec5SDimitry Andric   SDValue Chain = CLI.Chain;
4120b57cec5SDimitry Andric   SDValue Callee = CLI.Callee;
4130b57cec5SDimitry Andric   bool &IsTailCall = CLI.IsTailCall;
4140b57cec5SDimitry Andric   CallingConv::ID CallConv = CLI.CallConv;
4150b57cec5SDimitry Andric   bool IsVarArg = CLI.IsVarArg;
4160b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric   // BPF target does not support tail call optimization.
4190b57cec5SDimitry Andric   IsTailCall = false;
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   switch (CallConv) {
4220b57cec5SDimitry Andric   default:
4235f757f3fSDimitry Andric     report_fatal_error("unsupported calling convention: " + Twine(CallConv));
4240b57cec5SDimitry Andric   case CallingConv::Fast:
4250b57cec5SDimitry Andric   case CallingConv::C:
4260b57cec5SDimitry Andric     break;
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   // Analyze operands of the call, assigning locations to each operand.
4300b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> ArgLocs;
4310b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric   CCInfo.AnalyzeCallOperands(Outs, getHasAlu32() ? CC_BPF32 : CC_BPF64);
4340b57cec5SDimitry Andric 
43506c3fb27SDimitry Andric   unsigned NumBytes = CCInfo.getStackSize();
4360b57cec5SDimitry Andric 
4370b57cec5SDimitry Andric   if (Outs.size() > MaxArgs)
4385f757f3fSDimitry Andric     fail(CLI.DL, DAG, "too many arguments", Callee);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric   for (auto &Arg : Outs) {
4410b57cec5SDimitry Andric     ISD::ArgFlagsTy Flags = Arg.Flags;
4420b57cec5SDimitry Andric     if (!Flags.isByVal())
4430b57cec5SDimitry Andric       continue;
4440b57cec5SDimitry Andric     fail(CLI.DL, DAG, "pass by value not supported", Callee);
4455f757f3fSDimitry Andric     break;
4460b57cec5SDimitry Andric   }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   auto PtrVT = getPointerTy(MF.getDataLayout());
4490b57cec5SDimitry Andric   Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL);
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   SmallVector<std::pair<unsigned, SDValue>, MaxArgs> RegsToPass;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   // Walk arg assignments
4545f757f3fSDimitry Andric   for (size_t i = 0; i < std::min(ArgLocs.size(), MaxArgs); ++i) {
4550b57cec5SDimitry Andric     CCValAssign &VA = ArgLocs[i];
4565f757f3fSDimitry Andric     SDValue &Arg = OutVals[i];
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric     // Promote the value if needed.
4590b57cec5SDimitry Andric     switch (VA.getLocInfo()) {
4600b57cec5SDimitry Andric     default:
4615f757f3fSDimitry Andric       report_fatal_error("unhandled location info: " + Twine(VA.getLocInfo()));
4620b57cec5SDimitry Andric     case CCValAssign::Full:
4630b57cec5SDimitry Andric       break;
4640b57cec5SDimitry Andric     case CCValAssign::SExt:
4650b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::SIGN_EXTEND, CLI.DL, VA.getLocVT(), Arg);
4660b57cec5SDimitry Andric       break;
4670b57cec5SDimitry Andric     case CCValAssign::ZExt:
4680b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ZERO_EXTEND, CLI.DL, VA.getLocVT(), Arg);
4690b57cec5SDimitry Andric       break;
4700b57cec5SDimitry Andric     case CCValAssign::AExt:
4710b57cec5SDimitry Andric       Arg = DAG.getNode(ISD::ANY_EXTEND, CLI.DL, VA.getLocVT(), Arg);
4720b57cec5SDimitry Andric       break;
4730b57cec5SDimitry Andric     }
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric     // Push arguments into RegsToPass vector
4760b57cec5SDimitry Andric     if (VA.isRegLoc())
4770b57cec5SDimitry Andric       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
4780b57cec5SDimitry Andric     else
4795f757f3fSDimitry Andric       report_fatal_error("stack arguments are not supported");
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
48206c3fb27SDimitry Andric   SDValue InGlue;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   // Build a sequence of copy-to-reg nodes chained together with token chain and
48506c3fb27SDimitry Andric   // flag operands which copy the outgoing args into registers.  The InGlue in
4860b57cec5SDimitry Andric   // necessary since all emitted instructions must be stuck together.
4870b57cec5SDimitry Andric   for (auto &Reg : RegsToPass) {
48806c3fb27SDimitry Andric     Chain = DAG.getCopyToReg(Chain, CLI.DL, Reg.first, Reg.second, InGlue);
48906c3fb27SDimitry Andric     InGlue = Chain.getValue(1);
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   // If the callee is a GlobalAddress node (quite common, every direct call is)
4930b57cec5SDimitry Andric   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it.
4940b57cec5SDimitry Andric   // Likewise ExternalSymbol -> TargetExternalSymbol.
4950b57cec5SDimitry Andric   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
4960b57cec5SDimitry Andric     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT,
4970b57cec5SDimitry Andric                                         G->getOffset(), 0);
4980b57cec5SDimitry Andric   } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) {
4990b57cec5SDimitry Andric     Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0);
5005f757f3fSDimitry Andric     fail(CLI.DL, DAG,
5015f757f3fSDimitry Andric          Twine("A call to built-in function '" + StringRef(E->getSymbol()) +
5025f757f3fSDimitry Andric                "' is not supported."));
5030b57cec5SDimitry Andric   }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   // Returns a chain & a flag for retval copy to use.
5060b57cec5SDimitry Andric   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
5070b57cec5SDimitry Andric   SmallVector<SDValue, 8> Ops;
5080b57cec5SDimitry Andric   Ops.push_back(Chain);
5090b57cec5SDimitry Andric   Ops.push_back(Callee);
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   // Add argument registers to the end of the list so that they are
5120b57cec5SDimitry Andric   // known live into the call.
5130b57cec5SDimitry Andric   for (auto &Reg : RegsToPass)
5140b57cec5SDimitry Andric     Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType()));
5150b57cec5SDimitry Andric 
51606c3fb27SDimitry Andric   if (InGlue.getNode())
51706c3fb27SDimitry Andric     Ops.push_back(InGlue);
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   Chain = DAG.getNode(BPFISD::CALL, CLI.DL, NodeTys, Ops);
52006c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
52106c3fb27SDimitry Andric 
52206c3fb27SDimitry Andric   DAG.addNoMergeSiteInfo(Chain.getNode(), CLI.NoMerge);
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   // Create the CALLSEQ_END node.
52506c3fb27SDimitry Andric   Chain = DAG.getCALLSEQ_END(Chain, NumBytes, 0, InGlue, CLI.DL);
52606c3fb27SDimitry Andric   InGlue = Chain.getValue(1);
5270b57cec5SDimitry Andric 
5280b57cec5SDimitry Andric   // Handle result values, copying them out of physregs into vregs that we
5290b57cec5SDimitry Andric   // return.
53006c3fb27SDimitry Andric   return LowerCallResult(Chain, InGlue, CallConv, IsVarArg, Ins, CLI.DL, DAG,
5310b57cec5SDimitry Andric                          InVals);
5320b57cec5SDimitry Andric }
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric SDValue
5350b57cec5SDimitry Andric BPFTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
5360b57cec5SDimitry Andric                                bool IsVarArg,
5370b57cec5SDimitry Andric                                const SmallVectorImpl<ISD::OutputArg> &Outs,
5380b57cec5SDimitry Andric                                const SmallVectorImpl<SDValue> &OutVals,
5390b57cec5SDimitry Andric                                const SDLoc &DL, SelectionDAG &DAG) const {
54006c3fb27SDimitry Andric   unsigned Opc = BPFISD::RET_GLUE;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   // CCValAssign - represent the assignment of the return value to a location
5430b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
5440b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   // CCState - Info about the registers and stack slot.
5470b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   if (MF.getFunction().getReturnType()->isAggregateType()) {
5505f757f3fSDimitry Andric     fail(DL, DAG, "aggregate returns are not supported");
5510b57cec5SDimitry Andric     return DAG.getNode(Opc, DL, MVT::Other, Chain);
5520b57cec5SDimitry Andric   }
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   // Analize return values.
5550b57cec5SDimitry Andric   CCInfo.AnalyzeReturn(Outs, getHasAlu32() ? RetCC_BPF32 : RetCC_BPF64);
5560b57cec5SDimitry Andric 
55706c3fb27SDimitry Andric   SDValue Glue;
5580b57cec5SDimitry Andric   SmallVector<SDValue, 4> RetOps(1, Chain);
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   // Copy the result values into the output registers.
5615f757f3fSDimitry Andric   for (size_t i = 0; i != RVLocs.size(); ++i) {
5620b57cec5SDimitry Andric     CCValAssign &VA = RVLocs[i];
5635f757f3fSDimitry Andric     if (!VA.isRegLoc())
5645f757f3fSDimitry Andric       report_fatal_error("stack return values are not supported");
5650b57cec5SDimitry Andric 
56606c3fb27SDimitry Andric     Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Glue);
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric     // Guarantee that all emitted copies are stuck together,
5690b57cec5SDimitry Andric     // avoiding something bad.
57006c3fb27SDimitry Andric     Glue = Chain.getValue(1);
5710b57cec5SDimitry Andric     RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT()));
5720b57cec5SDimitry Andric   }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   RetOps[0] = Chain; // Update chain.
5750b57cec5SDimitry Andric 
57606c3fb27SDimitry Andric   // Add the glue if we have it.
57706c3fb27SDimitry Andric   if (Glue.getNode())
57806c3fb27SDimitry Andric     RetOps.push_back(Glue);
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   return DAG.getNode(Opc, DL, MVT::Other, RetOps);
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerCallResult(
58406c3fb27SDimitry Andric     SDValue Chain, SDValue InGlue, CallingConv::ID CallConv, bool IsVarArg,
5850b57cec5SDimitry Andric     const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
5860b57cec5SDimitry Andric     SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   MachineFunction &MF = DAG.getMachineFunction();
5890b57cec5SDimitry Andric   // Assign locations to each value returned by this call.
5900b57cec5SDimitry Andric   SmallVector<CCValAssign, 16> RVLocs;
5910b57cec5SDimitry Andric   CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext());
5920b57cec5SDimitry Andric 
5935f757f3fSDimitry Andric   if (Ins.size() > 1) {
5940b57cec5SDimitry Andric     fail(DL, DAG, "only small returns supported");
5955f757f3fSDimitry Andric     for (auto &In : Ins)
5965f757f3fSDimitry Andric       InVals.push_back(DAG.getConstant(0, DL, In.VT));
59706c3fb27SDimitry Andric     return DAG.getCopyFromReg(Chain, DL, 1, Ins[0].VT, InGlue).getValue(1);
5980b57cec5SDimitry Andric   }
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric   CCInfo.AnalyzeCallResult(Ins, getHasAlu32() ? RetCC_BPF32 : RetCC_BPF64);
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   // Copy all of the result registers out of their specified physreg.
6030b57cec5SDimitry Andric   for (auto &Val : RVLocs) {
6040b57cec5SDimitry Andric     Chain = DAG.getCopyFromReg(Chain, DL, Val.getLocReg(),
60506c3fb27SDimitry Andric                                Val.getValVT(), InGlue).getValue(1);
60606c3fb27SDimitry Andric     InGlue = Chain.getValue(2);
6070b57cec5SDimitry Andric     InVals.push_back(Chain.getValue(0));
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   return Chain;
6110b57cec5SDimitry Andric }
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric static void NegateCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) {
6140b57cec5SDimitry Andric   switch (CC) {
6150b57cec5SDimitry Andric   default:
6160b57cec5SDimitry Andric     break;
6170b57cec5SDimitry Andric   case ISD::SETULT:
6180b57cec5SDimitry Andric   case ISD::SETULE:
6190b57cec5SDimitry Andric   case ISD::SETLT:
6200b57cec5SDimitry Andric   case ISD::SETLE:
6210b57cec5SDimitry Andric     CC = ISD::getSetCCSwappedOperands(CC);
6220b57cec5SDimitry Andric     std::swap(LHS, RHS);
6230b57cec5SDimitry Andric     break;
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric }
6260b57cec5SDimitry Andric 
6275f757f3fSDimitry Andric SDValue BPFTargetLowering::LowerSDIVSREM(SDValue Op, SelectionDAG &DAG) const {
6285f757f3fSDimitry Andric   SDLoc DL(Op);
6295f757f3fSDimitry Andric   fail(DL, DAG,
6305f757f3fSDimitry Andric        "unsupported signed division, please convert to unsigned div/mod.");
6315f757f3fSDimitry Andric   return DAG.getUNDEF(Op->getValueType(0));
6325f757f3fSDimitry Andric }
6335f757f3fSDimitry Andric 
6345f757f3fSDimitry Andric SDValue BPFTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
6355f757f3fSDimitry Andric                                                    SelectionDAG &DAG) const {
6365f757f3fSDimitry Andric   SDLoc DL(Op);
6375f757f3fSDimitry Andric   fail(DL, DAG, "unsupported dynamic stack allocation");
6385f757f3fSDimitry Andric   auto Ops = {DAG.getConstant(0, SDLoc(), Op.getValueType()), Op.getOperand(0)};
6395f757f3fSDimitry Andric   return DAG.getMergeValues(Ops, SDLoc());
6405f757f3fSDimitry Andric }
6415f757f3fSDimitry Andric 
6420b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
6430b57cec5SDimitry Andric   SDValue Chain = Op.getOperand(0);
6440b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
6450b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(2);
6460b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(3);
6470b57cec5SDimitry Andric   SDValue Dest = Op.getOperand(4);
6480b57cec5SDimitry Andric   SDLoc DL(Op);
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   if (!getHasJmpExt())
6510b57cec5SDimitry Andric     NegateCC(LHS, RHS, CC);
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   return DAG.getNode(BPFISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS,
6540b57cec5SDimitry Andric                      DAG.getConstant(CC, DL, LHS.getValueType()), Dest);
6550b57cec5SDimitry Andric }
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
6580b57cec5SDimitry Andric   SDValue LHS = Op.getOperand(0);
6590b57cec5SDimitry Andric   SDValue RHS = Op.getOperand(1);
6600b57cec5SDimitry Andric   SDValue TrueV = Op.getOperand(2);
6610b57cec5SDimitry Andric   SDValue FalseV = Op.getOperand(3);
6620b57cec5SDimitry Andric   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
6630b57cec5SDimitry Andric   SDLoc DL(Op);
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   if (!getHasJmpExt())
6660b57cec5SDimitry Andric     NegateCC(LHS, RHS, CC);
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   SDValue TargetCC = DAG.getConstant(CC, DL, LHS.getValueType());
6690b57cec5SDimitry Andric   SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue);
6700b57cec5SDimitry Andric   SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV};
6710b57cec5SDimitry Andric 
6720b57cec5SDimitry Andric   return DAG.getNode(BPFISD::SELECT_CC, DL, VTs, Ops);
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric const char *BPFTargetLowering::getTargetNodeName(unsigned Opcode) const {
6760b57cec5SDimitry Andric   switch ((BPFISD::NodeType)Opcode) {
6770b57cec5SDimitry Andric   case BPFISD::FIRST_NUMBER:
6780b57cec5SDimitry Andric     break;
67906c3fb27SDimitry Andric   case BPFISD::RET_GLUE:
68006c3fb27SDimitry Andric     return "BPFISD::RET_GLUE";
6810b57cec5SDimitry Andric   case BPFISD::CALL:
6820b57cec5SDimitry Andric     return "BPFISD::CALL";
6830b57cec5SDimitry Andric   case BPFISD::SELECT_CC:
6840b57cec5SDimitry Andric     return "BPFISD::SELECT_CC";
6850b57cec5SDimitry Andric   case BPFISD::BR_CC:
6860b57cec5SDimitry Andric     return "BPFISD::BR_CC";
6870b57cec5SDimitry Andric   case BPFISD::Wrapper:
6880b57cec5SDimitry Andric     return "BPFISD::Wrapper";
6890b57cec5SDimitry Andric   case BPFISD::MEMCPY:
6900b57cec5SDimitry Andric     return "BPFISD::MEMCPY";
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric   return nullptr;
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
695*0fca6ea1SDimitry Andric static SDValue getTargetNode(GlobalAddressSDNode *N, const SDLoc &DL, EVT Ty,
696*0fca6ea1SDimitry Andric                              SelectionDAG &DAG, unsigned Flags) {
697*0fca6ea1SDimitry Andric   return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
698*0fca6ea1SDimitry Andric }
699*0fca6ea1SDimitry Andric 
700*0fca6ea1SDimitry Andric static SDValue getTargetNode(ConstantPoolSDNode *N, const SDLoc &DL, EVT Ty,
701*0fca6ea1SDimitry Andric                              SelectionDAG &DAG, unsigned Flags) {
702*0fca6ea1SDimitry Andric   return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlign(),
703*0fca6ea1SDimitry Andric                                    N->getOffset(), Flags);
704*0fca6ea1SDimitry Andric }
705*0fca6ea1SDimitry Andric 
706*0fca6ea1SDimitry Andric template <class NodeTy>
707*0fca6ea1SDimitry Andric SDValue BPFTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
708*0fca6ea1SDimitry Andric                                    unsigned Flags) const {
709*0fca6ea1SDimitry Andric   SDLoc DL(N);
710*0fca6ea1SDimitry Andric 
711*0fca6ea1SDimitry Andric   SDValue GA = getTargetNode(N, DL, MVT::i64, DAG, Flags);
712*0fca6ea1SDimitry Andric 
713*0fca6ea1SDimitry Andric   return DAG.getNode(BPFISD::Wrapper, DL, MVT::i64, GA);
714*0fca6ea1SDimitry Andric }
715*0fca6ea1SDimitry Andric 
7160b57cec5SDimitry Andric SDValue BPFTargetLowering::LowerGlobalAddress(SDValue Op,
7170b57cec5SDimitry Andric                                               SelectionDAG &DAG) const {
718*0fca6ea1SDimitry Andric   GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
7195f757f3fSDimitry Andric   if (N->getOffset() != 0)
7205f757f3fSDimitry Andric     report_fatal_error("invalid offset for global address: " +
7215f757f3fSDimitry Andric                        Twine(N->getOffset()));
722*0fca6ea1SDimitry Andric   return getAddr(N, DAG);
723*0fca6ea1SDimitry Andric }
7240b57cec5SDimitry Andric 
725*0fca6ea1SDimitry Andric SDValue BPFTargetLowering::LowerConstantPool(SDValue Op,
726*0fca6ea1SDimitry Andric                                              SelectionDAG &DAG) const {
727*0fca6ea1SDimitry Andric   ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
7280b57cec5SDimitry Andric 
729*0fca6ea1SDimitry Andric   return getAddr(N, DAG);
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric unsigned
7330b57cec5SDimitry Andric BPFTargetLowering::EmitSubregExt(MachineInstr &MI, MachineBasicBlock *BB,
7340b57cec5SDimitry Andric                                  unsigned Reg, bool isSigned) const {
7350b57cec5SDimitry Andric   const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
7360b57cec5SDimitry Andric   const TargetRegisterClass *RC = getRegClassFor(MVT::i64);
7370b57cec5SDimitry Andric   int RShiftOp = isSigned ? BPF::SRA_ri : BPF::SRL_ri;
7380b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
7390b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   MachineRegisterInfo &RegInfo = F->getRegInfo();
7425ffd83dbSDimitry Andric 
7435ffd83dbSDimitry Andric   if (!isSigned) {
7445ffd83dbSDimitry Andric     Register PromotedReg0 = RegInfo.createVirtualRegister(RC);
7455ffd83dbSDimitry Andric     BuildMI(BB, DL, TII.get(BPF::MOV_32_64), PromotedReg0).addReg(Reg);
7465ffd83dbSDimitry Andric     return PromotedReg0;
7475ffd83dbSDimitry Andric   }
7488bcb0991SDimitry Andric   Register PromotedReg0 = RegInfo.createVirtualRegister(RC);
7498bcb0991SDimitry Andric   Register PromotedReg1 = RegInfo.createVirtualRegister(RC);
7508bcb0991SDimitry Andric   Register PromotedReg2 = RegInfo.createVirtualRegister(RC);
7515f757f3fSDimitry Andric   if (HasMovsx) {
7525f757f3fSDimitry Andric     BuildMI(BB, DL, TII.get(BPF::MOVSX_rr_32), PromotedReg0).addReg(Reg);
7535f757f3fSDimitry Andric   } else {
7540b57cec5SDimitry Andric     BuildMI(BB, DL, TII.get(BPF::MOV_32_64), PromotedReg0).addReg(Reg);
7550b57cec5SDimitry Andric     BuildMI(BB, DL, TII.get(BPF::SLL_ri), PromotedReg1)
7560b57cec5SDimitry Andric       .addReg(PromotedReg0).addImm(32);
7570b57cec5SDimitry Andric     BuildMI(BB, DL, TII.get(RShiftOp), PromotedReg2)
7580b57cec5SDimitry Andric       .addReg(PromotedReg1).addImm(32);
7595f757f3fSDimitry Andric   }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric   return PromotedReg2;
7620b57cec5SDimitry Andric }
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric MachineBasicBlock *
7650b57cec5SDimitry Andric BPFTargetLowering::EmitInstrWithCustomInserterMemcpy(MachineInstr &MI,
7660b57cec5SDimitry Andric                                                      MachineBasicBlock *BB)
7670b57cec5SDimitry Andric                                                      const {
7680b57cec5SDimitry Andric   MachineFunction *MF = MI.getParent()->getParent();
7690b57cec5SDimitry Andric   MachineRegisterInfo &MRI = MF->getRegInfo();
7700b57cec5SDimitry Andric   MachineInstrBuilder MIB(*MF, MI);
7710b57cec5SDimitry Andric   unsigned ScratchReg;
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   // This function does custom insertion during lowering BPFISD::MEMCPY which
7740b57cec5SDimitry Andric   // only has two register operands from memcpy semantics, the copy source
7750b57cec5SDimitry Andric   // address and the copy destination address.
7760b57cec5SDimitry Andric   //
7770b57cec5SDimitry Andric   // Because we will expand BPFISD::MEMCPY into load/store pairs, we will need
7780b57cec5SDimitry Andric   // a third scratch register to serve as the destination register of load and
7790b57cec5SDimitry Andric   // source register of store.
7800b57cec5SDimitry Andric   //
7810b57cec5SDimitry Andric   // The scratch register here is with the Define | Dead | EarlyClobber flags.
7820b57cec5SDimitry Andric   // The EarlyClobber flag has the semantic property that the operand it is
7830b57cec5SDimitry Andric   // attached to is clobbered before the rest of the inputs are read. Hence it
7840b57cec5SDimitry Andric   // must be unique among the operands to the instruction. The Define flag is
7850b57cec5SDimitry Andric   // needed to coerce the machine verifier that an Undef value isn't a problem
7860b57cec5SDimitry Andric   // as we anyway is loading memory into it. The Dead flag is needed as the
7870b57cec5SDimitry Andric   // value in scratch isn't supposed to be used by any other instruction.
7880b57cec5SDimitry Andric   ScratchReg = MRI.createVirtualRegister(&BPF::GPRRegClass);
7890b57cec5SDimitry Andric   MIB.addReg(ScratchReg,
7900b57cec5SDimitry Andric              RegState::Define | RegState::Dead | RegState::EarlyClobber);
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   return BB;
7930b57cec5SDimitry Andric }
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric MachineBasicBlock *
7960b57cec5SDimitry Andric BPFTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
7970b57cec5SDimitry Andric                                                MachineBasicBlock *BB) const {
7980b57cec5SDimitry Andric   const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo();
7990b57cec5SDimitry Andric   DebugLoc DL = MI.getDebugLoc();
8000b57cec5SDimitry Andric   unsigned Opc = MI.getOpcode();
8010b57cec5SDimitry Andric   bool isSelectRROp = (Opc == BPF::Select ||
8020b57cec5SDimitry Andric                        Opc == BPF::Select_64_32 ||
8030b57cec5SDimitry Andric                        Opc == BPF::Select_32 ||
8040b57cec5SDimitry Andric                        Opc == BPF::Select_32_64);
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric   bool isMemcpyOp = Opc == BPF::MEMCPY;
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric #ifndef NDEBUG
8090b57cec5SDimitry Andric   bool isSelectRIOp = (Opc == BPF::Select_Ri ||
8100b57cec5SDimitry Andric                        Opc == BPF::Select_Ri_64_32 ||
8110b57cec5SDimitry Andric                        Opc == BPF::Select_Ri_32 ||
8120b57cec5SDimitry Andric                        Opc == BPF::Select_Ri_32_64);
8130b57cec5SDimitry Andric 
8145f757f3fSDimitry Andric   if (!(isSelectRROp || isSelectRIOp || isMemcpyOp))
8155f757f3fSDimitry Andric     report_fatal_error("unhandled instruction type: " + Twine(Opc));
8160b57cec5SDimitry Andric #endif
8170b57cec5SDimitry Andric 
8180b57cec5SDimitry Andric   if (isMemcpyOp)
8190b57cec5SDimitry Andric     return EmitInstrWithCustomInserterMemcpy(MI, BB);
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric   bool is32BitCmp = (Opc == BPF::Select_32 ||
8220b57cec5SDimitry Andric                      Opc == BPF::Select_32_64 ||
8230b57cec5SDimitry Andric                      Opc == BPF::Select_Ri_32 ||
8240b57cec5SDimitry Andric                      Opc == BPF::Select_Ri_32_64);
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   // To "insert" a SELECT instruction, we actually have to insert the diamond
8270b57cec5SDimitry Andric   // control-flow pattern.  The incoming instruction knows the destination vreg
8280b57cec5SDimitry Andric   // to set, the condition code register to branch on, the true/false values to
8290b57cec5SDimitry Andric   // select between, and a branch opcode to use.
8300b57cec5SDimitry Andric   const BasicBlock *LLVM_BB = BB->getBasicBlock();
8310b57cec5SDimitry Andric   MachineFunction::iterator I = ++BB->getIterator();
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric   // ThisMBB:
8340b57cec5SDimitry Andric   // ...
8350b57cec5SDimitry Andric   //  TrueVal = ...
8360b57cec5SDimitry Andric   //  jmp_XX r1, r2 goto Copy1MBB
8370b57cec5SDimitry Andric   //  fallthrough --> Copy0MBB
8380b57cec5SDimitry Andric   MachineBasicBlock *ThisMBB = BB;
8390b57cec5SDimitry Andric   MachineFunction *F = BB->getParent();
8400b57cec5SDimitry Andric   MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
8410b57cec5SDimitry Andric   MachineBasicBlock *Copy1MBB = F->CreateMachineBasicBlock(LLVM_BB);
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric   F->insert(I, Copy0MBB);
8440b57cec5SDimitry Andric   F->insert(I, Copy1MBB);
8450b57cec5SDimitry Andric   // Update machine-CFG edges by transferring all successors of the current
8460b57cec5SDimitry Andric   // block to the new block which will contain the Phi node for the select.
8470b57cec5SDimitry Andric   Copy1MBB->splice(Copy1MBB->begin(), BB,
8480b57cec5SDimitry Andric                    std::next(MachineBasicBlock::iterator(MI)), BB->end());
8490b57cec5SDimitry Andric   Copy1MBB->transferSuccessorsAndUpdatePHIs(BB);
8500b57cec5SDimitry Andric   // Next, add the true and fallthrough blocks as its successors.
8510b57cec5SDimitry Andric   BB->addSuccessor(Copy0MBB);
8520b57cec5SDimitry Andric   BB->addSuccessor(Copy1MBB);
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric   // Insert Branch if Flag
8550b57cec5SDimitry Andric   int CC = MI.getOperand(3).getImm();
8560b57cec5SDimitry Andric   int NewCC;
8570b57cec5SDimitry Andric   switch (CC) {
8580b57cec5SDimitry Andric #define SET_NEWCC(X, Y) \
8590b57cec5SDimitry Andric   case ISD::X: \
8600b57cec5SDimitry Andric     if (is32BitCmp && HasJmp32) \
8610b57cec5SDimitry Andric       NewCC = isSelectRROp ? BPF::Y##_rr_32 : BPF::Y##_ri_32; \
8620b57cec5SDimitry Andric     else \
8630b57cec5SDimitry Andric       NewCC = isSelectRROp ? BPF::Y##_rr : BPF::Y##_ri; \
8640b57cec5SDimitry Andric     break
8650b57cec5SDimitry Andric   SET_NEWCC(SETGT, JSGT);
8660b57cec5SDimitry Andric   SET_NEWCC(SETUGT, JUGT);
8670b57cec5SDimitry Andric   SET_NEWCC(SETGE, JSGE);
8680b57cec5SDimitry Andric   SET_NEWCC(SETUGE, JUGE);
8690b57cec5SDimitry Andric   SET_NEWCC(SETEQ, JEQ);
8700b57cec5SDimitry Andric   SET_NEWCC(SETNE, JNE);
8710b57cec5SDimitry Andric   SET_NEWCC(SETLT, JSLT);
8720b57cec5SDimitry Andric   SET_NEWCC(SETULT, JULT);
8730b57cec5SDimitry Andric   SET_NEWCC(SETLE, JSLE);
8740b57cec5SDimitry Andric   SET_NEWCC(SETULE, JULE);
8750b57cec5SDimitry Andric   default:
8760b57cec5SDimitry Andric     report_fatal_error("unimplemented select CondCode " + Twine(CC));
8770b57cec5SDimitry Andric   }
8780b57cec5SDimitry Andric 
8798bcb0991SDimitry Andric   Register LHS = MI.getOperand(1).getReg();
8800b57cec5SDimitry Andric   bool isSignedCmp = (CC == ISD::SETGT ||
8810b57cec5SDimitry Andric                       CC == ISD::SETGE ||
8820b57cec5SDimitry Andric                       CC == ISD::SETLT ||
8830b57cec5SDimitry Andric                       CC == ISD::SETLE);
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric   // eBPF at the moment only has 64-bit comparison. Any 32-bit comparison need
8860b57cec5SDimitry Andric   // to be promoted, however if the 32-bit comparison operands are destination
8870b57cec5SDimitry Andric   // registers then they are implicitly zero-extended already, there is no
8880b57cec5SDimitry Andric   // need of explicit zero-extend sequence for them.
8890b57cec5SDimitry Andric   //
8900b57cec5SDimitry Andric   // We simply do extension for all situations in this method, but we will
8910b57cec5SDimitry Andric   // try to remove those unnecessary in BPFMIPeephole pass.
8920b57cec5SDimitry Andric   if (is32BitCmp && !HasJmp32)
8930b57cec5SDimitry Andric     LHS = EmitSubregExt(MI, BB, LHS, isSignedCmp);
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   if (isSelectRROp) {
8968bcb0991SDimitry Andric     Register RHS = MI.getOperand(2).getReg();
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric     if (is32BitCmp && !HasJmp32)
8990b57cec5SDimitry Andric       RHS = EmitSubregExt(MI, BB, RHS, isSignedCmp);
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     BuildMI(BB, DL, TII.get(NewCC)).addReg(LHS).addReg(RHS).addMBB(Copy1MBB);
9020b57cec5SDimitry Andric   } else {
9030b57cec5SDimitry Andric     int64_t imm32 = MI.getOperand(2).getImm();
904349cc55cSDimitry Andric     // Check before we build J*_ri instruction.
9055f757f3fSDimitry Andric     if (!isInt<32>(imm32))
9065f757f3fSDimitry Andric       report_fatal_error("immediate overflows 32 bits: " + Twine(imm32));
9070b57cec5SDimitry Andric     BuildMI(BB, DL, TII.get(NewCC))
9080b57cec5SDimitry Andric         .addReg(LHS).addImm(imm32).addMBB(Copy1MBB);
9090b57cec5SDimitry Andric   }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   // Copy0MBB:
9120b57cec5SDimitry Andric   //  %FalseValue = ...
9130b57cec5SDimitry Andric   //  # fallthrough to Copy1MBB
9140b57cec5SDimitry Andric   BB = Copy0MBB;
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric   // Update machine-CFG edges
9170b57cec5SDimitry Andric   BB->addSuccessor(Copy1MBB);
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   // Copy1MBB:
9200b57cec5SDimitry Andric   //  %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ]
9210b57cec5SDimitry Andric   // ...
9220b57cec5SDimitry Andric   BB = Copy1MBB;
9230b57cec5SDimitry Andric   BuildMI(*BB, BB->begin(), DL, TII.get(BPF::PHI), MI.getOperand(0).getReg())
9240b57cec5SDimitry Andric       .addReg(MI.getOperand(5).getReg())
9250b57cec5SDimitry Andric       .addMBB(Copy0MBB)
9260b57cec5SDimitry Andric       .addReg(MI.getOperand(4).getReg())
9270b57cec5SDimitry Andric       .addMBB(ThisMBB);
9280b57cec5SDimitry Andric 
9290b57cec5SDimitry Andric   MI.eraseFromParent(); // The pseudo instruction is gone now.
9300b57cec5SDimitry Andric   return BB;
9310b57cec5SDimitry Andric }
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric EVT BPFTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
9340b57cec5SDimitry Andric                                           EVT VT) const {
9350b57cec5SDimitry Andric   return getHasAlu32() ? MVT::i32 : MVT::i64;
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric 
9380b57cec5SDimitry Andric MVT BPFTargetLowering::getScalarShiftAmountTy(const DataLayout &DL,
9390b57cec5SDimitry Andric                                               EVT VT) const {
9400b57cec5SDimitry Andric   return (getHasAlu32() && VT == MVT::i32) ? MVT::i32 : MVT::i64;
9410b57cec5SDimitry Andric }
942349cc55cSDimitry Andric 
943349cc55cSDimitry Andric bool BPFTargetLowering::isLegalAddressingMode(const DataLayout &DL,
944349cc55cSDimitry Andric                                               const AddrMode &AM, Type *Ty,
945349cc55cSDimitry Andric                                               unsigned AS,
946349cc55cSDimitry Andric                                               Instruction *I) const {
947349cc55cSDimitry Andric   // No global is ever allowed as a base.
948349cc55cSDimitry Andric   if (AM.BaseGV)
949349cc55cSDimitry Andric     return false;
950349cc55cSDimitry Andric 
951349cc55cSDimitry Andric   switch (AM.Scale) {
952349cc55cSDimitry Andric   case 0: // "r+i" or just "i", depending on HasBaseReg.
953349cc55cSDimitry Andric     break;
954349cc55cSDimitry Andric   case 1:
955349cc55cSDimitry Andric     if (!AM.HasBaseReg) // allow "r+i".
956349cc55cSDimitry Andric       break;
957349cc55cSDimitry Andric     return false; // disallow "r+r" or "r+r+i".
958349cc55cSDimitry Andric   default:
959349cc55cSDimitry Andric     return false;
960349cc55cSDimitry Andric   }
961349cc55cSDimitry Andric 
962349cc55cSDimitry Andric   return true;
963349cc55cSDimitry Andric }
964