[PATCH] D87428: [RFC] BPF: avoid same condition evaluated in multiple branch instructions
Yonghong Song via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 9 19:16:41 PDT 2020
yonghong-song created this revision.
yonghong-song added a reviewer: ast.
Herald added subscribers: llvm-commits, hiraditya.
Herald added a project: LLVM.
yonghong-song requested review of this revision.
This patch specifically tries to address an issue reported at
https://lore.kernel.org/bpf/20200812074826.GB754656@krava/
If one icmp condition is used in more than one places, prevent
this condition from inlining into multiple places.
For example,
cond = a < b
...
select cond, val1, val2
...
br cond, block1, block2
In actually lowering, cond will be put into select_cc and br_cc
so we will have proper cond in the jmp inst.
It is reported this caused the issue if cond happens to be
pkt_ptr < pkt_end
due to particular kernel implementation.
The transformation here is to put a barrier after "cond = a < b"
so cond cannot be inlined into select/br. The pseudo generated code
looks like:
if a < b then
tmp = 1
then
tmp = 0
...
if (tmp == 1) val1; else val2
...
if (tmp == 1) goto block1; else goto block2;
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D87428
Files:
llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp
Index: llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp
===================================================================
--- llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp
+++ llvm/lib/Target/BPF/BPFCheckAndAdjustIR.cpp
@@ -61,6 +61,7 @@
void checkIR(Module &M);
bool adjustIR(Module &M);
bool removePassThroughBuiltin(Module &M);
+ bool serializeCond(Module &M);
bool optimizeReloc(Module &M);
void findOptRelocCand(Instruction &I);
void checkBitCast(BitCastInst *BI, GetElementPtrInst *GEP1, GlobalVariable *GV1);
@@ -144,6 +145,61 @@
return Changed;
}
+bool BPFCheckAndAdjustIR::serializeCond(Module &M) {
+ // Forcing to lower an icmp condition if it is used
+ // in multiple places.
+ // For:
+ // icmp1 = ...
+ // ...
+ // a = select icmp1, val1, val2
+ // ...
+ // ... icmp1 ...
+ // Change to:
+ // icmp1 = ...
+ // icmp1 = user_asm_barrier(icmp1)
+ // ...
+ // a = select icmp1, val1, val2
+ // ...
+ // ... icmp1 ...
+ SmallVector<ICmpInst *, 16> Candidates;
+ for (Function &F : M)
+ for (auto &BB : F)
+ for (auto &I : BB) {
+ auto *Cond = dyn_cast<ICmpInst>(&I);
+ if (!Cond || Cond->use_empty() || Cond->hasOneUse())
+ continue;
+ Candidates.push_back(Cond);
+ }
+
+ if (Candidates.empty())
+ return false;
+
+ bool Changed = false;
+ for (auto *Cond : Candidates) {
+ SmallVector<Instruction *, 16> Uses;
+ for (User *U : Cond->users()) {
+ Instruction *Inst = dyn_cast<Instruction>(U);
+ if (!Inst || (!isa<SelectInst>(Inst) && !isa<BranchInst>(Inst)))
+ continue;
+ Uses.push_back(Inst);
+ }
+ if (Uses.size() < 2)
+ continue;
+
+ Changed = true;
+ Instruction *NextI = Cond->getNextNonDebugInstruction();
+ assert(NextI);
+ FunctionType *AsmTy = FunctionType::get(Cond->getType(), {Cond->getType()}, false);
+ InlineAsm *Asm = InlineAsm::get(AsmTy, StringRef(""), StringRef("=r,0"), true);
+ auto *CI = CallInst::Create(Asm, {Cond}, "", NextI);
+ for (Instruction *Inst : Uses) {
+ Inst->setOperand(0, CI);
+ }
+ }
+
+ return Changed;
+}
+
// Adjust/Optimize the following pattern
// %0 = load i64, i64* @"llvm.bpf_htab:0:0$0:0", align 8
// %1 = getelementptr i8, i8* bitcast (%struct.anon.2* @m_hash to i8*),
@@ -304,6 +360,7 @@
bool Changed = false;
Changed = removePassThroughBuiltin(M);
+ Changed = serializeCond(M);
Changed = optimizeReloc(M) || Changed;
return false;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D87428.290862.patch
Type: text/x-patch
Size: 2496 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20200910/53c4953a/attachment.bin>
More information about the llvm-commits
mailing list