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
fail(const SDLoc & DL,SelectionDAG & DAG,const Twine & Msg,SDValue Val={})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
BPFTargetLowering(const TargetMachine & TM,const BPFSubtarget & STI)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
isOffsetFoldingLegal(const GlobalAddressSDNode * GA) const1930b57cec5SDimitry Andric bool BPFTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const {
1940b57cec5SDimitry Andric return false;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric
isTruncateFree(Type * Ty1,Type * Ty2) const1975ffd83dbSDimitry 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
isTruncateFree(EVT VT1,EVT VT2) const2055ffd83dbSDimitry 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
isZExtFree(Type * Ty1,Type * Ty2) const2135ffd83dbSDimitry 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
isZExtFree(EVT VT1,EVT VT2) const2215ffd83dbSDimitry 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
isZExtFree(SDValue Val,EVT VT2) const2295f757f3fSDimitry 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
getConstraintType(StringRef Constraint) const242fe6060f1SDimitry 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 *>
getRegForInlineAsmConstraint(const TargetRegisterInfo * TRI,StringRef Constraint,MVT VT) const2560b57cec5SDimitry 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
ReplaceNodeResults(SDNode * N,SmallVectorImpl<SDValue> & Results,SelectionDAG & DAG) const276fe6060f1SDimitry 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
LowerOperation(SDValue Op,SelectionDAG & DAG) const3020b57cec5SDimitry 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
LowerFormalArguments(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const3250b57cec5SDimitry 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
LowerCall(TargetLowering::CallLoweringInfo & CLI,SmallVectorImpl<SDValue> & InVals) const4050b57cec5SDimitry 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
LowerReturn(SDValue Chain,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::OutputArg> & Outs,const SmallVectorImpl<SDValue> & OutVals,const SDLoc & DL,SelectionDAG & DAG) const5350b57cec5SDimitry 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
LowerCallResult(SDValue Chain,SDValue InGlue,CallingConv::ID CallConv,bool IsVarArg,const SmallVectorImpl<ISD::InputArg> & Ins,const SDLoc & DL,SelectionDAG & DAG,SmallVectorImpl<SDValue> & InVals) const5830b57cec5SDimitry 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
NegateCC(SDValue & LHS,SDValue & RHS,ISD::CondCode & CC)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
LowerSDIVSREM(SDValue Op,SelectionDAG & DAG) const6275f757f3fSDimitry 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
LowerDYNAMIC_STACKALLOC(SDValue Op,SelectionDAG & DAG) const6345f757f3fSDimitry 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
LowerBR_CC(SDValue Op,SelectionDAG & DAG) const6420b57cec5SDimitry 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
LowerSELECT_CC(SDValue Op,SelectionDAG & DAG) const6570b57cec5SDimitry 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
getTargetNodeName(unsigned Opcode) const6750b57cec5SDimitry 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
getTargetNode(GlobalAddressSDNode * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,unsigned Flags)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
getTargetNode(ConstantPoolSDNode * N,const SDLoc & DL,EVT Ty,SelectionDAG & DAG,unsigned Flags)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>
getAddr(NodeTy * N,SelectionDAG & DAG,unsigned Flags) const707*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
LowerGlobalAddress(SDValue Op,SelectionDAG & DAG) const7160b57cec5SDimitry 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
LowerConstantPool(SDValue Op,SelectionDAG & DAG) const725*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
EmitSubregExt(MachineInstr & MI,MachineBasicBlock * BB,unsigned Reg,bool isSigned) const7330b57cec5SDimitry 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 *
EmitInstrWithCustomInserterMemcpy(MachineInstr & MI,MachineBasicBlock * BB) const7650b57cec5SDimitry 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 *
EmitInstrWithCustomInserter(MachineInstr & MI,MachineBasicBlock * BB) const7960b57cec5SDimitry 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
getSetCCResultType(const DataLayout &,LLVMContext &,EVT VT) const9330b57cec5SDimitry Andric EVT BPFTargetLowering::getSetCCResultType(const DataLayout &, LLVMContext &,
9340b57cec5SDimitry Andric EVT VT) const {
9350b57cec5SDimitry Andric return getHasAlu32() ? MVT::i32 : MVT::i64;
9360b57cec5SDimitry Andric }
9370b57cec5SDimitry Andric
getScalarShiftAmountTy(const DataLayout & DL,EVT VT) const9380b57cec5SDimitry 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
isLegalAddressingMode(const DataLayout & DL,const AddrMode & AM,Type * Ty,unsigned AS,Instruction * I) const943349cc55cSDimitry 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