Skip to content

Commit

Permalink
[JumpThreading] Don't phi translate past loop phi (#70664)
Browse files Browse the repository at this point in the history
When evaluating comparisons in predecessors, phi operands are translated
into the predecessor. If the translation is across a backedge, this
means that the two operands of the icmp will be from two different loop
iterations, resulting in incorrect simplification.

Fix this by not performing the phi translation for phis in loop headers.

Note: This is not a complete fix. If the
jump-threading-across-loop-headers option is enabled, the LoopHeaders
variable does not get populated. Additional changes will be needed to
fix that case.

Related to #70651.
  • Loading branch information
nikic committed Oct 31, 2023
1 parent 33b8586 commit 75881db
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/Scalar/JumpThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,10 @@ bool JumpThreadingPass::computeValueKnownInPredecessorsImpl(
PHINode *PN = dyn_cast<PHINode>(CmpLHS);
if (!PN)
PN = dyn_cast<PHINode>(CmpRHS);
if (PN && PN->getParent() == BB) {
// Do not perform phi translation across a loop header phi, because this
// may result in comparison of values from two different loop iterations.
// FIXME: This check is broken if LoopHeaders is not populated.
if (PN && PN->getParent() == BB && !LoopHeaders.contains(BB)) {
const DataLayout &DL = PN->getModule()->getDataLayout();
// We can do this simplification if any comparisons fold to true or false.
// See if any do.
Expand Down
19 changes: 17 additions & 2 deletions llvm/test/Transforms/JumpThreading/pr70651.ll
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
; RUN: opt -S -passes=jump-threading < %s | FileCheck %s
; RUN: opt -S -passes=jump-threading -jump-threading-across-loop-headers < %s | FileCheck %s --check-prefix=THREAD-LOOP

; FIXME: This is a miscompile.
; FIXME: This is a miscompile if -jump-threading-across-loop-headers is enabled.
define i64 @test(i64 %v) {
; CHECK-LABEL: define i64 @test(
; CHECK-SAME: i64 [[V:%.*]]) {
Expand All @@ -12,10 +13,24 @@ define i64 @test(i64 %v) {
; CHECK-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[FOR_BODY]] ]
; CHECK-NEXT: [[SUM_NEXT]] = add i64 [[SUM]], [[V]]
; CHECK-NEXT: [[OVERFLOW:%.*]] = icmp ult i64 [[SUM_NEXT]], [[SUM]]
; CHECK-NEXT: br i1 [[V_NONNEG]], label [[FOR_BODY]], label [[EXIT:%.*]]
; CHECK-NEXT: [[CMP:%.*]] = xor i1 [[V_NONNEG]], [[OVERFLOW]]
; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[EXIT:%.*]]
; CHECK: exit:
; CHECK-NEXT: ret i64 [[SUM]]
;
; THREAD-LOOP-LABEL: define i64 @test(
; THREAD-LOOP-SAME: i64 [[V:%.*]]) {
; THREAD-LOOP-NEXT: entry:
; THREAD-LOOP-NEXT: [[V_NONNEG:%.*]] = icmp sgt i64 [[V]], -1
; THREAD-LOOP-NEXT: br label [[FOR_BODY:%.*]]
; THREAD-LOOP: for.body:
; THREAD-LOOP-NEXT: [[SUM:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[SUM_NEXT:%.*]], [[FOR_BODY]] ]
; THREAD-LOOP-NEXT: [[SUM_NEXT]] = add i64 [[SUM]], [[V]]
; THREAD-LOOP-NEXT: [[OVERFLOW:%.*]] = icmp ult i64 [[SUM_NEXT]], [[SUM]]
; THREAD-LOOP-NEXT: br i1 [[V_NONNEG]], label [[FOR_BODY]], label [[EXIT:%.*]]
; THREAD-LOOP: exit:
; THREAD-LOOP-NEXT: ret i64 [[SUM]]
;
entry:
%v.nonneg = icmp sgt i64 %v, -1
br label %for.body
Expand Down

0 comments on commit 75881db

Please sign in to comment.