[llvm] [SCEV] Use ashr to adjust constant multipliers (PR #135534)

Yingwei Zheng via llvm-commits llvm-commits at lists.llvm.org
Sun Apr 13 02:10:58 PDT 2025


https://github.com/dtcxzyw created https://github.com/llvm/llvm-project/pull/135534

SCEV converts "-2 *nsw (i32 V)" into "2148473647 *nsw (i32 V)". But we cannot preserve the nsw flag when the constant multiplier is negative. This patch changes lshr to ashr so that we can preserve both nsw and nuw flags. 

Alive2 proof: https://alive2.llvm.org/ce/z/LZVSEa
Closes https://github.com/llvm/llvm-project/issues/135531.


>From 295b5f3ce447a479b4ea3d002682581b7a8817db Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Apr 2025 16:45:18 +0800
Subject: [PATCH 1/2] [SCEV] Add pre-commit tests. NFC.

---
 .../test/Analysis/ScalarEvolution/pr135531.ll | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 llvm/test/Analysis/ScalarEvolution/pr135531.ll

diff --git a/llvm/test/Analysis/ScalarEvolution/pr135531.ll b/llvm/test/Analysis/ScalarEvolution/pr135531.ll
new file mode 100644
index 0000000000000..5be0060ee8286
--- /dev/null
+++ b/llvm/test/Analysis/ScalarEvolution/pr135531.ll
@@ -0,0 +1,19 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt -disable-output -passes='print<scalar-evolution>' < %s 2>&1 | FileCheck %s
+
+define i32 @pr135511(i32 %x) {
+; CHECK-LABEL: 'pr135511'
+; CHECK-NEXT:  Classifying expressions for: @pr135511
+; CHECK-NEXT:    %and = and i32 %x, 16382
+; CHECK-NEXT:    --> (2 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nuw><nsw> U: [0,16383) S: [0,16383)
+; CHECK-NEXT:    %neg = sub nsw i32 0, %and
+; CHECK-NEXT:    --> (-2 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nsw> U: [0,-1) S: [-16382,1)
+; CHECK-NEXT:    %res = and i32 %neg, 268431360
+; CHECK-NEXT:    --> (4096 * (zext i16 (trunc i32 ((2147483647 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nuw><nsw> /u 2048) to i16) to i32))<nuw><nsw> U: [0,268431361) S: [0,268431361)
+; CHECK-NEXT:  Determining loop execution counts for: @pr135511
+;
+  %and = and i32 %x, 16382
+  %neg = sub nsw i32 0, %and
+  %res = and i32 %neg, 268431360
+  ret i32 %res
+}

>From 26ffed0bc8ff5bca496e1d25b2c89c628a3150a1 Mon Sep 17 00:00:00 2001
From: Yingwei Zheng <dtcxzyw2333 at gmail.com>
Date: Sun, 13 Apr 2025 16:59:59 +0800
Subject: [PATCH 2/2] [SCEV] Use ashr to adjust constant multipliers

---
 llvm/lib/Analysis/ScalarEvolution.cpp          | 2 +-
 llvm/test/Analysis/ScalarEvolution/pr135531.ll | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c62ea1526981d..d193c9e3210ea 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -7841,7 +7841,7 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) {
               unsigned GCD = std::min(MulZeros, TZ);
               APInt DivAmt = APInt::getOneBitSet(BitWidth, TZ - GCD);
               SmallVector<const SCEV*, 4> MulOps;
-              MulOps.push_back(getConstant(OpC->getAPInt().lshr(GCD)));
+              MulOps.push_back(getConstant(OpC->getAPInt().ashr(GCD)));
               append_range(MulOps, LHSMul->operands().drop_front());
               auto *NewMul = getMulExpr(MulOps, LHSMul->getNoWrapFlags());
               ShiftedLHS = getUDivExpr(NewMul, getConstant(DivAmt));
diff --git a/llvm/test/Analysis/ScalarEvolution/pr135531.ll b/llvm/test/Analysis/ScalarEvolution/pr135531.ll
index 5be0060ee8286..e172d56d3a515 100644
--- a/llvm/test/Analysis/ScalarEvolution/pr135531.ll
+++ b/llvm/test/Analysis/ScalarEvolution/pr135531.ll
@@ -9,7 +9,7 @@ define i32 @pr135511(i32 %x) {
 ; CHECK-NEXT:    %neg = sub nsw i32 0, %and
 ; CHECK-NEXT:    --> (-2 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nsw> U: [0,-1) S: [-16382,1)
 ; CHECK-NEXT:    %res = and i32 %neg, 268431360
-; CHECK-NEXT:    --> (4096 * (zext i16 (trunc i32 ((2147483647 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nuw><nsw> /u 2048) to i16) to i32))<nuw><nsw> U: [0,268431361) S: [0,268431361)
+; CHECK-NEXT:    --> (4096 * (zext i16 (trunc i32 ((-1 * (zext i13 (trunc i32 (%x /u 2) to i13) to i32))<nsw> /u 2048) to i16) to i32))<nuw><nsw> U: [0,268431361) S: [0,268431361)
 ; CHECK-NEXT:  Determining loop execution counts for: @pr135511
 ;
   %and = and i32 %x, 16382



More information about the llvm-commits mailing list