LLVM  15.0.0git
BPFCheckAndAdjustIR.cpp
Go to the documentation of this file.
1 //===------------ BPFCheckAndAdjustIR.cpp - Check and Adjust IR -----------===//
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 // Check IR and adjust IR for verifier friendly codes.
10 // The following are done for IR checking:
11 // - no relocation globals in PHI node.
12 // The following are done for IR adjustment:
13 // - remove __builtin_bpf_passthrough builtins. Target independent IR
14 // optimizations are done and those builtins can be removed.
15 //
16 //===----------------------------------------------------------------------===//
17 
18 #include "BPF.h"
19 #include "BPFCORE.h"
20 #include "BPFTargetMachine.h"
22 #include "llvm/IR/GlobalVariable.h"
23 #include "llvm/IR/Instruction.h"
24 #include "llvm/IR/Instructions.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/IR/Type.h"
27 #include "llvm/IR/User.h"
28 #include "llvm/IR/Value.h"
29 #include "llvm/Pass.h"
31 
32 #define DEBUG_TYPE "bpf-check-and-opt-ir"
33 
34 using namespace llvm;
35 
36 namespace {
37 
38 class BPFCheckAndAdjustIR final : public ModulePass {
39  bool runOnModule(Module &F) override;
40 
41 public:
42  static char ID;
43  BPFCheckAndAdjustIR() : ModulePass(ID) {}
44 
45 private:
46  void checkIR(Module &M);
47  bool adjustIR(Module &M);
48  bool removePassThroughBuiltin(Module &M);
49  bool removeCompareBuiltin(Module &M);
50 };
51 } // End anonymous namespace
52 
54 INITIALIZE_PASS(BPFCheckAndAdjustIR, DEBUG_TYPE, "BPF Check And Adjust IR",
55  false, false)
56 
58  return new BPFCheckAndAdjustIR();
59 }
60 
61 void BPFCheckAndAdjustIR::checkIR(Module &M) {
62  // Ensure relocation global won't appear in PHI node
63  // This may happen if the compiler generated the following code:
64  // B1:
65  // g1 = @llvm.skb_buff:0:1...
66  // ...
67  // goto B_COMMON
68  // B2:
69  // g2 = @llvm.skb_buff:0:2...
70  // ...
71  // goto B_COMMON
72  // B_COMMON:
73  // g = PHI(g1, g2)
74  // x = load g
75  // ...
76  // If anything likes the above "g = PHI(g1, g2)", issue a fatal error.
77  for (Function &F : M)
78  for (auto &BB : F)
79  for (auto &I : BB) {
80  PHINode *PN = dyn_cast<PHINode>(&I);
81  if (!PN || PN->use_empty())
82  continue;
83  for (int i = 0, e = PN->getNumIncomingValues(); i < e; ++i) {
84  auto *GV = dyn_cast<GlobalVariable>(PN->getIncomingValue(i));
85  if (!GV)
86  continue;
87  if (GV->hasAttribute(BPFCoreSharedInfo::AmaAttr) ||
88  GV->hasAttribute(BPFCoreSharedInfo::TypeIdAttr))
89  report_fatal_error("relocation global in PHI node");
90  }
91  }
92 }
93 
94 bool BPFCheckAndAdjustIR::removePassThroughBuiltin(Module &M) {
95  // Remove __builtin_bpf_passthrough()'s which are used to prevent
96  // certain IR optimizations. Now major IR optimizations are done,
97  // remove them.
98  bool Changed = false;
99  CallInst *ToBeDeleted = nullptr;
100  for (Function &F : M)
101  for (auto &BB : F)
102  for (auto &I : BB) {
103  if (ToBeDeleted) {
104  ToBeDeleted->eraseFromParent();
105  ToBeDeleted = nullptr;
106  }
107 
108  auto *Call = dyn_cast<CallInst>(&I);
109  if (!Call)
110  continue;
111  auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
112  if (!GV)
113  continue;
114  if (!GV->getName().startswith("llvm.bpf.passthrough"))
115  continue;
116  Changed = true;
117  Value *Arg = Call->getArgOperand(1);
118  Call->replaceAllUsesWith(Arg);
119  ToBeDeleted = Call;
120  }
121  return Changed;
122 }
123 
124 bool BPFCheckAndAdjustIR::removeCompareBuiltin(Module &M) {
125  // Remove __builtin_bpf_compare()'s which are used to prevent
126  // certain IR optimizations. Now major IR optimizations are done,
127  // remove them.
128  bool Changed = false;
129  CallInst *ToBeDeleted = nullptr;
130  for (Function &F : M)
131  for (auto &BB : F)
132  for (auto &I : BB) {
133  if (ToBeDeleted) {
134  ToBeDeleted->eraseFromParent();
135  ToBeDeleted = nullptr;
136  }
137 
138  auto *Call = dyn_cast<CallInst>(&I);
139  if (!Call)
140  continue;
141  auto *GV = dyn_cast<GlobalValue>(Call->getCalledOperand());
142  if (!GV)
143  continue;
144  if (!GV->getName().startswith("llvm.bpf.compare"))
145  continue;
146 
147  Changed = true;
148  Value *Arg0 = Call->getArgOperand(0);
149  Value *Arg1 = Call->getArgOperand(1);
150  Value *Arg2 = Call->getArgOperand(2);
151 
152  auto OpVal = cast<ConstantInt>(Arg0)->getValue().getZExtValue();
153  CmpInst::Predicate Opcode = (CmpInst::Predicate)OpVal;
154 
155  auto *ICmp = new ICmpInst(Opcode, Arg1, Arg2);
156  BB.getInstList().insert(Call->getIterator(), ICmp);
157 
158  Call->replaceAllUsesWith(ICmp);
159  ToBeDeleted = Call;
160  }
161  return Changed;
162 }
163 
164 bool BPFCheckAndAdjustIR::adjustIR(Module &M) {
165  bool Changed = removePassThroughBuiltin(M);
166  Changed = removeCompareBuiltin(M) || Changed;
167  return Changed;
168 }
169 
170 bool BPFCheckAndAdjustIR::runOnModule(Module &M) {
171  checkIR(M);
172  return adjustIR(M);
173 }
i
i
Definition: README.txt:29
DEBUG_TYPE
#define DEBUG_TYPE
Definition: BPFCheckAndAdjustIR.cpp:32
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::CmpInst::Predicate
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:719
llvm::ModulePass
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition: Pass.h:248
llvm::createBPFCheckAndAdjustIR
ModulePass * createBPFCheckAndAdjustIR()
DebugInfoMetadata.h
llvm::Function
Definition: Function.h:60
Pass.h
Module.h
BPF.h
F
#define F(x, y, z)
Definition: MD5.cpp:55
Arg
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
Definition: AMDGPULibCalls.cpp:186
Instruction.h
llvm::PHINode::getIncomingValue
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
Definition: Instructions.h:2747
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
llvm::MCID::Call
@ Call
Definition: MCInstrDesc.h:155
llvm::PHINode::getNumIncomingValues
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Definition: Instructions.h:2743
llvm::Value::use_empty
bool use_empty() const
Definition: Value.h:344
llvm::CallingConv::ID
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Type.h
llvm::Instruction::eraseFromParent
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:77
llvm::ICmpInst
This instruction compares its operands according to the predicate given to the constructor.
Definition: Instructions.h:1173
INITIALIZE_PASS
INITIALIZE_PASS(BPFCheckAndAdjustIR, DEBUG_TYPE, "BPF Check And Adjust IR", false, false) ModulePass *llvm
Definition: BPFCheckAndAdjustIR.cpp:54
llvm::numbers::e
constexpr double e
Definition: MathExtras.h:57
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::BPFCoreSharedInfo::TypeIdAttr
static constexpr StringRef TypeIdAttr
The attribute attached to globals representing a type id.
Definition: BPFCORE.h:63
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
GlobalVariable.h
BPFCORE.h
llvm::BPFCoreSharedInfo::AmaAttr
static constexpr StringRef AmaAttr
The attribute attached to globals representing a field access.
Definition: BPFCORE.h:61
Instructions.h
User.h
llvm::PHINode
Definition: Instructions.h:2651
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1461
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
BasicBlockUtils.h
Value.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38
BPFTargetMachine.h