| commit 1da9834557cd4302a5183b8228ce063e69f82602 |
| Author: Roman Lebedev <lebedev.ri@gmail.com> |
| Date: Mon Jul 27 15:07:51 2020 +0300 |
| |
| [JumpThreading] ProcessBranchOnXOR(): bailout if any pred ends in indirect branch (PR46857) |
| |
| SplitBlockPredecessors() can not split blocks that have such terminators, |
| and in two other places we already ensure that we don't end up calling |
| SplitBlockPredecessors() on such blocks. Do so in one more place. |
| |
| Fixes https://bugs.llvm.org/show_bug.cgi?id=46857 |
| |
| diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp |
| index 9d0500419a7..2f379b7f616 100644 |
| --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp |
| +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp |
| @@ -1859,6 +1859,14 @@ bool JumpThreadingPass::ProcessBranchOnXOR(BinaryOperator *BO) { |
| return true; |
| } |
| |
| + // If any of predecessors end with an indirect goto, we can't change its |
| + // destination. Same for CallBr. |
| + if (any_of(BlocksToFoldInto, [](BasicBlock *Pred) { |
| + return isa<IndirectBrInst>(Pred->getTerminator()) || |
| + isa<CallBrInst>(Pred->getTerminator()); |
| + })) |
| + return false; |
| + |
| // Try to duplicate BB into PredBB. |
| return DuplicateCondBranchOnPHIIntoPred(BB, BlocksToFoldInto); |
| } |
| diff --git a/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll |
| new file mode 100644 |
| index 00000000000..3de7d626513 |
| --- /dev/null |
| +++ b/llvm/test/Transforms/JumpThreading/pr46857-callbr.ll |
| @@ -0,0 +1,52 @@ |
| +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| +; RUN: opt < %s -jump-threading -S | FileCheck %s |
| + |
| +; CHECK-ALL-LABEL: @func( |
| + |
| +define i1 @func(i1 %arg, i32 %arg1, i1 %arg2) { |
| +; CHECK-LABEL: @func( |
| +; CHECK-NEXT: bb: |
| +; CHECK-NEXT: br i1 [[ARG:%.*]], label [[BB3:%.*]], label [[BB4:%.*]] |
| +; CHECK: bb3: |
| +; CHECK-NEXT: [[I:%.*]] = icmp eq i32 [[ARG1:%.*]], 0 |
| +; CHECK-NEXT: br label [[BB7:%.*]] |
| +; CHECK: bb4: |
| +; CHECK-NEXT: callbr void asm sideeffect "", "X"(i8* blockaddress(@func, [[BB7]])) |
| +; CHECK-NEXT: to label [[BB5:%.*]] [label %bb7] |
| +; CHECK: bb5: |
| +; CHECK-NEXT: br label [[BB7]] |
| +; CHECK: bb7: |
| +; CHECK-NEXT: [[I8:%.*]] = phi i1 [ [[I]], [[BB3]] ], [ [[ARG2:%.*]], [[BB5]] ], [ [[ARG2]], [[BB4]] ] |
| +; CHECK-NEXT: [[I9:%.*]] = xor i1 [[I8]], [[ARG]] |
| +; CHECK-NEXT: br i1 [[I9]], label [[BB11:%.*]], label [[BB11]] |
| +; CHECK: bb11: |
| +; CHECK-NEXT: ret i1 [[I9]] |
| +; |
| +bb: |
| + br i1 %arg, label %bb3, label %bb4 |
| + |
| +bb3: |
| + %i = icmp eq i32 %arg1, 0 |
| + br label %bb7 |
| + |
| +bb4: |
| + callbr void asm sideeffect "", "X"(i8* blockaddress(@func, %bb6)) |
| + to label %bb5 [label %bb6] |
| + |
| +bb5: |
| + br label %bb6 |
| + |
| +bb6: |
| + br label %bb7 |
| + |
| +bb7: |
| + %i8 = phi i1 [ %i, %bb3 ], [ %arg2, %bb6 ] |
| + %i9 = xor i1 %i8, %arg |
| + br i1 %i9, label %bb11, label %bb10 |
| + |
| +bb10: |
| + br label %bb11 |
| + |
| +bb11: |
| + ret i1 %i9 |
| +} |