27#include "llvm/IR/IntrinsicsBPF.h"
36#define DEBUG_TYPE "bpf-isel"
37#define PASS_NAME "BPF DAG->DAG Pattern Instruction Selection"
49 BPFDAGToDAGISel() =
delete;
64 std::vector<SDValue> &OutOps)
override;
68#include "BPFGenDAGISel.inc"
81 typedef std::vector<unsigned char> val_vec_type;
85 val_vec_type &Vals,
int Offset);
87 val_vec_type &Vals,
int Offset);
89 val_vec_type &Vals,
int Offset);
93 std::map<const void *, val_vec_type> cs_vals_;
104char BPFDAGToDAGISelLegacy::ID = 0;
112 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr)) {
113 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
114 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
123 if (CurDAG->isBaseWithConstantOffset(
Addr)) {
124 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
125 if (isInt<16>(CN->getSExtValue())) {
127 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
128 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
132 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
138 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
147 if (!CurDAG->isBaseWithConstantOffset(
Addr))
151 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
152 if (isInt<16>(CN->getSExtValue())) {
154 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
155 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
159 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
166bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
168 std::vector<SDValue> &OutOps) {
170 switch (ConstraintCode) {
173 case InlineAsm::ConstraintCode::m:
174 if (!SelectAddr(
Op, Op0, Op1))
181 OutOps.push_back(Op0);
182 OutOps.push_back(Op1);
183 OutOps.push_back(AluOp);
188 unsigned Opcode =
Node->getOpcode();
191 if (
Node->isMachineOpcode()) {
201 unsigned IntNo =
Node->getConstantOperandVal(1);
203 case Intrinsic::bpf_load_byte:
204 case Intrinsic::bpf_load_half:
205 case Intrinsic::bpf_load_word: {
212 SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
213 Chain = CurDAG->getCopyToReg(Chain,
DL, R6Reg, Skb,
SDValue());
214 Node = CurDAG->UpdateNodeOperands(
Node, Chain, N1, R6Reg, N3);
222 int FI = cast<FrameIndexSDNode>(
Node)->getIndex();
223 EVT VT =
Node->getValueType(0);
224 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
225 unsigned Opc = BPF::MOV_rr;
226 if (
Node->hasOneUse()) {
227 CurDAG->SelectNodeTo(
Node, Opc, VT, TFI);
230 ReplaceNode(
Node, CurDAG->getMachineNode(Opc,
SDLoc(
Node), VT, TFI));
239void BPFDAGToDAGISel::PreprocessLoad(
SDNode *
Node,
247 bool to_replace =
false;
250 if (!
LD->getMemOperand()->getSize().hasValue())
254 if (!size || size > 8 || (size & (size - 1)) || !
LD->isSimple())
257 SDNode *LDAddrNode =
LD->getOperand(1).getNode();
259 unsigned opcode = LDAddrNode->
getOpcode();
276 getConstantFieldValue(GADN, CDN->
getZExtValue(), size, new_val.c);
283 dyn_cast<GlobalAddressSDNode>(
OP1.getNode()))
284 to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
302 LLVM_DEBUG(
dbgs() <<
"Replacing load of size " << size <<
" with constant "
304 SDValue NVal = CurDAG->getConstant(val,
DL,
LD->getValueType(0));
311 CurDAG->ReplaceAllUsesOfValuesWith(
From, To, 2);
314 CurDAG->DeleteNode(
Node);
317void BPFDAGToDAGISel::PreprocessISelDAG() {
326 E = CurDAG->allnodes_end();
329 unsigned Opcode =
Node->getOpcode();
331 PreprocessLoad(
Node,
I);
333 PreprocessTrunc(
Node,
I);
339 unsigned char *ByteSeq) {
342 if (!V || !
V->hasInitializer() || !
V->isConstant())
349 auto it = cs_vals_.find(
static_cast<const void *
>(
Init));
350 if (it != cs_vals_.end()) {
356 DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
358 total_size =
DL.getTypeAllocSize(CA->getType()->getElementType()) *
359 CA->getNumOperands();
363 val_vec_type Vals(total_size, 0);
364 if (fillGenericConstant(
DL,
Init, Vals, 0) ==
false)
366 cs_vals_[
static_cast<const void *
>(
Init)] = Vals;
367 TmpVal = std::move(Vals);
376 if (
DL.isLittleEndian())
381 bool endian_match = test_buf.s == test_val;
383 ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[
Offset +
Size - 1 - j];
388bool BPFDAGToDAGISel::fillGenericConstant(
const DataLayout &
DL,
393 if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
396 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
406 Vals[
Offset + i] =
DL.isLittleEndian()
407 ? ((val >> (i * 8)) & 0xFF)
408 : ((val >> ((
Size - i - 1) * 8)) & 0xFF);
414 return fillConstantDataArray(
DL, CDA, Vals,
Offset);
417 return fillConstantArray(
DL, CA, Vals,
Offset);
420 return fillConstantStruct(
DL, CVS, Vals,
Offset);
425bool BPFDAGToDAGISel::fillConstantDataArray(
const DataLayout &
DL,
427 val_vec_type &Vals,
int Offset) {
438bool BPFDAGToDAGISel::fillConstantArray(
const DataLayout &
DL,
440 val_vec_type &Vals,
int Offset) {
450bool BPFDAGToDAGISel::fillConstantStruct(
const DataLayout &
DL,
452 val_vec_type &Vals,
int Offset) {
457 if (fillGenericConstant(
DL,
Field, Vals,
Offset + SizeSoFar) ==
false)
463void BPFDAGToDAGISel::PreprocessTrunc(
SDNode *
Node,
482 if (!((IntNo == Intrinsic::bpf_load_byte && MaskV == 0xFF) ||
483 (IntNo == Intrinsic::bpf_load_half && MaskV == 0xFFFF) ||
484 (IntNo == Intrinsic::bpf_load_word && MaskV == 0xFFFFFFFF)))
491 CurDAG->ReplaceAllUsesWith(
SDValue(
Node, 0), BaseV);
493 CurDAG->DeleteNode(
Node);
497 return new BPFDAGToDAGISelLegacy(TM);
amdgpu AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
BlockVerifier::State From
This file contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
DEMANGLE_DUMP_METHOD void dump() const
ConstantArray - Constant Array Declarations.
An array constant whose element type is a simple 1/2/4/8-byte integer or float/double,...
unsigned getNumElements() const
Return the number of elements in the array or vector.
Constant * getElementAsConstant(unsigned i) const
Return a Constant for a specified index's element.
This is the shared class of boolean and integer constants.
uint64_t getZExtValue() const
StructType * getType() const
Specialization - reduce amount of casting.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
This class is used to represent ISD::LOAD nodes.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
unsigned getNumOperands() const
Return the number of values used by this operation.
const SDValue & getOperand(unsigned Num) const
uint64_t getConstantOperandVal(unsigned Num) const
Helper method returns the integer value of a ConstantSDNode operand.
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
unsigned getOpcode() const
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
virtual bool runOnMachineFunction(MachineFunction &mf)
ilist< SDNode >::iterator allnodes_iterator
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
Type * getType() const
All values are typed, get the type of this value.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ BUILTIN_OP_END
BUILTIN_OP_END - This must be the last enum value in this list.
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
void write16be(void *P, uint16_t V)
void write16le(void *P, uint16_t V)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)