[llvm-branch-commits] [llvm] release/20.x: [ScalarEvolution] Handle addrec incoming value in isImpliedViaMerge() (#126236) (PR #126492)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Feb 10 01:38:18 PST 2025


https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/126492

Backport ae08969a2068dd327fbf4d0f606550574fbb9e45 7aed53eb1982113e825534f0f66d0a0e46e7a5ed

Requested by: @nikic

>From 4b9b2830f11c3d3e397d150164b1525bdefa75ae Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 7 Feb 2025 12:41:06 +0100
Subject: [PATCH 1/2] [IndVars] Add test for #126012 (NFC)

(cherry picked from commit ae08969a2068dd327fbf4d0f606550574fbb9e45)
---
 .../Transforms/IndVarSimplify/pr126012.ll     | 49 +++++++++++++++++++
 1 file changed, 49 insertions(+)
 create mode 100644 llvm/test/Transforms/IndVarSimplify/pr126012.ll

diff --git a/llvm/test/Transforms/IndVarSimplify/pr126012.ll b/llvm/test/Transforms/IndVarSimplify/pr126012.ll
new file mode 100644
index 000000000000000..725ea89b8e65189
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/pr126012.ll
@@ -0,0 +1,49 @@
+; 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.
+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:    [[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:    br label %[[FOR_INC]]
+; CHECK:       [[FOR_INC]]:
+; CHECK-NEXT:    [[PHI]] = phi i32 [ [[EXT]], %[[FOR_END]] ], [ 0, %[[FOR_PREHEADER]] ]
+; CHECK-NEXT:    [[INC]] = add nuw nsw i32 [[INDVAR3]], 1
+; CHECK-NEXT:    [[EXITCOND:%.*]] = icmp eq i32 [[INDVAR3]], 2
+; CHECK-NEXT:    br i1 [[EXITCOND]], label %[[FOR_EXIT:.*]], label %[[FOR_PREHEADER]]
+; CHECK:       [[FOR_EXIT]]:
+; CHECK-NEXT:    [[INDVAR1_LCSSA:%.*]] = phi i32 [ [[INDVAR1]], %[[FOR_INC]] ]
+; CHECK-NEXT:    ret i32 [[INDVAR1_LCSSA]]
+;
+entry:
+  br label %for.preheader
+
+for.preheader:
+  %indvar1 = phi i32 [ 0, %entry ], [ %phi, %for.inc ]
+  %indvar2 = phi i32 [ 1, %entry ], [ %indvar3, %for.inc ]
+  %indvar3 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]
+  %cond1 = icmp eq i32 %indvar3, 0
+  br i1 %cond1, label %for.inc, label %for.end
+
+for.end:
+  %cmp = icmp sgt i32 %indvar2, 0
+  %ext = zext i1 %cmp to i32
+  br label %for.inc
+
+for.inc:
+  %phi = phi i32 [ %ext, %for.end ], [ 0, %for.preheader ]
+  %inc = add i32 %indvar3, 1
+  %exitcond = icmp eq i32 %indvar3, 2
+  br i1 %exitcond, label %for.exit, label %for.preheader
+
+for.exit:
+  ret i32 %indvar1
+}

>From 5d5f8d3b9273236ce73bf547f7f80d41be93fe62 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Mon, 10 Feb 2025 10:07:21 +0100
Subject: [PATCH 2/2] [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.

(cherry picked from commit 7aed53eb1982113e825534f0f66d0a0e46e7a5ed)
---
 llvm/lib/Analysis/ScalarEvolution.cpp           |  6 ++++++
 llvm/test/Transforms/IndVarSimplify/pr126012.ll | 10 +++++++---
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 2ce40877b523e10..c71202c8dd58e4d 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -12402,6 +12402,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;
     }
diff --git a/llvm/test/Transforms/IndVarSimplify/pr126012.ll b/llvm/test/Transforms/IndVarSimplify/pr126012.ll
index 725ea89b8e65189..5189fe020dd3bfd 100644
--- a/llvm/test/Transforms/IndVarSimplify/pr126012.ll
+++ b/llvm/test/Transforms/IndVarSimplify/pr126012.ll
@@ -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]] ]



More information about the llvm-branch-commits mailing list