[llvm] [SCEV] Commute sign extends through nsw multiplication (PR #163840)

Alireza Torabian via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 16 11:26:38 PDT 2025


https://github.com/1997alireza created https://github.com/llvm/llvm-project/pull/163840

When NSW flag is present, SCEV simplifies sext((A * B * ...)<nsw>) to (sext(A) * sext(B) * ...)<nsw>.

>From bad74244a055ccda65e39e63f90d689dd0c6d3f4 Mon Sep 17 00:00:00 2001
From: a00917109 <alireza.torabian at huawei.com>
Date: Thu, 16 Oct 2025 14:20:55 -0400
Subject: [PATCH] [SCEV] Commute sign extends through nsw multiplication

When NSW flag is present, SCEV simplifies sext((A * B * ...)<nsw>) to
(sext(A) * sext(B) * ...)<nsw>.
---
 llvm/lib/Analysis/ScalarEvolution.cpp | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index a64b93d541943..bf7c214a78954 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1988,6 +1988,20 @@ const SCEV *ScalarEvolution::getSignExtendExprImpl(const SCEV *Op, Type *Ty,
       }
     }
   }
+
+  if (auto *SA = dyn_cast<SCEVMulExpr>(Op)) {
+    // sext((A * B * ...)<nsw>) --> (sext(A) * sext(B) * ...)<nsw>
+    if (SA->hasNoSignedWrap()) {
+      // If the multiplication does not sign overflow then we can, by
+      // definition, commute the sign extension with the multiplication
+      // operation.
+      SmallVector<const SCEV *, 4> Ops;
+      for (const auto *Op : SA->operands())
+        Ops.push_back(getSignExtendExpr(Op, Ty, Depth + 1));
+      return getMulExpr(Ops, SCEV::FlagNSW, Depth + 1);
+    }
+  }
+
   // If the input value is a chrec scev, and we can prove that the value
   // did not overflow the old, smaller, value, we can sign extend all of the
   // operands (often constants).  This allows analysis of something like



More information about the llvm-commits mailing list