27#include "llvm/IR/IntrinsicsBPF.h"
36#define DEBUG_TYPE "bpf-isel"
37#define PASS_NAME "BPF DAG->DAG Pattern Instruction Selection"
51 BPFDAGToDAGISel() =
delete;
66 std::vector<SDValue> &OutOps)
override;
70#include "BPFGenDAGISel.inc"
83 typedef std::vector<unsigned char> val_vec_type;
87 val_vec_type &Vals,
int Offset);
89 val_vec_type &Vals,
int Offset);
91 val_vec_type &Vals,
int Offset);
95 std::map<const void *, val_vec_type> cs_vals_;
99char BPFDAGToDAGISel::ID = 0;
107 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr)) {
108 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
109 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
118 if (CurDAG->isBaseWithConstantOffset(
Addr)) {
119 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
120 if (isInt<16>(CN->getSExtValue())) {
122 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
123 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
127 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
133 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
142 if (!CurDAG->isBaseWithConstantOffset(
Addr))
146 auto *CN = cast<ConstantSDNode>(
Addr.getOperand(1));
147 if (isInt<16>(CN->getSExtValue())) {
149 if (
auto *FIN = dyn_cast<FrameIndexSDNode>(
Addr.getOperand(0)))
150 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
154 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
161bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
163 std::vector<SDValue> &OutOps) {
165 switch (ConstraintCode) {
168 case InlineAsm::ConstraintCode::m:
169 if (!SelectAddr(
Op, Op0, Op1))
176 OutOps.push_back(Op0);
177 OutOps.push_back(Op1);
178 OutOps.push_back(AluOp);
183 unsigned Opcode =
Node->getOpcode();
186 if (
Node->isMachineOpcode()) {
196 if (!Subtarget->hasSdivSmod()) {
200 errs() <<
"Error at line " <<
DL.getLine() <<
": ";
203 errs() <<
"Unsupport signed division for DAG: ";
205 errs() <<
"Please convert to unsigned div/mod.\n";
210 unsigned IntNo = cast<ConstantSDNode>(
Node->getOperand(1))->getZExtValue();
212 case Intrinsic::bpf_load_byte:
213 case Intrinsic::bpf_load_half:
214 case Intrinsic::bpf_load_word: {
221 SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
222 Chain = CurDAG->getCopyToReg(Chain,
DL, R6Reg, Skb,
SDValue());
223 Node = CurDAG->UpdateNodeOperands(
Node, Chain, N1, R6Reg, N3);
231 int FI = cast<FrameIndexSDNode>(
Node)->getIndex();
232 EVT VT =
Node->getValueType(0);
233 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
234 unsigned Opc = BPF::MOV_rr;
235 if (
Node->hasOneUse()) {
236 CurDAG->SelectNodeTo(
Node, Opc, VT, TFI);
239 ReplaceNode(
Node, CurDAG->getMachineNode(Opc,
SDLoc(
Node), VT, TFI));
248void BPFDAGToDAGISel::PreprocessLoad(
SDNode *
Node,
256 bool to_replace =
false;
261 if (!size || size > 8 || (size & (size - 1)) || !
LD->isSimple())
264 SDNode *LDAddrNode =
LD->getOperand(1).getNode();
266 unsigned opcode = LDAddrNode->
getOpcode();
283 getConstantFieldValue(GADN, CDN->
getZExtValue(), size, new_val.c);
290 dyn_cast<GlobalAddressSDNode>(
OP1.getNode()))
291 to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
309 LLVM_DEBUG(
dbgs() <<
"Replacing load of size " << size <<
" with constant "
311 SDValue NVal = CurDAG->getConstant(val,
DL,
LD->getValueType(0));
318 CurDAG->ReplaceAllUsesOfValuesWith(
From, To, 2);
321 CurDAG->DeleteNode(
Node);
324void BPFDAGToDAGISel::PreprocessISelDAG() {
333 E = CurDAG->allnodes_end();
336 unsigned Opcode =
Node->getOpcode();
338 PreprocessLoad(
Node,
I);
340 PreprocessTrunc(
Node,
I);
346 unsigned char *ByteSeq) {
349 if (!V || !
V->hasInitializer() || !
V->isConstant())
356 auto it = cs_vals_.find(
static_cast<const void *
>(
Init));
357 if (it != cs_vals_.end()) {
363 DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
365 total_size =
DL.getTypeAllocSize(CA->getType()->getElementType()) *
366 CA->getNumOperands();
370 val_vec_type Vals(total_size, 0);
371 if (fillGenericConstant(
DL,
Init, Vals, 0) ==
false)
373 cs_vals_[
static_cast<const void *
>(
Init)] = Vals;
374 TmpVal = std::move(Vals);
383 if (
DL.isLittleEndian())
388 bool endian_match = test_buf.s == test_val;
390 ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[
Offset +
Size - 1 - j];
395bool BPFDAGToDAGISel::fillGenericConstant(
const DataLayout &
DL,
400 if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
403 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
413 Vals[
Offset + i] =
DL.isLittleEndian()
414 ? ((val >> (i * 8)) & 0xFF)
415 : ((val >> ((
Size - i - 1) * 8)) & 0xFF);
421 return fillConstantDataArray(
DL, CDA, Vals,
Offset);
424 return fillConstantArray(
DL, CA, Vals,
Offset);
427 return fillConstantStruct(
DL, CVS, Vals,
Offset);
432bool BPFDAGToDAGISel::fillConstantDataArray(
const DataLayout &
DL,
434 val_vec_type &Vals,
int Offset) {
445bool BPFDAGToDAGISel::fillConstantArray(
const DataLayout &
DL,
447 val_vec_type &Vals,
int Offset) {
457bool BPFDAGToDAGISel::fillConstantStruct(
const DataLayout &
DL,
459 val_vec_type &Vals,
int Offset) {
464 if (fillGenericConstant(
DL,
Field, Vals,
Offset + SizeSoFar) ==
false)
470void BPFDAGToDAGISel::PreprocessTrunc(
SDNode *
Node,
486 unsigned IntNo = cast<ConstantSDNode>(BaseV->
getOperand(1))->getZExtValue();
489 if (!((IntNo == Intrinsic::bpf_load_byte && MaskV == 0xFF) ||
490 (IntNo == Intrinsic::bpf_load_half && MaskV == 0xFFFF) ||
491 (IntNo == Intrinsic::bpf_load_word && MaskV == 0xFFFFFFFF)))
498 CurDAG->ReplaceAllUsesWith(
SDValue(
Node, 0), BaseV);
500 CurDAG->DeleteNode(
Node);
504 return new BPFDAGToDAGISel(
TM);
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu AMDGPU Register Bank Select
BlockVerifier::State From
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 ...
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
void print(OutputBuffer &OB) const
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
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...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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.
Iterator for intrusive lists based on ilist_node.
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.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)