Bug Summary

File:lib/Target/BPF/BPFISelDAGToDAG.cpp
Warning:line 310, column 9
Assigned value is garbage or undefined

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name BPFISelDAGToDAG.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-eagerly-assume -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -mrelocation-model pic -pic-level 2 -mthread-model posix -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-7/lib/clang/7.0.0 -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/lib/Target/BPF -I /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/BPF -I /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/include -I /build/llvm-toolchain-snapshot-7~svn338205/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/x86_64-linux-gnu/c++/8 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/backward -internal-isystem /usr/include/clang/7.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-7/lib/clang/7.0.0/include -internal-externc-isystem /usr/lib/gcc/x86_64-linux-gnu/8/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-7~svn338205/build-llvm/lib/Target/BPF -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2018-07-29-043837-17923-1 -x c++ /build/llvm-toolchain-snapshot-7~svn338205/lib/Target/BPF/BPFISelDAGToDAG.cpp -faddrsig
1//===-- BPFISelDAGToDAG.cpp - A dag to dag inst selector for BPF ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a DAG pattern matching instruction selector for BPF,
11// converting from a legalized dag to a BPF dag.
12//
13//===----------------------------------------------------------------------===//
14
15#include "BPF.h"
16#include "BPFRegisterInfo.h"
17#include "BPFSubtarget.h"
18#include "BPFTargetMachine.h"
19#include "llvm/CodeGen/FunctionLoweringInfo.h"
20#include "llvm/CodeGen/MachineConstantPool.h"
21#include "llvm/CodeGen/MachineFrameInfo.h"
22#include "llvm/CodeGen/MachineFunction.h"
23#include "llvm/CodeGen/MachineInstrBuilder.h"
24#include "llvm/CodeGen/MachineRegisterInfo.h"
25#include "llvm/CodeGen/SelectionDAGISel.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/IR/IntrinsicInst.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"
33
34using namespace llvm;
35
36#define DEBUG_TYPE"bpf-isel" "bpf-isel"
37
38// Instruction Selector Implementation
39namespace {
40
41class BPFDAGToDAGISel : public SelectionDAGISel {
42
43 /// Subtarget - Keep a pointer to the BPFSubtarget around so that we can
44 /// make the right decision when generating code for different subtargets.
45 const BPFSubtarget *Subtarget;
46
47public:
48 explicit BPFDAGToDAGISel(BPFTargetMachine &TM)
49 : SelectionDAGISel(TM), Subtarget(nullptr) {
50 curr_func_ = nullptr;
51 }
52
53 StringRef getPassName() const override {
54 return "BPF DAG->DAG Pattern Instruction Selection";
55 }
56
57 bool runOnMachineFunction(MachineFunction &MF) override {
58 // Reset the subtarget each time through.
59 Subtarget = &MF.getSubtarget<BPFSubtarget>();
60 return SelectionDAGISel::runOnMachineFunction(MF);
61 }
62
63 void PreprocessISelDAG() override;
64
65 bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode,
66 std::vector<SDValue> &OutOps) override;
67
68
69private:
70// Include the pieces autogenerated from the target description.
71#include "BPFGenDAGISel.inc"
72
73 void Select(SDNode *N) override;
74
75 // Complex Pattern for address selection.
76 bool SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
77 bool SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offset);
78
79 // Node preprocessing cases
80 void PreprocessLoad(SDNode *Node, SelectionDAG::allnodes_iterator &I);
81 void PreprocessCopyToReg(SDNode *Node);
82 void PreprocessTrunc(SDNode *Node, SelectionDAG::allnodes_iterator &I);
83
84 // Find constants from a constant structure
85 typedef std::vector<unsigned char> val_vec_type;
86 bool fillGenericConstant(const DataLayout &DL, const Constant *CV,
87 val_vec_type &Vals, uint64_t Offset);
88 bool fillConstantDataArray(const DataLayout &DL, const ConstantDataArray *CDA,
89 val_vec_type &Vals, int Offset);
90 bool fillConstantArray(const DataLayout &DL, const ConstantArray *CA,
91 val_vec_type &Vals, int Offset);
92 bool fillConstantStruct(const DataLayout &DL, const ConstantStruct *CS,
93 val_vec_type &Vals, int Offset);
94 bool getConstantFieldValue(const GlobalAddressSDNode *Node, uint64_t Offset,
95 uint64_t Size, unsigned char *ByteSeq);
96 bool checkLoadDef(unsigned DefReg, unsigned match_load_op);
97
98 // Mapping from ConstantStruct global value to corresponding byte-list values
99 std::map<const void *, val_vec_type> cs_vals_;
100 // Mapping from vreg to load memory opcode
101 std::map<unsigned, unsigned> load_to_vreg_;
102 // Current function
103 const Function *curr_func_;
104};
105} // namespace
106
107// ComplexPattern used on BPF Load/Store instructions
108bool BPFDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) {
109 // if Address is FI, get the TargetFrameIndex.
110 SDLoc DL(Addr);
111 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
112 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
113 Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
114 return true;
115 }
116
117 if (Addr.getOpcode() == ISD::TargetExternalSymbol ||
118 Addr.getOpcode() == ISD::TargetGlobalAddress)
119 return false;
120
121 // Addresses of the form Addr+const or Addr|const
122 if (CurDAG->isBaseWithConstantOffset(Addr)) {
123 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
124 if (isInt<16>(CN->getSExtValue())) {
125
126 // If the first operand is a FI, get the TargetFI Node
127 if (FrameIndexSDNode *FIN =
128 dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
129 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
130 else
131 Base = Addr.getOperand(0);
132
133 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
134 return true;
135 }
136 }
137
138 Base = Addr;
139 Offset = CurDAG->getTargetConstant(0, DL, MVT::i64);
140 return true;
141}
142
143// ComplexPattern used on BPF FI instruction
144bool BPFDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base,
145 SDValue &Offset) {
146 SDLoc DL(Addr);
147
148 if (!CurDAG->isBaseWithConstantOffset(Addr))
149 return false;
150
151 // Addresses of the form Addr+const or Addr|const
152 ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
153 if (isInt<16>(CN->getSExtValue())) {
154
155 // If the first operand is a FI, get the TargetFI Node
156 if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr.getOperand(0)))
157 Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64);
158 else
159 return false;
160
161 Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64);
162 return true;
163 }
164
165 return false;
166}
167
168bool BPFDAGToDAGISel::SelectInlineAsmMemoryOperand(
169 const SDValue &Op, unsigned ConstraintCode, std::vector<SDValue> &OutOps) {
170 SDValue Op0, Op1;
171 switch (ConstraintCode) {
172 default:
173 return true;
174 case InlineAsm::Constraint_m: // memory
175 if (!SelectAddr(Op, Op0, Op1))
176 return true;
177 break;
178 }
179
180 SDLoc DL(Op);
181 SDValue AluOp = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32);;
182 OutOps.push_back(Op0);
183 OutOps.push_back(Op1);
184 OutOps.push_back(AluOp);
185 return false;
186}
187
188void BPFDAGToDAGISel::Select(SDNode *Node) {
189 unsigned Opcode = Node->getOpcode();
190
191 // If we have a custom node, we already have selected!
192 if (Node->isMachineOpcode()) {
193 LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "== "; Node->dump(CurDAG);
dbgs() << '\n'; } } while (false)
;
194 return;
195 }
196
197 // tablegen selection should be handled here.
198 switch (Opcode) {
199 default:
200 break;
201 case ISD::SDIV: {
202 DebugLoc Empty;
203 const DebugLoc &DL = Node->getDebugLoc();
204 if (DL != Empty)
205 errs() << "Error at line " << DL.getLine() << ": ";
206 else
207 errs() << "Error: ";
208 errs() << "Unsupport signed division for DAG: ";
209 Node->print(errs(), CurDAG);
210 errs() << "Please convert to unsigned div/mod.\n";
211 break;
212 }
213 case ISD::INTRINSIC_W_CHAIN: {
214 unsigned IntNo = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue();
215 switch (IntNo) {
216 case Intrinsic::bpf_load_byte:
217 case Intrinsic::bpf_load_half:
218 case Intrinsic::bpf_load_word: {
219 SDLoc DL(Node);
220 SDValue Chain = Node->getOperand(0);
221 SDValue N1 = Node->getOperand(1);
222 SDValue Skb = Node->getOperand(2);
223 SDValue N3 = Node->getOperand(3);
224
225 SDValue R6Reg = CurDAG->getRegister(BPF::R6, MVT::i64);
226 Chain = CurDAG->getCopyToReg(Chain, DL, R6Reg, Skb, SDValue());
227 Node = CurDAG->UpdateNodeOperands(Node, Chain, N1, R6Reg, N3);
228 break;
229 }
230 }
231 break;
232 }
233
234 case ISD::FrameIndex: {
235 int FI = cast<FrameIndexSDNode>(Node)->getIndex();
236 EVT VT = Node->getValueType(0);
237 SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
238 unsigned Opc = BPF::MOV_rr;
239 if (Node->hasOneUse()) {
240 CurDAG->SelectNodeTo(Node, Opc, VT, TFI);
241 return;
242 }
243 ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI));
244 return;
245 }
246 }
247
248 // Select the default instruction
249 SelectCode(Node);
250}
251
252void BPFDAGToDAGISel::PreprocessLoad(SDNode *Node,
253 SelectionDAG::allnodes_iterator &I) {
254 union {
255 uint8_t c[8];
256 uint16_t s;
257 uint32_t i;
258 uint64_t d;
259 } new_val; // hold up the constant values replacing loads.
260 bool to_replace = false;
261 SDLoc DL(Node);
262 const LoadSDNode *LD = cast<LoadSDNode>(Node);
263 uint64_t size = LD->getMemOperand()->getSize();
264
265 if (!size || size > 8 || (size & (size - 1)))
9
Assuming 'size' is not equal to 0
10
Assuming 'size' is <= 8
11
Assuming the condition is false
12
Taking false branch
266 return;
267
268 SDNode *LDAddrNode = LD->getOperand(1).getNode();
269 // Match LDAddr against either global_addr or (global_addr + offset)
270 unsigned opcode = LDAddrNode->getOpcode();
271 if (opcode == ISD::ADD) {
13
Assuming 'opcode' is equal to ADD
14
Taking true branch
272 SDValue OP1 = LDAddrNode->getOperand(0);
273 SDValue OP2 = LDAddrNode->getOperand(1);
274
275 // We want to find the pattern global_addr + offset
276 SDNode *OP1N = OP1.getNode();
277 if (OP1N->getOpcode() <= ISD::BUILTIN_OP_END || OP1N->getNumOperands() == 0)
15
Assuming the condition is false
16
Assuming the condition is false
17
Taking false branch
278 return;
279
280 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Check candidate load: "; LD->
dump(); dbgs() << '\n'; } } while (false)
;
281
282 const GlobalAddressSDNode *GADN =
283 dyn_cast<GlobalAddressSDNode>(OP1N->getOperand(0).getNode());
284 const ConstantSDNode *CDN = dyn_cast<ConstantSDNode>(OP2.getNode());
285 if (GADN && CDN)
18
Assuming 'GADN' is non-null
19
Assuming 'CDN' is non-null
20
Taking true branch
286 to_replace =
287 getConstantFieldValue(GADN, CDN->getZExtValue(), size, new_val.c);
288 } else if (LDAddrNode->getOpcode() > ISD::BUILTIN_OP_END &&
289 LDAddrNode->getNumOperands() > 0) {
290 LLVM_DEBUG(dbgs() << "Check candidate load: "; LD->dump(); dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Check candidate load: "; LD->
dump(); dbgs() << '\n'; } } while (false)
;
291
292 SDValue OP1 = LDAddrNode->getOperand(0);
293 if (const GlobalAddressSDNode *GADN =
294 dyn_cast<GlobalAddressSDNode>(OP1.getNode()))
295 to_replace = getConstantFieldValue(GADN, 0, size, new_val.c);
296 }
297
298 if (!to_replace)
21
Taking false branch
299 return;
300
301 // replacing the old with a new value
302 uint64_t val;
303 if (size == 1)
22
Assuming 'size' is not equal to 1
23
Taking false branch
304 val = new_val.c[0];
305 else if (size == 2)
24
Assuming 'size' is not equal to 2
25
Taking false branch
306 val = new_val.s;
307 else if (size == 4)
26
Assuming 'size' is not equal to 4
27
Taking false branch
308 val = new_val.i;
309 else {
310 val = new_val.d;
28
Assigned value is garbage or undefined
311 }
312
313 LLVM_DEBUG(dbgs() << "Replacing load of size " << size << " with constant "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Replacing load of size " <<
size << " with constant " << val << '\n'; }
} while (false)
314 << val << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Replacing load of size " <<
size << " with constant " << val << '\n'; }
} while (false)
;
315 SDValue NVal = CurDAG->getConstant(val, DL, MVT::i64);
316
317 // After replacement, the current node is dead, we need to
318 // go backward one step to make iterator still work
319 I--;
320 SDValue From[] = {SDValue(Node, 0), SDValue(Node, 1)};
321 SDValue To[] = {NVal, NVal};
322 CurDAG->ReplaceAllUsesOfValuesWith(From, To, 2);
323 I++;
324 // It is safe to delete node now
325 CurDAG->DeleteNode(Node);
326}
327
328void BPFDAGToDAGISel::PreprocessISelDAG() {
329 // Iterate through all nodes, interested in the following cases:
330 //
331 // . loads from ConstantStruct or ConstantArray of constructs
332 // which can be turns into constant itself, with this we can
333 // avoid reading from read-only section at runtime.
334 //
335 // . reg truncating is often the result of 8/16/32bit->64bit or
336 // 8/16bit->32bit conversion. If the reg value is loaded with
337 // masked byte width, the AND operation can be removed since
338 // BPF LOAD already has zero extension.
339 //
340 // This also solved a correctness issue.
341 // In BPF socket-related program, e.g., __sk_buff->{data, data_end}
342 // are 32-bit registers, but later on, kernel verifier will rewrite
343 // it with 64-bit value. Therefore, truncating the value after the
344 // load will result in incorrect code.
345
346 // clear the load_to_vreg_ map so that we have a clean start
347 // for this function.
348 if (!curr_func_) {
1
Assuming the condition is false
2
Taking false branch
349 curr_func_ = FuncInfo->Fn;
350 } else if (curr_func_ != FuncInfo->Fn) {
3
Assuming the condition is false
4
Taking false branch
351 load_to_vreg_.clear();
352 curr_func_ = FuncInfo->Fn;
353 }
354
355 for (SelectionDAG::allnodes_iterator I = CurDAG->allnodes_begin(),
5
Loop condition is true. Entering loop body
356 E = CurDAG->allnodes_end();
357 I != E;) {
358 SDNode *Node = &*I++;
359 unsigned Opcode = Node->getOpcode();
360 if (Opcode == ISD::LOAD)
6
Assuming 'Opcode' is equal to LOAD
7
Taking true branch
361 PreprocessLoad(Node, I);
8
Calling 'BPFDAGToDAGISel::PreprocessLoad'
362 else if (Opcode == ISD::CopyToReg)
363 PreprocessCopyToReg(Node);
364 else if (Opcode == ISD::AND)
365 PreprocessTrunc(Node, I);
366 }
367}
368
369bool BPFDAGToDAGISel::getConstantFieldValue(const GlobalAddressSDNode *Node,
370 uint64_t Offset, uint64_t Size,
371 unsigned char *ByteSeq) {
372 const GlobalVariable *V = dyn_cast<GlobalVariable>(Node->getGlobal());
373
374 if (!V || !V->hasInitializer())
375 return false;
376
377 const Constant *Init = V->getInitializer();
378 const DataLayout &DL = CurDAG->getDataLayout();
379 val_vec_type TmpVal;
380
381 auto it = cs_vals_.find(static_cast<const void *>(Init));
382 if (it != cs_vals_.end()) {
383 TmpVal = it->second;
384 } else {
385 uint64_t total_size = 0;
386 if (const ConstantStruct *CS = dyn_cast<ConstantStruct>(Init))
387 total_size =
388 DL.getStructLayout(cast<StructType>(CS->getType()))->getSizeInBytes();
389 else if (const ConstantArray *CA = dyn_cast<ConstantArray>(Init))
390 total_size = DL.getTypeAllocSize(CA->getType()->getElementType()) *
391 CA->getNumOperands();
392 else
393 return false;
394
395 val_vec_type Vals(total_size, 0);
396 if (fillGenericConstant(DL, Init, Vals, 0) == false)
397 return false;
398 cs_vals_[static_cast<const void *>(Init)] = Vals;
399 TmpVal = std::move(Vals);
400 }
401
402 // test whether host endianness matches target
403 union {
404 uint8_t c[2];
405 uint16_t s;
406 } test_buf;
407 uint16_t test_val = 0x2345;
408 if (DL.isLittleEndian())
409 support::endian::write16le(test_buf.c, test_val);
410 else
411 support::endian::write16be(test_buf.c, test_val);
412
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];
416
417 return true;
418}
419
420bool BPFDAGToDAGISel::fillGenericConstant(const DataLayout &DL,
421 const Constant *CV,
422 val_vec_type &Vals, uint64_t Offset) {
423 uint64_t Size = DL.getTypeAllocSize(CV->getType());
424
425 if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV))
426 return true; // already done
427
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 "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Byte array at offset " <<
Offset << " with value " << val << '\n'; }
} while (false)
431 << val << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Byte array at offset " <<
Offset << " with value " << val << '\n'; }
} while (false)
;
432
433 if (Size > 8 || (Size & (Size - 1)))
434 return false;
435
436 // Store based on target endian
437 for (uint64_t i = 0; i < Size; ++i) {
438 Vals[Offset + i] = DL.isLittleEndian()
439 ? ((val >> (i * 8)) & 0xFF)
440 : ((val >> ((Size - i - 1) * 8)) & 0xFF);
441 }
442 return true;
443 }
444
445 if (const ConstantDataArray *CDA = dyn_cast<ConstantDataArray>(CV))
446 return fillConstantDataArray(DL, CDA, Vals, Offset);
447
448 if (const ConstantArray *CA = dyn_cast<ConstantArray>(CV))
449 return fillConstantArray(DL, CA, Vals, Offset);
450
451 if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV))
452 return fillConstantStruct(DL, CVS, Vals, Offset);
453
454 return false;
455}
456
457bool BPFDAGToDAGISel::fillConstantDataArray(const DataLayout &DL,
458 const ConstantDataArray *CDA,
459 val_vec_type &Vals, int Offset) {
460 for (unsigned i = 0, e = CDA->getNumElements(); i != e; ++i) {
461 if (fillGenericConstant(DL, CDA->getElementAsConstant(i), Vals, Offset) ==
462 false)
463 return false;
464 Offset += DL.getTypeAllocSize(CDA->getElementAsConstant(i)->getType());
465 }
466
467 return true;
468}
469
470bool BPFDAGToDAGISel::fillConstantArray(const DataLayout &DL,
471 const ConstantArray *CA,
472 val_vec_type &Vals, int Offset) {
473 for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
474 if (fillGenericConstant(DL, CA->getOperand(i), Vals, Offset) == false)
475 return false;
476 Offset += DL.getTypeAllocSize(CA->getOperand(i)->getType());
477 }
478
479 return true;
480}
481
482bool BPFDAGToDAGISel::fillConstantStruct(const DataLayout &DL,
483 const ConstantStruct *CS,
484 val_vec_type &Vals, int Offset) {
485 const StructLayout *Layout = DL.getStructLayout(CS->getType());
486 for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i) {
487 const Constant *Field = CS->getOperand(i);
488 uint64_t SizeSoFar = Layout->getElementOffset(i);
489 if (fillGenericConstant(DL, Field, Vals, Offset + SizeSoFar) == false)
490 return false;
491 }
492 return true;
493}
494
495void BPFDAGToDAGISel::PreprocessCopyToReg(SDNode *Node) {
496 const RegisterSDNode *RegN = dyn_cast<RegisterSDNode>(Node->getOperand(1));
497 if (!RegN || !TargetRegisterInfo::isVirtualRegister(RegN->getReg()))
498 return;
499
500 const LoadSDNode *LD = dyn_cast<LoadSDNode>(Node->getOperand(2));
501 if (!LD)
502 return;
503
504 // Assign a load value to a virtual register. record its load width
505 unsigned mem_load_op = 0;
506 switch (LD->getMemOperand()->getSize()) {
507 default:
508 return;
509 case 4:
510 mem_load_op = BPF::LDW;
511 break;
512 case 2:
513 mem_load_op = BPF::LDH;
514 break;
515 case 1:
516 mem_load_op = BPF::LDB;
517 break;
518 }
519
520 LLVM_DEBUG(dbgs() << "Find Load Value to VReg "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Find Load Value to VReg " <<
TargetRegisterInfo::virtReg2Index(RegN->getReg()) <<
'\n'; } } while (false)
521 << TargetRegisterInfo::virtReg2Index(RegN->getReg())do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Find Load Value to VReg " <<
TargetRegisterInfo::virtReg2Index(RegN->getReg()) <<
'\n'; } } while (false)
522 << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Find Load Value to VReg " <<
TargetRegisterInfo::virtReg2Index(RegN->getReg()) <<
'\n'; } } while (false)
;
523 load_to_vreg_[RegN->getReg()] = mem_load_op;
524}
525
526void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
527 SelectionDAG::allnodes_iterator &I) {
528 ConstantSDNode *MaskN = dyn_cast<ConstantSDNode>(Node->getOperand(1));
529 if (!MaskN)
530 return;
531
532 // The Reg operand should be a virtual register, which is defined
533 // outside the current basic block. DAG combiner has done a pretty
534 // good job in removing truncating inside a single basic block except
535 // when the Reg operand comes from bpf_load_[byte | half | word] for
536 // which the generic optimizer doesn't understand their results are
537 // zero extended.
538 SDValue BaseV = Node->getOperand(0);
539 if (BaseV.getOpcode() == ISD::INTRINSIC_W_CHAIN) {
540 unsigned IntNo = cast<ConstantSDNode>(BaseV->getOperand(1))->getZExtValue();
541 uint64_t MaskV = MaskN->getZExtValue();
542
543 if (!((IntNo == Intrinsic::bpf_load_byte && MaskV == 0xFF) ||
544 (IntNo == Intrinsic::bpf_load_half && MaskV == 0xFFFF) ||
545 (IntNo == Intrinsic::bpf_load_word && MaskV == 0xFFFFFFFF)))
546 return;
547
548 LLVM_DEBUG(dbgs() << "Remove the redundant AND operation in: ";do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Remove the redundant AND operation in: "
; Node->dump(); dbgs() << '\n'; } } while (false)
549 Node->dump(); dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Remove the redundant AND operation in: "
; Node->dump(); dbgs() << '\n'; } } while (false)
;
550
551 I--;
552 CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
553 I++;
554 CurDAG->DeleteNode(Node);
555
556 return;
557 }
558
559 // Multiple basic blocks case.
560 if (BaseV.getOpcode() != ISD::CopyFromReg)
561 return;
562
563 unsigned match_load_op = 0;
564 switch (MaskN->getZExtValue()) {
565 default:
566 return;
567 case 0xFFFFFFFF:
568 match_load_op = BPF::LDW;
569 break;
570 case 0xFFFF:
571 match_load_op = BPF::LDH;
572 break;
573 case 0xFF:
574 match_load_op = BPF::LDB;
575 break;
576 }
577
578 const RegisterSDNode *RegN =
579 dyn_cast<RegisterSDNode>(BaseV.getNode()->getOperand(1));
580 if (!RegN || !TargetRegisterInfo::isVirtualRegister(RegN->getReg()))
581 return;
582 unsigned AndOpReg = RegN->getReg();
583 LLVM_DEBUG(dbgs() << "Examine " << printReg(AndOpReg) << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Examine " << printReg(
AndOpReg) << '\n'; } } while (false)
;
584
585 // Examine the PHI insns in the MachineBasicBlock to found out the
586 // definitions of this virtual register. At this stage (DAG2DAG
587 // transformation), only PHI machine insns are available in the machine basic
588 // block.
589 MachineBasicBlock *MBB = FuncInfo->MBB;
590 MachineInstr *MII = nullptr;
591 for (auto &MI : *MBB) {
592 for (unsigned i = 0; i < MI.getNumOperands(); ++i) {
593 const MachineOperand &MOP = MI.getOperand(i);
594 if (!MOP.isReg() || !MOP.isDef())
595 continue;
596 unsigned Reg = MOP.getReg();
597 if (TargetRegisterInfo::isVirtualRegister(Reg) && Reg == AndOpReg) {
598 MII = &MI;
599 break;
600 }
601 }
602 }
603
604 if (MII == nullptr) {
605 // No phi definition in this block.
606 if (!checkLoadDef(AndOpReg, match_load_op))
607 return;
608 } else {
609 // The PHI node looks like:
610 // %2 = PHI %0, <%bb.1>, %1, <%bb.3>
611 // Trace each incoming definition, e.g., (%0, %bb.1) and (%1, %bb.3)
612 // The AND operation can be removed if both %0 in %bb.1 and %1 in
613 // %bb.3 are defined with a load matching the MaskN.
614 LLVM_DEBUG(dbgs() << "Check PHI Insn: "; MII->dump(); dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Check PHI Insn: "; MII->dump
(); dbgs() << '\n'; } } while (false)
;
615 unsigned PrevReg = -1;
616 for (unsigned i = 0; i < MII->getNumOperands(); ++i) {
617 const MachineOperand &MOP = MII->getOperand(i);
618 if (MOP.isReg()) {
619 if (MOP.isDef())
620 continue;
621 PrevReg = MOP.getReg();
622 if (!TargetRegisterInfo::isVirtualRegister(PrevReg))
623 return;
624 if (!checkLoadDef(PrevReg, match_load_op))
625 return;
626 }
627 }
628 }
629
630 LLVM_DEBUG(dbgs() << "Remove the redundant AND operation in: "; Node->dump();do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Remove the redundant AND operation in: "
; Node->dump(); dbgs() << '\n'; } } while (false)
631 dbgs() << '\n')do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType
("bpf-isel")) { dbgs() << "Remove the redundant AND operation in: "
; Node->dump(); dbgs() << '\n'; } } while (false)
;
632
633 I--;
634 CurDAG->ReplaceAllUsesWith(SDValue(Node, 0), BaseV);
635 I++;
636 CurDAG->DeleteNode(Node);
637}
638
639bool BPFDAGToDAGISel::checkLoadDef(unsigned DefReg, unsigned match_load_op) {
640 auto it = load_to_vreg_.find(DefReg);
641 if (it == load_to_vreg_.end())
642 return false; // The definition of register is not exported yet.
643
644 return it->second == match_load_op;
645}
646
647FunctionPass *llvm::createBPFISelDag(BPFTargetMachine &TM) {
648 return new BPFDAGToDAGISel(TM);
649}