1 //===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF ----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines a DAG pattern matching instruction selector for BPF,
10 // converting from a legalized dag to a BPF dag.
12 //===----------------------------------------------------------------------===//
15 #include "BPFRegisterInfo.h"
16 #include "BPFSubtarget.h"
17 #include "BPFTargetMachine.h"
18 #include "llvm/CodeGen/FunctionLoweringInfo.h"
19 #include "llvm/CodeGen/MachineConstantPool.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/SelectionDAGISel.h"
25 #include "llvm/IR/Constants.h"
26 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/IR/IntrinsicsBPF.h"
28 #include "llvm/Support/Debug.h"
29 #include "llvm/Support/Endian.h"
30 #include "llvm/Support/ErrorHandling.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
36 #define DEBUG_TYPE "bpf-isel"
37 #define PASS_NAME "BPF DAG->DAG Pattern Instruction Selection"
39 // Instruction Selector Implementation
42 class BPFDAGToDAGISel
: public SelectionDAGISel
{
44 /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can
45 /// make the right decision when generating code for different subtargets.
46 const BPFSubtarget
*Subtarget
;
49 BPFDAGToDAGISel() = delete;
51 explicit BPFDAGToDAGISel(BPFTargetMachine
&TM
)
52 : SelectionDAGISel(TM
), Subtarget(nullptr) {}
54 bool runOnMachineFunction(MachineFunction
&MF
) override
{
55 // Reset the subtarget each time through.
56 Subtarget
= &MF
.getSubtarget
<BPFSubtarget
>();
57 return SelectionDAGISel::runOnMachineFunction(MF
);
60 void PreprocessISelDAG() override
;
62 bool SelectInlineAsmMemoryOperand(const SDValue
&Op
,
63 InlineAsm::ConstraintCode ConstraintCode
,
64 std::vector
<SDValue
> &OutOps
) override
;
67 // Include the pieces autogenerated from the target description.
68 #include "BPFGenDAGISel.inc"
70 void Select(SDNode
*N
) override
;
72 // Complex Pattern for address selection.
73 bool SelectAddr(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
74 bool SelectFIAddr(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
);
76 // Node preprocessing cases
77 void PreprocessLoad(SDNode
*Node
, SelectionDAG::allnodes_iterator
&I
);
78 void PreprocessTrunc(SDNode
*Node
, SelectionDAG::allnodes_iterator
&I
);
80 // Find constants from a constant structure
81 typedef std::vector
<unsigned char> val_vec_type
;
82 bool fillGenericConstant(const DataLayout
&DL
, const Constant
*CV
,
83 val_vec_type
&Vals
, uint64_t Offset
);
84 bool fillConstantDataArray(const DataLayout
&DL
, const ConstantDataArray
*CDA
,
85 val_vec_type
&Vals
, int Offset
);
86 bool fillConstantArray(const DataLayout
&DL
, const ConstantArray
*CA
,
87 val_vec_type
&Vals
, int Offset
);
88 bool fillConstantStruct(const DataLayout
&DL
, const ConstantStruct
*CS
,
89 val_vec_type
&Vals
, int Offset
);
90 bool getConstantFieldValue(const GlobalAddressSDNode
*Node
, uint64_t Offset
,
91 uint64_t Size
, unsigned char *ByteSeq
);
92 // Mapping from ConstantStruct global value to corresponding byte-list values
93 std::map
<const void *, val_vec_type
> cs_vals_
;
96 class BPFDAGToDAGISelLegacy
: public SelectionDAGISelLegacy
{
99 BPFDAGToDAGISelLegacy(BPFTargetMachine
&TM
)
100 : SelectionDAGISelLegacy(ID
, std::make_unique
<BPFDAGToDAGISel
>(TM
)) {}
104 char BPFDAGToDAGISelLegacy::ID
= 0;
106 INITIALIZE_PASS(BPFDAGToDAGISelLegacy
, DEBUG_TYPE
, PASS_NAME
, false, false)
108 // ComplexPattern used on BPF Load/Store instructions
109 bool BPFDAGToDAGISel::SelectAddr(SDValue Addr
, SDValue
&Base
, SDValue
&Offset
) {
110 // if Address is FI, get the TargetFrameIndex.
112 if (auto *FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
)) {
113 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i64
);
114 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i64
);
118 if (Addr
.getOpcode() == ISD::TargetExternalSymbol
||
119 Addr
.getOpcode() == ISD::TargetGlobalAddress
)
122 // Addresses of the form Addr+const or Addr|const
123 if (CurDAG
->isBaseWithConstantOffset(Addr
)) {
124 auto *CN
= cast
<ConstantSDNode
>(Addr
.getOperand(1));
125 if (isInt
<16>(CN
->getSExtValue())) {
126 // If the first operand is a FI, get the TargetFI Node
127 if (auto *FIN
= dyn_cast
<FrameIndexSDNode
>(Addr
.getOperand(0)))
128 Base
= CurDAG
->getTargetFrameIndex(FIN
->getIndex(), MVT::i64
);
130 Base
= Addr
.getOperand(0);
132 Offset
= CurDAG
->getTargetConstant(CN
->getSExtValue(), DL
, MVT::i64
);
138 Offset
= CurDAG
->getTargetConstant(0, DL
, MVT::i64
);
142 // ComplexPattern used on BPF FI instruction
143 bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr
, SDValue
&Base
,
147 if (!CurDAG
->isBaseWithConstantOffset(Addr
))
150 // Addresses of the form Addr+const or Addr|const
151 auto *CN
= cast
<ConstantSDNode
>(Addr
.getOperand(1));
152 if (isInt
<16>(CN
->getSExtValue())) {
153 // If the first operand is a FI, get the TargetFI Node
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
);
166 bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
167 const SDValue
&Op
, InlineAsm::ConstraintCode ConstraintCode
,
168 std::vector
<SDValue
> &OutOps
) {
170 switch (ConstraintCode
) {
173 case InlineAsm::ConstraintCode::m
: // memory
174 if (!SelectAddr(Op
, Op0
, Op1
))
180 SDValue AluOp
= CurDAG
->getTargetConstant(ISD::ADD
, DL
, MVT::i32
);
181 OutOps
.push_back(Op0
);
182 OutOps
.push_back(Op1
);
183 OutOps
.push_back(AluOp
);
187 void BPFDAGToDAGISel::Select(SDNode
*Node
) {
188 unsigned Opcode
= Node
->getOpcode();
190 // If we have a custom node, we already have selected!
191 if (Node
->isMachineOpcode()) {
192 LLVM_DEBUG(dbgs() << "== "; Node
->dump(CurDAG
); dbgs() << '\n');
196 // tablegen selection should be handled here.
200 case ISD::INTRINSIC_W_CHAIN
: {
201 unsigned IntNo
= Node
->getConstantOperandVal(1);
203 case Intrinsic::bpf_load_byte
:
204 case Intrinsic::bpf_load_half
:
205 case Intrinsic::bpf_load_word
: {
207 SDValue Chain
= Node
->getOperand(0);
208 SDValue N1
= Node
->getOperand(1);
209 SDValue Skb
= Node
->getOperand(2);
210 SDValue N3
= Node
->getOperand(3);
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
);
221 case ISD::FrameIndex
: {
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
));
235 // Select the default instruction
239 void BPFDAGToDAGISel::PreprocessLoad(SDNode
*Node
,
240 SelectionDAG::allnodes_iterator
&I
) {
246 } new_val
; // hold up the constant values replacing loads.
247 bool to_replace
= false;
249 const LoadSDNode
*LD
= cast
<LoadSDNode
>(Node
);
250 if (!LD
->getMemOperand()->getSize().hasValue())
252 uint64_t size
= LD
->getMemOperand()->getSize().getValue();
254 if (!size
|| size
> 8 || (size
& (size
- 1)) || !LD
->isSimple())
257 SDNode
*LDAddrNode
= LD
->getOperand(1).getNode();
258 // Match LDAddr against either global_addr or (global_addr + offset)
259 unsigned opcode
= LDAddrNode
->getOpcode();
260 if (opcode
== ISD::ADD
) {
261 SDValue OP1
= LDAddrNode
->getOperand(0);
262 SDValue OP2
= LDAddrNode
->getOperand(1);
264 // We want to find the pattern global_addr + offset
265 SDNode
*OP1N
= OP1
.getNode();
266 if (OP1N
->getOpcode() <= ISD::BUILTIN_OP_END
|| OP1N
->getNumOperands() == 0)
269 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD
->dump(); dbgs() << '\n');
271 const GlobalAddressSDNode
*GADN
=
272 dyn_cast
<GlobalAddressSDNode
>(OP1N
->getOperand(0).getNode());
273 const ConstantSDNode
*CDN
= dyn_cast
<ConstantSDNode
>(OP2
.getNode());
276 getConstantFieldValue(GADN
, CDN
->getZExtValue(), size
, new_val
.c
);
277 } else if (LDAddrNode
->getOpcode() > ISD::BUILTIN_OP_END
&&
278 LDAddrNode
->getNumOperands() > 0) {
279 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD
->dump(); dbgs() << '\n');
281 SDValue OP1
= LDAddrNode
->getOperand(0);
282 if (const GlobalAddressSDNode
*GADN
=
283 dyn_cast
<GlobalAddressSDNode
>(OP1
.getNode()))
284 to_replace
= getConstantFieldValue(GADN
, 0, size
, new_val
.c
);
290 // replacing the old with a new value
302 LLVM_DEBUG(dbgs() << "Replacing load of size " << size
<< " with constant "
304 SDValue NVal
= CurDAG
->getConstant(val
, DL
, LD
->getValueType(0));
306 // After replacement, the current node is dead, we need to
307 // go backward one step to make iterator still work
309 SDValue From
[] = {SDValue(Node
, 0), SDValue(Node
, 1)};
310 SDValue To
[] = {NVal
, NVal
};
311 CurDAG
->ReplaceAllUsesOfValuesWith(From
, To
, 2);
313 // It is safe to delete node now
314 CurDAG
->DeleteNode(Node
);
317 void BPFDAGToDAGISel::PreprocessISelDAG() {
318 // Iterate through all nodes, interested in the following case:
320 // . loads from ConstantStruct or ConstantArray of constructs
321 // which can be turns into constant itself, with this we can
322 // avoid reading from read-only section at runtime.
324 // . Removing redundant AND for intrinsic narrow loads.
325 for (SelectionDAG::allnodes_iterator I
= CurDAG
->allnodes_begin(),
326 E
= CurDAG
->allnodes_end();
328 SDNode
*Node
= &*I
++;
329 unsigned Opcode
= Node
->getOpcode();
330 if (Opcode
== ISD::LOAD
)
331 PreprocessLoad(Node
, I
);
332 else if (Opcode
== ISD::AND
)
333 PreprocessTrunc(Node
, I
);
337 bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode
*Node
,
338 uint64_t Offset
, uint64_t Size
,
339 unsigned char *ByteSeq
) {
340 const GlobalVariable
*V
= dyn_cast
<GlobalVariable
>(Node
->getGlobal());
342 if (!V
|| !V
->hasInitializer() || !V
->isConstant())
345 const Constant
*Init
= V
->getInitializer();
346 const DataLayout
&DL
= CurDAG
->getDataLayout();
349 auto it
= cs_vals_
.find(static_cast<const void *>(Init
));
350 if (it
!= cs_vals_
.end()) {
353 uint64_t total_size
= 0;
354 if (const ConstantStruct
*CS
= dyn_cast
<ConstantStruct
>(Init
))
356 DL
.getStructLayout(cast
<StructType
>(CS
->getType()))->getSizeInBytes();
357 else if (const ConstantArray
*CA
= dyn_cast
<ConstantArray
>(Init
))
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
);
370 // test whether host endianness matches target
375 uint16_t test_val
= 0x2345;
376 if (DL
.isLittleEndian())
377 support::endian::write16le(test_buf
.c
, test_val
);
379 support::endian::write16be(test_buf
.c
, test_val
);
381 bool endian_match
= test_buf
.s
== test_val
;
382 for (uint64_t i
= Offset
, j
= 0; i
< Offset
+ Size
; i
++, j
++)
383 ByteSeq
[j
] = endian_match
? TmpVal
[i
] : TmpVal
[Offset
+ Size
- 1 - j
];
388 bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout
&DL
,
390 val_vec_type
&Vals
, uint64_t Offset
) {
391 uint64_t Size
= DL
.getTypeAllocSize(CV
->getType());
393 if (isa
<ConstantAggregateZero
>(CV
) || isa
<UndefValue
>(CV
))
394 return true; // already done
396 if (const ConstantInt
*CI
= dyn_cast
<ConstantInt
>(CV
)) {
397 uint64_t val
= CI
->getZExtValue();
398 LLVM_DEBUG(dbgs() << "Byte array at offset " << Offset
<< " with value "
401 if (Size
> 8 || (Size
& (Size
- 1)))
404 // Store based on target endian
405 for (uint64_t i
= 0; i
< Size
; ++i
) {
406 Vals
[Offset
+ i
] = DL
.isLittleEndian()
407 ? ((val
>> (i
* 8)) & 0xFF)
408 : ((val
>> ((Size
- i
- 1) * 8)) & 0xFF);
413 if (const ConstantDataArray
*CDA
= dyn_cast
<ConstantDataArray
>(CV
))
414 return fillConstantDataArray(DL
, CDA
, Vals
, Offset
);
416 if (const ConstantArray
*CA
= dyn_cast
<ConstantArray
>(CV
))
417 return fillConstantArray(DL
, CA
, Vals
, Offset
);
419 if (const ConstantStruct
*CVS
= dyn_cast
<ConstantStruct
>(CV
))
420 return fillConstantStruct(DL
, CVS
, Vals
, Offset
);
425 bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout
&DL
,
426 const ConstantDataArray
*CDA
,
427 val_vec_type
&Vals
, int Offset
) {
428 for (unsigned i
= 0, e
= CDA
->getNumElements(); i
!= e
; ++i
) {
429 if (fillGenericConstant(DL
, CDA
->getElementAsConstant(i
), Vals
, Offset
) ==
432 Offset
+= DL
.getTypeAllocSize(CDA
->getElementAsConstant(i
)->getType());
438 bool BPFDAGToDAGISel::fillConstantArray(const DataLayout
&DL
,
439 const ConstantArray
*CA
,
440 val_vec_type
&Vals
, int Offset
) {
441 for (unsigned i
= 0, e
= CA
->getNumOperands(); i
!= e
; ++i
) {
442 if (fillGenericConstant(DL
, CA
->getOperand(i
), Vals
, Offset
) == false)
444 Offset
+= DL
.getTypeAllocSize(CA
->getOperand(i
)->getType());
450 bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout
&DL
,
451 const ConstantStruct
*CS
,
452 val_vec_type
&Vals
, int Offset
) {
453 const StructLayout
*Layout
= DL
.getStructLayout(CS
->getType());
454 for (unsigned i
= 0, e
= CS
->getNumOperands(); i
!= e
; ++i
) {
455 const Constant
*Field
= CS
->getOperand(i
);
456 uint64_t SizeSoFar
= Layout
->getElementOffset(i
);
457 if (fillGenericConstant(DL
, Field
, Vals
, Offset
+ SizeSoFar
) == false)
463 void BPFDAGToDAGISel::PreprocessTrunc(SDNode
*Node
,
464 SelectionDAG::allnodes_iterator
&I
) {
465 ConstantSDNode
*MaskN
= dyn_cast
<ConstantSDNode
>(Node
->getOperand(1));
469 // The Reg operand should be a virtual register, which is defined
470 // outside the current basic block. DAG combiner has done a pretty
471 // good job in removing truncating inside a single basic block except
472 // when the Reg operand comes from bpf_load_[byte | half | word] for
473 // which the generic optimizer doesn't understand their results are
475 SDValue BaseV
= Node
->getOperand(0);
476 if (BaseV
.getOpcode() != ISD::INTRINSIC_W_CHAIN
)
479 unsigned IntNo
= BaseV
->getConstantOperandVal(1);
480 uint64_t MaskV
= MaskN
->getZExtValue();
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)))
487 LLVM_DEBUG(dbgs() << "Remove the redundant AND operation in: ";
488 Node
->dump(); dbgs() << '\n');
491 CurDAG
->ReplaceAllUsesWith(SDValue(Node
, 0), BaseV
);
493 CurDAG
->DeleteNode(Node
);
496 FunctionPass
*llvm::createBPFISelDag(BPFTargetMachine
&TM
) {
497 return new BPFDAGToDAGISelLegacy(TM
);