LLVM  17.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  ICmp->insertBefore(Call);
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:18
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::AArch64PACKey::ID
ID
Definition: AArch64BaseInfo.h:824
llvm::CmpInst::Predicate
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
Definition: InstrTypes.h:718
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:59
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:187
Instruction.h
llvm::PHINode::getIncomingValue
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
Definition: Instructions.h:2794
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:145
llvm::MCID::Call
@ Call
Definition: MCInstrDesc.h:156
llvm::PHINode::getNumIncomingValues
unsigned getNumIncomingValues() const
Return the number of incoming edges.
Definition: Instructions.h:2790
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:82
llvm::ICmpInst
This instruction compares its operands according to the predicate given to the constructor.
Definition: Instructions.h:1197
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:31
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:65
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:63
Instructions.h
User.h
llvm::PHINode
Definition: Instructions.h:2708
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1485
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
BPFTargetMachine.h