[llvm] 9e6aa81 - [BPF] Fix a recursion bug in BPF Peephole ZEXT optimization
Yonghong Song via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 22 08:08:19 PST 2019
Author: Yonghong Song
Date: 2019-11-22T08:05:43-08:00
New Revision: 9e6aa81588505461e06c807c567b073224f1e817
URL: https://github.com/llvm/llvm-project/commit/9e6aa81588505461e06c807c567b073224f1e817
DIFF: https://github.com/llvm/llvm-project/commit/9e6aa81588505461e06c807c567b073224f1e817.diff
LOG: [BPF] Fix a recursion bug in BPF Peephole ZEXT optimization
Commit a0841dfe8594 ("[BPF] Fix a bug in peephole optimization")
fixed a bug in peephole optimization. Recursion is introduced
to handle COPY and PHI instructions.
Unfortunately, multiple PHI instructions may form a cycle
and this will cause infinite recursion, eventual segfault.
For Commit a0841dfe8594, I indeed tried a few loops to ensure
that I won't see the recursion, but I did not try with
complex control flows, which, as demonstrated with the test case
in this patch, may introduce PHI cycles.
This patch fixed the issue by introducing a set to remember
visited PHI instructions. This way, cycles can be properly
detected and handled.
Differential Revision: https://reviews.llvm.org/D70586
Added:
llvm/test/CodeGen/BPF/32-bit-subreg-peephole-phi-3.ll
Modified:
llvm/lib/Target/BPF/BPFMIPeephole.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/BPF/BPFMIPeephole.cpp b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
index c0f99fa2b449..022267fbe3c2 100644
--- a/llvm/lib/Target/BPF/BPFMIPeephole.cpp
+++ b/llvm/lib/Target/BPF/BPFMIPeephole.cpp
@@ -57,6 +57,8 @@ struct BPFMIPeephole : public MachineFunctionPass {
bool isMovFrom32Def(MachineInstr *MovMI);
bool eliminateZExtSeq(void);
+ std::set<MachineInstr *> PhiInsns;
+
public:
// Main entry point for this pass.
@@ -113,8 +115,13 @@ bool BPFMIPeephole::isPhiFrom32Def(MachineInstr *PhiMI)
MachineInstr *PhiDef = MRI->getVRegDef(opnd.getReg());
if (!PhiDef)
return false;
- if (PhiDef->isPHI() && !isPhiFrom32Def(PhiDef))
- return false;
+ if (PhiDef->isPHI()) {
+ if (PhiInsns.find(PhiDef) != PhiInsns.end())
+ return false;
+ PhiInsns.insert(PhiDef);
+ if (!isPhiFrom32Def(PhiDef))
+ return false;
+ }
if (PhiDef->getOpcode() == BPF::COPY && !isCopyFrom32Def(PhiDef))
return false;
}
@@ -129,6 +136,9 @@ bool BPFMIPeephole::isInsnFrom32Def(MachineInstr *DefInsn)
return false;
if (DefInsn->isPHI()) {
+ if (PhiInsns.find(DefInsn) != PhiInsns.end())
+ return false;
+ PhiInsns.insert(DefInsn);
if (!isPhiFrom32Def(DefInsn))
return false;
} else if (DefInsn->getOpcode() == BPF::COPY) {
@@ -146,6 +156,7 @@ bool BPFMIPeephole::isMovFrom32Def(MachineInstr *MovMI)
LLVM_DEBUG(dbgs() << " Def of Mov Src:");
LLVM_DEBUG(DefInsn->dump());
+ PhiInsns.clear();
if (!isInsnFrom32Def(DefInsn))
return false;
diff --git a/llvm/test/CodeGen/BPF/32-bit-subreg-peephole-phi-3.ll b/llvm/test/CodeGen/BPF/32-bit-subreg-peephole-phi-3.ll
new file mode 100644
index 000000000000..d46214032e6e
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/32-bit-subreg-peephole-phi-3.ll
@@ -0,0 +1,52 @@
+; RUN: llc -O2 -march=bpfel -mcpu=v2 -mattr=+alu32 < %s | FileCheck %s
+;
+; For the below example, two phi node in the loop may depend on
+; each other. So implementation must handle recursion properly.
+;
+; int test(unsigned long a, unsigned long b, unsigned long c) {
+; int val = 0;
+;
+; #pragma clang loop unroll(disable)
+; for (long i = 0; i < 100; i++) {
+; if (a > b)
+; val = 1;
+; a += b;
+; if (b > c)
+; val = 1;
+; b += c;
+; }
+;
+; return val == 0 ? 1 : 0;
+; }
+
+
+define dso_local i32 @test(i64 %a, i64 %b, i64 %c) local_unnamed_addr {
+entry:
+ br label %for.body
+
+for.cond.cleanup: ; preds = %for.body
+ %cmp6 = icmp eq i32 %val.2, 0
+ %cond = zext i1 %cmp6 to i32
+ ret i32 %cond
+
+for.body: ; preds = %for.body, %entry
+ %i.018 = phi i64 [ 0, %entry ], [ %inc, %for.body ]
+ %val.017 = phi i32 [ 0, %entry ], [ %val.2, %for.body ]
+ %a.addr.016 = phi i64 [ %a, %entry ], [ %add, %for.body ]
+ %b.addr.015 = phi i64 [ %b, %entry ], [ %add5, %for.body ]
+ %cmp1 = icmp ugt i64 %a.addr.016, %b.addr.015
+ %add = add i64 %a.addr.016, %b.addr.015
+ %cmp2 = icmp ugt i64 %b.addr.015, %c
+ %0 = or i1 %cmp2, %cmp1
+ %val.2 = select i1 %0, i32 1, i32 %val.017
+ %add5 = add i64 %b.addr.015, %c
+ %inc = add nuw nsw i64 %i.018, 1
+ %exitcond = icmp eq i64 %inc, 100
+ br i1 %exitcond, label %for.cond.cleanup, label %for.body, !llvm.loop !2
+}
+; CHECK: [[VAL:r[0-9]+]] <<= 32
+; CHECK: [[VAL]] >>= 32
+; CHECK: if [[VAL]] == 0 goto
+
+!2 = distinct !{!2, !3}
+!3 = !{!"llvm.loop.unroll.disable"}
More information about the llvm-commits
mailing list