36 #define DEBUG_TYPE "bpf-isel" 54 return "BPF DAG->DAG Pattern Instruction Selection";
63 void PreprocessISelDAG()
override;
65 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
unsigned ConstraintCode,
66 std::vector<SDValue> &OutOps)
override;
71 #include "BPFGenDAGISel.inc" 81 void PreprocessCopyToReg(
SDNode *Node);
85 typedef std::vector<unsigned char> val_vec_type;
87 val_vec_type &Vals, uint64_t Offset);
89 val_vec_type &Vals,
int Offset);
91 val_vec_type &Vals,
int Offset);
93 val_vec_type &Vals,
int Offset);
95 uint64_t
Size,
unsigned char *ByteSeq);
96 bool checkLoadDef(
unsigned DefReg,
unsigned match_load_op);
99 std::map<const void *, val_vec_type> cs_vals_;
101 std::map<unsigned, unsigned> load_to_vreg_;
112 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(),
MVT::i64);
113 Offset = CurDAG->getTargetConstant(0, DL,
MVT::i64);
122 if (CurDAG->isBaseWithConstantOffset(Addr)) {
128 dyn_cast<FrameIndexSDNode>(Addr.
getOperand(0)))
129 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(),
MVT::i64);
139 Offset = CurDAG->getTargetConstant(0, DL,
MVT::i64);
148 if (!CurDAG->isBaseWithConstantOffset(Addr))
157 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(),
MVT::i64);
168 bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
169 const SDValue &
Op,
unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
171 switch (ConstraintCode) {
175 if (!SelectAddr(Op, Op0, Op1))
182 OutOps.push_back(Op0);
183 OutOps.push_back(Op1);
184 OutOps.push_back(AluOp);
205 errs() <<
"Error at line " << DL.
getLine() <<
": ";
208 errs() <<
"Unsupport signed division for DAG: ";
210 errs() <<
"Please convert to unsigned div/mod.\n";
214 unsigned IntNo = cast<ConstantSDNode>(Node->
getOperand(1))->getZExtValue();
226 Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb,
SDValue());
227 Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
235 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
237 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
238 unsigned Opc = BPF::MOV_rr;
240 CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
243 ReplaceNode(Node, CurDAG->getMachineNode(Opc,
SDLoc(Node), VT, TFI));
252 void BPFDAGToDAGISel::PreprocessLoad(
SDNode *Node,
260 bool to_replace =
false;
265 if (!size || size > 8 || (size & (size - 1)))
270 unsigned opcode = LDAddrNode->
getOpcode();
287 getConstantFieldValue(GADN, CDN->getZExtValue(),
size, new_val.c);
294 dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
295 to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
313 LLVM_DEBUG(
dbgs() <<
"Replacing load of size " << size <<
" with constant " 322 CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
325 CurDAG->DeleteNode(Node);
328 void BPFDAGToDAGISel::PreprocessISelDAG() {
349 curr_func_ = FuncInfo->Fn;
350 }
else if (curr_func_ != FuncInfo->Fn) {
351 load_to_vreg_.clear();
352 curr_func_ = FuncInfo->Fn;
356 E = CurDAG->allnodes_end();
361 PreprocessLoad(Node, I);
363 PreprocessCopyToReg(Node);
365 PreprocessTrunc(Node, I);
370 uint64_t Offset, uint64_t
Size,
371 unsigned char *ByteSeq) {
378 const DataLayout &DL = CurDAG->getDataLayout();
381 auto it = cs_vals_.find(static_cast<const void *>(Init));
382 if (it != cs_vals_.end()) {
385 uint64_t total_size = 0;
389 else if (
const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
391 CA->getNumOperands();
395 val_vec_type Vals(total_size, 0);
396 if (fillGenericConstant(DL, Init, Vals, 0) ==
false)
398 cs_vals_[
static_cast<const void *
>(Init)] = Vals;
399 TmpVal = std::move(Vals);
407 uint16_t test_val = 0x2345;
413 bool endian_match = test_buf.s == test_val;
414 for (uint64_t i = Offset, j = 0; i < Offset +
Size; i++, j++)
415 ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
420 bool BPFDAGToDAGISel::fillGenericConstant(
const DataLayout &DL,
422 val_vec_type &Vals, uint64_t Offset) {
425 if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
428 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
429 uint64_t val = CI->getZExtValue();
430 LLVM_DEBUG(
dbgs() <<
"Byte array at offset " << Offset <<
" with value " 433 if (Size > 8 || (Size & (Size - 1)))
437 for (uint64_t i = 0; i <
Size; ++i) {
439 ? ((val >> (i * 8)) & 0xFF)
440 : ((val >> ((Size - i - 1) * 8)) & 0xFF);
446 return fillConstantDataArray(DL, CDA, Vals, Offset);
449 return fillConstantArray(DL, CA, Vals, Offset);
452 return fillConstantStruct(DL, CVS, Vals, Offset);
457 bool BPFDAGToDAGISel::fillConstantDataArray(
const DataLayout &DL,
459 val_vec_type &Vals,
int Offset) {
470 bool BPFDAGToDAGISel::fillConstantArray(
const DataLayout &DL,
472 val_vec_type &Vals,
int Offset) {
482 bool BPFDAGToDAGISel::fillConstantStruct(
const DataLayout &DL,
484 val_vec_type &Vals,
int Offset) {
489 if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) ==
false)
495 void BPFDAGToDAGISel::PreprocessCopyToReg(
SDNode *Node) {
505 unsigned mem_load_op = 0;
510 mem_load_op = BPF::LDW;
513 mem_load_op = BPF::LDH;
516 mem_load_op = BPF::LDB;
523 load_to_vreg_[RegN->
getReg()] = mem_load_op;
526 void BPFDAGToDAGISel::PreprocessTrunc(
SDNode *Node,
540 unsigned IntNo = cast<ConstantSDNode>(BaseV->
getOperand(1))->getZExtValue();
552 CurDAG->ReplaceAllUsesWith(
SDValue(Node, 0), BaseV);
554 CurDAG->DeleteNode(Node);
563 unsigned match_load_op = 0;
568 match_load_op = BPF::LDW;
571 match_load_op = BPF::LDH;
574 match_load_op = BPF::LDB;
582 unsigned AndOpReg = RegN->
getReg();
591 for (
auto &
MI : *MBB) {
592 for (
unsigned i = 0; i <
MI.getNumOperands(); ++i) {
604 if (MII ==
nullptr) {
606 if (!checkLoadDef(AndOpReg, match_load_op))
615 unsigned PrevReg = -1;
624 if (!checkLoadDef(PrevReg, match_load_op))
634 CurDAG->ReplaceAllUsesWith(
SDValue(Node, 0), BaseV);
636 CurDAG->DeleteNode(Node);
639 bool BPFDAGToDAGISel::checkLoadDef(
unsigned DefReg,
unsigned match_load_op) {
640 auto it = load_to_vreg_.find(DefReg);
641 if (it == load_to_vreg_.end())
644 return it->second == match_load_op;
648 return new BPFDAGToDAGISel(TM);
BUILTIN_OP_END - This must be the last enum value in this list.
A parsed version of the target data layout string in and methods for querying it. ...
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
const GlobalValue * getGlobal() const
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
static unsigned virtReg2Index(unsigned Reg)
Convert a virtual register number to a 0-based index.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
This class represents lattice values for constants.
Constant * getElementAsConstant(unsigned i) const
Return a Constant for a specified index's element.
const StructLayout * getStructLayout(StructType *Ty) const
Returns a StructLayout object, indicating the alignment of the struct, its size, and the offsets of i...
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
unsigned getReg() const
getReg - Returns the register number.
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
uint64_t getSize() const
Return the size in bytes of the memory reference.
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
constexpr bool isInt< 16 >(int64_t x)
SDNode * getNode() const
get the SDNode which holds the desired result
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const DebugLoc & getDebugLoc() const
Return the source location info.
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
bool hasOneUse() const
Return true if there is exactly one use of this node.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
void write16le(void *P, uint16_t V)
unsigned getNumOperands() const
Retuns the total number of operands.
Printable printReg(unsigned Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
CopyToReg - This node has three operands: a chain, a register number to set to this value...
bool runOnMachineFunction(MachineFunction &MF) override
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
int64_t getSExtValue() const
Type * getType() const
All values are typed, get the type of this value.
Simple integer binary arithmetic operators.
bool isLittleEndian() const
Layout endianness...
Value * getOperand(unsigned i) const
An array constant whose element type is a simple 1/2/4/8-byte integer or float/double, and whose elements are just simple data values (i.e.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
const SDValue & getOperand(unsigned Num) const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
FunctionPass class - This class is used to implement most global optimizations.
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode...
unsigned getNumOperands() const
Return the number of values used by this operation.
void dump() const
Dump this node, for debugging.
Iterator for intrusive lists based on ilist_node.
unsigned getNumOperands() const
This is the shared class of boolean and integer constants.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
BlockVerifier::State From
MachineOperand class - Representation of each machine instruction operand.
uint64_t getSizeInBytes() const
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
ConstantArray - Constant Array Declarations.
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Representation of each machine instruction.
void write16be(void *P, uint16_t V)
Bitwise operators - logical and, logical or, logical xor.
uint64_t getElementOffset(unsigned Idx) const
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getOpcode() const
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void print(raw_ostream &OS, const SelectionDAG *G=nullptr) const
bool hasInitializer() const
Definitions have initializers, declarations don't.
StringRef - Represent a constant reference to a string, i.e.
unsigned getNumElements() const
Return the number of elements in the array or vector.
const SDValue & getOperand(unsigned i) const
uint64_t getZExtValue() const
const MachineOperand & getOperand(unsigned i) const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation...
StructType * getType() const
Specialization - reduce amount of casting.
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)
This class is used to represent ISD::LOAD nodes.