24#include "llvm/IR/IntrinsicsBPF.h"
32#define DEBUG_TYPE "bpf-isel"
33#define PASS_NAME "BPF DAG->DAG Pattern Instruction Selection"
45 BPFDAGToDAGISel() =
delete;
56 void PreprocessISelDAG()
override;
58 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
60 std::vector<SDValue> &OutOps)
override;
64#include "BPFGenDAGISel.inc"
77 typedef std::vector<unsigned char> val_vec_type;
81 val_vec_type &Vals,
int Offset);
83 val_vec_type &Vals,
int Offset);
85 val_vec_type &Vals,
int Offset);
89 std::map<const void *, val_vec_type> cs_vals_;
100char BPFDAGToDAGISelLegacy::ID = 0;
109 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
110 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
119 if (CurDAG->isBaseWithConstantOffset(Addr)) {
124 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
126 Base = Addr.getOperand(0);
128 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
134 Offset = CurDAG->getTargetConstant(0,
DL, MVT::i64);
143 if (!CurDAG->isBaseWithConstantOffset(Addr))
151 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
155 Offset = CurDAG->getTargetConstant(CN->getSExtValue(),
DL, MVT::i64);
162bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
164 std::vector<SDValue> &OutOps) {
166 switch (ConstraintCode) {
169 case InlineAsm::ConstraintCode::m:
170 if (!SelectAddr(
Op, Op0, Op1))
176 SDValue AluOp = CurDAG->getTargetConstant(
ISD::ADD,
DL, MVT::i32);
177 OutOps.push_back(Op0);
178 OutOps.push_back(Op1);
179 OutOps.push_back(AluOp);
183void BPFDAGToDAGISel::Select(SDNode *Node) {
184 unsigned Opcode =
Node->getOpcode();
187 if (
Node->isMachineOpcode()) {
201 EVT VT =
Node->getValueType(0);
202 if (VT != MVT::i64 && VT != MVT::i32)
204 CurDAG->SelectNodeTo(Node, VT == MVT::i64 ? BPF::MOV_ri : BPF::MOV_ri_32,
205 VT, CurDAG->getTargetConstant(0, SDLoc(Node), VT));
209 case BPFISD::LOAD_STACK_ARG: {
210 SDValue Chain =
Node->getOperand(0);
213 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Node), MVT::i64);
214 EVT ValVT =
Node->getValueType(0);
215 CurDAG->SelectNodeTo(Node, BPF::LOAD_STACK_ARG_PSEUDO, ValVT, MVT::Other,
220 case BPFISD::STORE_STACK_ARG: {
221 SDValue Chain =
Node->getOperand(0);
224 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Node), MVT::i64);
225 SDValue Val =
Node->getOperand(2);
230 SDValue
Imm = CurDAG->getTargetConstant(ValCN->getSExtValue(),
231 SDLoc(Node), MVT::i64);
232 CurDAG->SelectNodeTo(Node, BPF::STORE_STACK_ARG_IMM_PSEUDO, MVT::Other,
235 CurDAG->SelectNodeTo(Node, BPF::STORE_STACK_ARG_PSEUDO, MVT::Other,
Off,
243 EVT VT =
Node->getValueType(0);
244 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
245 unsigned Opc = BPF::MOV_rr;
246 if (
Node->hasOneUse()) {
247 CurDAG->SelectNodeTo(Node,
Opc, VT, TFI);
250 ReplaceNode(Node, CurDAG->getMachineNode(
Opc, SDLoc(Node), VT, TFI));
259void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
267 bool to_replace =
false;
270 if (!
LD->getMemOperand()->getSize().hasValue())
277 SDNode *LDAddrNode =
LD->getOperand(1).getNode();
279 unsigned opcode = LDAddrNode->
getOpcode();
285 SDNode *OP1N =
OP1.getNode();
291 const GlobalAddressSDNode *GADN =
302 if (
const GlobalAddressSDNode *GADN =
304 to_replace = getConstantFieldValue(GADN, 0,
size, new_val.c);
324 SDValue NVal = CurDAG->getConstant(val,
DL,
LD->getValueType(0));
329 SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
330 SDValue To[] = {NVal, NVal};
331 CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
334 CurDAG->DeleteNode(Node);
337void BPFDAGToDAGISel::PreprocessISelDAG() {
346 E = CurDAG->allnodes_end();
348 SDNode *
Node = &*
I++;
349 unsigned Opcode =
Node->getOpcode();
351 PreprocessLoad(Node,
I);
353 PreprocessTrunc(Node,
I);
357bool BPFDAGToDAGISel::getConstantFieldValue(
const GlobalAddressSDNode *Node,
359 unsigned char *ByteSeq) {
362 if (!V || !
V->hasInitializer() || !
V->isConstant())
365 const Constant *Init =
V->getInitializer();
366 const DataLayout &
DL = CurDAG->getDataLayout();
369 auto it = cs_vals_.find(
static_cast<const void *
>(Init));
370 if (it != cs_vals_.end()) {
378 total_size =
DL.getTypeAllocSize(CA->getType()->getElementType()) *
379 CA->getNumOperands();
383 val_vec_type Vals(total_size, 0);
384 if (fillGenericConstant(
DL, Init, Vals, 0) ==
false)
386 cs_vals_[
static_cast<const void *
>(Init)] = Vals;
387 TmpVal = std::move(Vals);
395 uint16_t test_val = 0x2345;
396 if (
DL.isLittleEndian())
401 bool endian_match = test_buf.s == test_val;
403 ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[
Offset +
Size - 1 -
j];
408bool BPFDAGToDAGISel::fillGenericConstant(
const DataLayout &
DL,
426 Vals[
Offset + i] =
DL.isLittleEndian()
427 ? ((val >> (i * 8)) & 0xFF)
428 : ((val >> ((
Size - i - 1) * 8)) & 0xFF);
434 return fillConstantDataArray(
DL, CDA, Vals,
Offset);
437 return fillConstantArray(
DL, CA, Vals,
Offset);
440 return fillConstantStruct(
DL, CVS, Vals,
Offset);
445bool BPFDAGToDAGISel::fillConstantDataArray(
const DataLayout &
DL,
446 const ConstantDataArray *CDA,
447 val_vec_type &Vals,
int Offset) {
458bool BPFDAGToDAGISel::fillConstantArray(
const DataLayout &
DL,
459 const ConstantArray *CA,
460 val_vec_type &Vals,
int Offset) {
470bool BPFDAGToDAGISel::fillConstantStruct(
const DataLayout &
DL,
471 const ConstantStruct *CS,
472 val_vec_type &Vals,
int Offset) {
473 const StructLayout *Layout =
DL.getStructLayout(CS->
getType());
477 if (fillGenericConstant(
DL,
Field, Vals,
Offset + SizeSoFar) ==
false)
483void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
495 SDValue BaseV =
Node->getOperand(0);
502 if (!((IntNo == Intrinsic::bpf_load_byte && MaskV == 0xFF) ||
503 (IntNo == Intrinsic::bpf_load_half && MaskV == 0xFFFF) ||
504 (IntNo == Intrinsic::bpf_load_word && MaskV == 0xFFFFFFFF)))
511 CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
513 CurDAG->DeleteNode(Node);
517 return new BPFDAGToDAGISelLegacy(TM);
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
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 ...
OptimizedStructLayoutField Field
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
BPFISelDAGToDAGPass(BPFTargetMachine &TM)
ConstantArray - Constant Array Declarations.
An array constant whose element type is a simple 1/2/4/8-byte integer, bytes or float/double,...
LLVM_ABI Constant * getElementAsConstant(uint64_t i) const
Return a Constant for a specified index's element.
LLVM_ABI uint64_t getNumElements() const
Return the number of elements in the array or vector.
uint64_t getZExtValue() const
StructType * getType() const
Specialization - reduce amount of casting.
This is an important base class in LLVM.
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.
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
const SDValue & getOperand(unsigned i) const
unsigned getOpcode() const
Storage of either a normal Value address, or a select instruction together with a pair of addresses f...
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
virtual bool runOnMachineFunction(MachineFunction &mf)
ilist< SDNode >::iterator allnodes_iterator
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.
@ POISON
POISON - A poison node.
@ 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.
@ UNDEF
UNDEF - An undefined node.
@ 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...
NodeAddr< NodeBase * > Node
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.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)
Implement std::hash so that hash_code can be used in STL containers.