LLVM 24.0.0git
BPFISelDAGToDAG.cpp
Go to the documentation of this file.
1//===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a DAG pattern matching instruction selector for BPF,
10// converting from a legalized dag to a BPF dag.
11//
12//===----------------------------------------------------------------------===//
13
14#include "BPF.h"
15#include "BPFSubtarget.h"
16#include "BPFTargetMachine.h"
22#include "llvm/IR/Constants.h"
24#include "llvm/IR/IntrinsicsBPF.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/Endian.h"
29
30using namespace llvm;
31
32#define DEBUG_TYPE "bpf-isel"
33#define PASS_NAME "BPF DAG->DAG Pattern Instruction Selection"
34
35// Instruction Selector Implementation
36namespace {
37
38class BPFDAGToDAGISel : public SelectionDAGISel {
39
40 /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can
41 /// make the right decision when generating code for different subtargets.
42 const BPFSubtarget *Subtarget;
43
44public:
45 BPFDAGToDAGISel() = delete;
46
47 explicit BPFDAGToDAGISel(BPFTargetMachine &TM)
48 : SelectionDAGISel(TM), Subtarget(nullptr) {}
49
50 bool runOnMachineFunction(MachineFunction &MF) override {
51 // Reset the subtarget each time through.
52 Subtarget = &MF.getSubtarget<BPFSubtarget>();
54 }
55
56 void PreprocessISelDAG() override;
57
58 bool SelectInlineAsmMemoryOperand(const SDValue &Op,
59 InlineAsm::ConstraintCode ConstraintCode,
60 std::vector<SDValue> &OutOps) override;
61
62private:
63// Include the pieces autogenerated from the target description.
64#include "BPFGenDAGISel.inc"
65
66 void Select(SDNode *N) override;
67
68 // Complex Pattern for address selection.
70 bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
71
72 // Node preprocessing cases
73 void PreprocessLoad(SDNode *Node, SelectionDAG::allnodes_iterator &I);
74 void PreprocessTrunc(SDNode *Node, SelectionDAG::allnodes_iterator &I);
75
76 // Find constants from a constant structure
77 typedef std::vector<unsigned char> val_vec_type;
78 bool fillGenericConstant(const DataLayout &DL, const Constant *CV,
79 val_vec_type &Vals, uint64_t Offset);
80 bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA,
81 val_vec_type &Vals, int Offset);
82 bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA,
83 val_vec_type &Vals, int Offset);
84 bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS,
85 val_vec_type &Vals, int Offset);
86 bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset,
87 uint64_t Size, unsigned char *ByteSeq);
88 // Mapping from ConstantStruct global value to corresponding byte-list values
89 std::map<const void *, val_vec_type> cs_vals_;
90};
91
92class BPFDAGToDAGISelLegacy : public SelectionDAGISelLegacy {
93public:
94 static char ID;
95 BPFDAGToDAGISelLegacy(BPFTargetMachine &TM)
96 : SelectionDAGISelLegacy(ID, std::make_unique<BPFDAGToDAGISel>(TM)) {}
97};
98} // namespace
99
100char BPFDAGToDAGISelLegacy::ID = 0;
101
102INITIALIZE_PASS(BPFDAGToDAGISelLegacy, DEBUG_TYPE, PASS_NAME, false, false)
103
104// ComplexPattern used on BPF Load/Store instructions
105bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
106 // if Address is FI, get the TargetFrameIndex.
107 SDLoc DL(Addr);
108 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
109 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
110 Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
111 return true;
112 }
113
114 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
115 Addr.getOpcode() == ISD::TargetGlobalAddress)
116 return false;
117
118 // Addresses of the form Addr+const or Addr|const
119 if (CurDAG->isBaseWithConstantOffset(Addr)) {
120 auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
121 if (isInt<16>(CN->getSExtValue())) {
122 // If the first operand is a FI, get the TargetFI Node
123 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
124 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
125 else
126 Base = Addr.getOperand(0);
127
128 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
129 return true;
130 }
131 }
132
133 Base = Addr;
134 Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
135 return true;
136}
137
138// ComplexPattern used on BPF FI instruction
139bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
140 SDValue &Offset) {
141 SDLoc DL(Addr);
142
143 if (!CurDAG->isBaseWithConstantOffset(Addr))
144 return false;
145
146 // Addresses of the form Addr+const or Addr|const
147 auto *CN = cast<ConstantSDNode>(Addr.getOperand(1));
148 if (isInt<16>(CN->getSExtValue())) {
149 // If the first operand is a FI, get the TargetFI Node
150 if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
151 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
152 else
153 return false;
154
155 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
156 return true;
157 }
158
159 return false;
160}
161
162bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
163 const SDValue &Op, InlineAsm::ConstraintCode ConstraintCode,
164 std::vector<SDValue> &OutOps) {
165 SDValue Op0, Op1;
166 switch (ConstraintCode) {
167 default:
168 return true;
169 case InlineAsm::ConstraintCode::m: // memory
170 if (!SelectAddr(Op, Op0, Op1))
171 return true;
172 break;
173 }
174
175 SDLoc DL(Op);
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);
180 return false;
181}
182
183void BPFDAGToDAGISel::Select(SDNode *Node) {
184 unsigned Opcode = Node->getOpcode();
185
186 // If we have a custom node, we already have selected!
187 if (Node->isMachineOpcode()) {
188 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n');
189 return;
190 }
191
192 // tablegen selection should be handled here.
193 switch (Opcode) {
194 default:
195 break;
196 case ISD::POISON:
197 case ISD::UNDEF: {
198 // IMPLICIT_DEF leaves the register as it is. The verifier rejects a read
199 // of a register that was not written, no matter what is done with the
200 // value.
201 EVT VT = Node->getValueType(0);
202 if (VT != MVT::i64 && VT != MVT::i32)
203 break;
204 CurDAG->SelectNodeTo(Node, VT == MVT::i64 ? BPF::MOV_ri : BPF::MOV_ri_32,
205 VT, CurDAG->getTargetConstant(0, SDLoc(Node), VT));
206 return;
207 }
208
209 case BPFISD::LOAD_STACK_ARG: {
210 SDValue Chain = Node->getOperand(0);
211 auto *CN = cast<ConstantSDNode>(Node->getOperand(1));
212 SDValue Off =
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,
216 Off, Chain);
217 return;
218 }
219
220 case BPFISD::STORE_STACK_ARG: {
221 SDValue Chain = Node->getOperand(0);
222 auto *CN = cast<ConstantSDNode>(Node->getOperand(1));
223 SDValue Off =
224 CurDAG->getTargetConstant(CN->getSExtValue(), SDLoc(Node), MVT::i64);
225 SDValue Val = Node->getOperand(2);
226
227 // Use store-immediate when the value is a constant that fits in 32 bits.
228 if (auto *ValCN = dyn_cast<ConstantSDNode>(Val);
229 ValCN && Subtarget->hasStoreImm() && isInt<32>(ValCN->getSExtValue())) {
230 SDValue Imm = CurDAG->getTargetConstant(ValCN->getSExtValue(),
231 SDLoc(Node), MVT::i64);
232 CurDAG->SelectNodeTo(Node, BPF::STORE_STACK_ARG_IMM_PSEUDO, MVT::Other,
233 Off, Imm, Chain);
234 } else {
235 CurDAG->SelectNodeTo(Node, BPF::STORE_STACK_ARG_PSEUDO, MVT::Other, Off,
236 Val, Chain);
237 }
238 return;
239 }
240
241 case ISD::FrameIndex: {
242 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
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);
248 return;
249 }
250 ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI));
251 return;
252 }
253 }
254
255 // Select the default instruction
256 SelectCode(Node);
257}
258
259void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
261 union {
262 uint8_t c[8];
263 uint16_t s;
264 uint32_t i;
265 uint64_t d;
266 } new_val; // hold up the constant values replacing loads.
267 bool to_replace = false;
268 SDLoc DL(Node);
269 const LoadSDNode *LD = cast<LoadSDNode>(Node);
270 if (!LD->getMemOperand()->getSize().hasValue())
271 return;
272 uint64_t size = LD->getMemOperand()->getSize().getValue();
273
274 if (!size || size > 8 || (size & (size - 1)) || !LD->isSimple())
275 return;
276
277 SDNode *LDAddrNode = LD->getOperand(1).getNode();
278 // Match LDAddr against either global_addr or (global_addr + offset)
279 unsigned opcode = LDAddrNode->getOpcode();
280 if (opcode == ISD::ADD) {
281 SDValue OP1 = LDAddrNode->getOperand(0);
282 SDValue OP2 = LDAddrNode->getOperand(1);
283
284 // We want to find the pattern global_addr + offset
285 SDNode *OP1N = OP1.getNode();
286 if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END || OP1N->getNumOperands() == 0)
287 return;
288
289 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
290
291 const GlobalAddressSDNode *GADN =
293 const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
294 if (GADN && CDN)
295 to_replace =
296 getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val.c);
297 } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
298 LDAddrNode->getNumOperands() > 0) {
299 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n');
300
301 SDValue OP1 = LDAddrNode->getOperand(0);
302 if (const GlobalAddressSDNode *GADN =
304 to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
305 }
306
307 if (!to_replace)
308 return;
309
310 // replacing the old with a new value
311 uint64_t val;
312 if (size == 1)
313 val = new_val.c[0];
314 else if (size == 2)
315 val = new_val.s;
316 else if (size == 4)
317 val = new_val.i;
318 else {
319 val = new_val.d;
320 }
321
322 LLVM_DEBUG(dbgs() << "Replacing load of size " << size << " with constant "
323 << val << '\n');
324 SDValue NVal = CurDAG->getConstant(val, DL, LD->getValueType(0));
325
326 // After replacement, the current node is dead, we need to
327 // go backward one step to make iterator still work
328 I--;
329 SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
330 SDValue To[] = {NVal, NVal};
331 CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
332 I++;
333 // It is safe to delete node now
334 CurDAG->DeleteNode(Node);
335}
336
337void BPFDAGToDAGISel::PreprocessISelDAG() {
338 // Iterate through all nodes, interested in the following case:
339 //
340 // . loads from ConstantStruct or ConstantArray of constructs
341 // which can be turns into constant itself, with this we can
342 // avoid reading from read-only section at runtime.
343 //
344 // . Removing redundant AND for intrinsic narrow loads.
345 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
346 E = CurDAG->allnodes_end();
347 I != E;) {
348 SDNode *Node = &*I++;
349 unsigned Opcode = Node->getOpcode();
350 if (Opcode == ISD::LOAD)
351 PreprocessLoad(Node, I);
352 else if (Opcode == ISD::AND)
353 PreprocessTrunc(Node, I);
354 }
355}
356
357bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
359 unsigned char *ByteSeq) {
360 const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
361
362 if (!V || !V->hasInitializer() || !V->isConstant())
363 return false;
364
365 const Constant *Init = V->getInitializer();
366 const DataLayout &DL = CurDAG->getDataLayout();
367 val_vec_type TmpVal;
368
369 auto it = cs_vals_.find(static_cast<const void *>(Init));
370 if (it != cs_vals_.end()) {
371 TmpVal = it->second;
372 } else {
373 uint64_t total_size = 0;
374 if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
375 total_size =
376 DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
377 else if (const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
378 total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) *
379 CA->getNumOperands();
380 else
381 return false;
382
383 val_vec_type Vals(total_size, 0);
384 if (fillGenericConstant(DL, Init, Vals, 0) == false)
385 return false;
386 cs_vals_[static_cast<const void *>(Init)] = Vals;
387 TmpVal = std::move(Vals);
388 }
389
390 // test whether host endianness matches target
391 union {
392 uint8_t c[2];
393 uint16_t s;
394 } test_buf;
395 uint16_t test_val = 0x2345;
396 if (DL.isLittleEndian())
397 support::endian::write16le(test_buf.c, test_val);
398 else
399 support::endian::write16be(test_buf.c, test_val);
400
401 bool endian_match = test_buf.s == test_val;
402 for (uint64_t i = Offset, j = 0; i < Offset + Size; i++, j++)
403 ByteSeq[j] = endian_match ? TmpVal[i] : TmpVal[Offset + Size - 1 - j];
404
405 return true;
406}
407
408bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL,
409 const Constant *CV,
410 val_vec_type &Vals, uint64_t Offset) {
411 uint64_t Size = DL.getTypeAllocSize(CV->getType());
412
414 return true; // already done
415
416 if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
417 uint64_t val = CI->getZExtValue();
418 LLVM_DEBUG(dbgs() << "Byte array at offset " << Offset << " with value "
419 << val << '\n');
420
421 if (Size > 8 || (Size & (Size - 1)))
422 return false;
423
424 // Store based on target endian
425 for (uint64_t i = 0; i < Size; ++i) {
426 Vals[Offset + i] = DL.isLittleEndian()
427 ? ((val >> (i * 8)) & 0xFF)
428 : ((val >> ((Size - i - 1) * 8)) & 0xFF);
429 }
430 return true;
431 }
432
433 if (const ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(CV))
434 return fillConstantDataArray(DL, CDA, Vals, Offset);
435
436 if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV))
437 return fillConstantArray(DL, CA, Vals, Offset);
438
439 if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
440 return fillConstantStruct(DL, CVS, Vals, Offset);
441
442 return false;
443}
444
445bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL,
446 const ConstantDataArray *CDA,
447 val_vec_type &Vals, int Offset) {
448 for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) {
449 if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) ==
450 false)
451 return false;
452 Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType());
453 }
454
455 return true;
456}
457
458bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL,
459 const ConstantArray *CA,
460 val_vec_type &Vals, int Offset) {
461 for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
462 if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false)
463 return false;
464 Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
465 }
466
467 return true;
468}
469
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());
474 for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
475 const Constant *Field = CS->getOperand(i);
476 uint64_t SizeSoFar = Layout->getElementOffset(i);
477 if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false)
478 return false;
479 }
480 return true;
481}
482
483void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
485 ConstantSDNode *MaskN = dyn_cast<ConstantSDNode>(Node->getOperand(1));
486 if (!MaskN)
487 return;
488
489 // The Reg operand should be a virtual register, which is defined
490 // outside the current basic block. DAG combiner has done a pretty
491 // good job in removing truncating inside a single basic block except
492 // when the Reg operand comes from bpf_load_[byte | half | word] for
493 // which the generic optimizer doesn't understand their results are
494 // zero extended.
495 SDValue BaseV = Node->getOperand(0);
496 if (BaseV.getOpcode() != ISD::INTRINSIC_W_CHAIN)
497 return;
498
499 unsigned IntNo = BaseV->getConstantOperandVal(1);
500 uint64_t MaskV = MaskN->getZExtValue();
501
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)))
505 return;
506
507 LLVM_DEBUG(dbgs() << "Remove the redundant AND operation in: ";
508 Node->dump(); dbgs() << '\n');
509
510 I--;
511 CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
512 I++;
513 CurDAG->DeleteNode(Node);
514}
515
517 return new BPFDAGToDAGISelLegacy(TM);
518}
519
uint64_t uint64_t
uint64_t Imm
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...
#define DEBUG_TYPE
#define I(x, y, z)
Definition MD5.cpp:57
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)
Definition PassSupport.h:56
#define LLVM_DEBUG(...)
Definition Debug.h:119
#define PASS_NAME
BPFISelDAGToDAGPass(BPFTargetMachine &TM)
bool hasStoreImm() const
ConstantArray - Constant Array Declarations.
Definition Constants.h:590
An array constant whose element type is a simple 1/2/4/8-byte integer, bytes or float/double,...
Definition Constants.h:865
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.
Definition Constants.h:661
This is an important base class in LLVM.
Definition Constant.h:44
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:312
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
Definition DataLayout.h:774
Value * getOperand(unsigned i) const
Definition User.h:207
unsigned getNumOperands() const
Definition User.h:229
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
@ POISON
POISON - A poison node.
Definition ISDOpcodes.h:238
@ ADD
Simple integer binary arithmetic operators.
Definition ISDOpcodes.h:266
@ 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.
@ TargetExternalSymbol
Definition ISDOpcodes.h:192
@ UNDEF
UNDEF - An undefined node.
Definition ISDOpcodes.h:235
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
Definition ISDOpcodes.h:187
@ AND
Bitwise operators - logical and, logical or, logical xor.
Definition ISDOpcodes.h:757
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
Definition ISDOpcodes.h:215
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
void write16be(void *P, uint16_t V)
Definition Endian.h:461
void write16le(void *P, uint16_t V)
Definition Endian.h:452
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
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.
Definition STLExtras.h:1685
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:166
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
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...
Definition Casting.h:547
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
FunctionPass * createBPFISelDag(BPFTargetMachine &TM)
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N