[llvm] r357930 - [JumpThreading] Fix incorrect fold conditional after indirectbr/callbr

Brian M. Rzycki via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 8 11:20:35 PDT 2019


Author: brzycki
Date: Mon Apr  8 11:20:35 2019
New Revision: 357930

URL: http://llvm.org/viewvc/llvm-project?rev=357930&view=rev
Log:
[JumpThreading] Fix incorrect fold conditional after indirectbr/callbr

Fixes bug 40992: https://bugs.llvm.org/show_bug.cgi?id=40992

There is potential for miscompiled code emitted from JumpThreading when
analyzing a block with one or more indirectbr or callbr predecessors. The
ProcessThreadableEdges() function incorrectly folds conditional branches
into an unconditional branch.

This patch prevents incorrect branch folding without fully pessimizing
other potential threading opportunities through the same basic block.

This IR shape was manually fed in via opt and is unclear if clang and the
full pass pipeline will ever emit similar code shapes.

Thanks to Matthias Liedtke for the bug report and simplified IR example.

Differential Revision: https://reviews.llvm.org/D60284

Added:
    llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp?rev=357930&r1=357929&r2=357930&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/JumpThreading.cpp Mon Apr  8 11:20:35 2019
@@ -1606,7 +1606,6 @@ bool JumpThreadingPass::ProcessThreadabl
   Constant *OnlyVal = nullptr;
   Constant *MultipleVal = (Constant *)(intptr_t)~0ULL;
 
-  unsigned PredWithKnownDest = 0;
   for (const auto &PredValue : PredValues) {
     BasicBlock *Pred = PredValue.second;
     if (!SeenPreds.insert(Pred).second)
@@ -1643,9 +1642,6 @@ bool JumpThreadingPass::ProcessThreadabl
         OnlyVal = MultipleVal;
     }
 
-    // We know where this predecessor is going.
-    ++PredWithKnownDest;
-
     // If the predecessor ends with an indirect goto, we can't change its
     // destination. Same for CallBr.
     if (isa<IndirectBrInst>(Pred->getTerminator()) ||
@@ -1663,7 +1659,7 @@ bool JumpThreadingPass::ProcessThreadabl
   // not thread. By doing so, we do not need to duplicate the current block and
   // also miss potential opportunities in case we dont/cant duplicate.
   if (OnlyDest && OnlyDest != MultipleDestSentinel) {
-    if (PredWithKnownDest == (size_t)pred_size(BB)) {
+    if (BB->hasNPredecessors(PredToDestList.size())) {
       bool SeenFirstBranchToOnlyDest = false;
       std::vector <DominatorTree::UpdateType> Updates;
       Updates.reserve(BB->getTerminator()->getNumSuccessors() - 1);

Added: llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll?rev=357930&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll (added)
+++ llvm/trunk/test/Transforms/JumpThreading/pr40992-indirectbr-folding.ll Mon Apr  8 11:20:35 2019
@@ -0,0 +1,44 @@
+; RUN: opt -S < %s -jump-threading | FileCheck %s
+
+; PR40992: Do not incorrectly fold %bb5 into an unconditional br to %bb7.
+;          Also verify we correctly thread %bb1 -> %bb7 when %c is false.
+
+define i32 @jtbr(i1 %v1, i1 %v2, i1 %v3) {
+; CHECK: bb0:
+bb0:
+  br label %bb1
+
+; CHECK: bb1:
+; CHECK-NEXT: and
+; CHECK-NEXT: br i1 %c, label %bb2, label %bb7
+bb1:
+  %c = and i1 %v1, %v2
+  br i1 %c, label %bb2, label %bb5
+
+; CHECK: bb2:
+; CHECK-NEXT: select
+; CHECK-NEXT: indirectbr i8* %ba, [label %bb3, label %bb5]
+bb2:
+  %ba = select i1 %v3, i8* blockaddress(@jtbr, %bb3), i8* blockaddress(@jtbr, %bb4)
+  indirectbr i8* %ba, [label %bb3, label %bb4]
+
+; CHECK: bb3:
+bb3:
+  br label %bb1
+
+; CHECK-NOT: bb4:
+bb4:
+  br label %bb5
+
+; CHECK: bb5:
+bb5:
+  br i1 %c, label %bb6, label %bb7
+
+; CHECK: bb6:
+bb6:
+  ret i32 0
+
+; CHECK: bb7:
+bb7:
+  ret i32 1
+}




More information about the llvm-commits mailing list