[ScalarEvolution] Handle addrec incoming value in isImpliedViaMerge() (#126236)

The code already guards against values coming from a previous iteration
using properlyDominates(). However, addrecs are considered to properly
dominate the loop they are defined in.

Handle this special case separately, by checking for expressions that
have computable loop evolution (this should cover cases like a zext of
an addrec as well).

I considered changing the definition of properlyDominates() instead, but
decided against it. The current definition is useful in other context,
e.g. when deciding whether an expression is safe to expand in a given
block.

Fixes https://github.com/llvm/llvm-project/issues/126012.
This commit is contained in:
Nikita Popov 2025-02-10 10:07:21 +01:00 committed by GitHub
parent 52a02b6d1e
commit 7aed53eb19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 13 additions and 3 deletions

View File

@ -12400,6 +12400,12 @@ bool ScalarEvolution::isImpliedViaMerge(CmpPredicate Pred, const SCEV *LHS,
// iteration of a loop.
if (!properlyDominates(L, LBB))
return false;
// Addrecs are considered to properly dominate their loop, so are missed
// by the previous check. Discard any values that have computable
// evolution in this loop.
if (auto *Loop = LI.getLoopFor(LBB))
if (hasComputableLoopEvolution(L, Loop))
return false;
if (!ProvedEasily(L, RHS))
return false;
}

View File

@ -1,18 +1,22 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -S -passes=indvars < %s | FileCheck %s
; FIXME: This is a miscompile.
; Do not infer that %cmp is true. The %indvar3 input of %indvar2 comes from
; a previous iteration, so we should not compare it to a value from the current
; iteration.
define i32 @test() {
; CHECK-LABEL: define i32 @test() {
; CHECK-NEXT: [[ENTRY:.*]]:
; CHECK-NEXT: br label %[[FOR_PREHEADER:.*]]
; CHECK: [[FOR_PREHEADER]]:
; CHECK-NEXT: [[INDVAR1:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[PHI:%.*]], %[[FOR_INC:.*]] ]
; CHECK-NEXT: [[INDVAR3:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[INC:%.*]], %[[FOR_INC]] ]
; CHECK-NEXT: [[INDVAR2:%.*]] = phi i32 [ 1, %[[ENTRY]] ], [ [[INDVAR3:%.*]], %[[FOR_INC]] ]
; CHECK-NEXT: [[INDVAR3]] = phi i32 [ 0, %[[ENTRY]] ], [ [[INC:%.*]], %[[FOR_INC]] ]
; CHECK-NEXT: [[COND1:%.*]] = icmp eq i32 [[INDVAR3]], 0
; CHECK-NEXT: br i1 [[COND1]], label %[[FOR_INC]], label %[[FOR_END:.*]]
; CHECK: [[FOR_END]]:
; CHECK-NEXT: [[EXT:%.*]] = zext i1 true to i32
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[INDVAR2]], 0
; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: br label %[[FOR_INC]]
; CHECK: [[FOR_INC]]:
; CHECK-NEXT: [[PHI]] = phi i32 [ [[EXT]], %[[FOR_END]] ], [ 0, %[[FOR_PREHEADER]] ]