diff --git a/llvm/lib/Transforms/Scalar/JumpThreading.cpp b/llvm/lib/Transforms/Scalar/JumpThreading.cpp index f2b9d784ead8a..7a8128c5b6c09 100644 --- a/llvm/lib/Transforms/Scalar/JumpThreading.cpp +++ b/llvm/lib/Transforms/Scalar/JumpThreading.cpp @@ -761,7 +761,10 @@ bool JumpThreadingPass::computeValueKnownInPredecessorsImpl( PHINode *PN = dyn_cast(CmpLHS); if (!PN) PN = dyn_cast(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. diff --git a/llvm/test/Transforms/JumpThreading/pr70651.ll b/llvm/test/Transforms/JumpThreading/pr70651.ll index a156be541874a..2c6059bfdb3d5 100644 --- a/llvm/test/Transforms/JumpThreading/pr70651.ll +++ b/llvm/test/Transforms/JumpThreading/pr70651.ll @@ -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:%.*]]) { @@ -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