[llvm] [polly] [SCEV] Introduce SDiv expressions (PR #216862)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 20:48:54 PDT 2026


================
@@ -3499,36 +3514,56 @@ const SCEV *ScalarEvolution::getURemExpr(SCEVUse LHS, SCEVUse RHS) {
 
 /// Get a canonical unsigned division expression, or something simpler if
 /// possible.
-const SCEV *ScalarEvolution::getUDivExpr(SCEVUse LHS, SCEVUse RHS) {
+const SCEV *ScalarEvolution::getDivExpr(bool IsSigned, SCEVUse LHS,
+                                        SCEVUse RHS) {
   assert(!LHS->getType()->isPointerTy() &&
-         "SCEVUDivExpr operand can't be pointer!");
+         "SCEVDivExpr operand can't be pointer!");
   assert(LHS->getType() == RHS->getType() &&
-         "SCEVUDivExpr operand types don't match!");
+         "SCEVDivExpr operand types don't match!");
 
-  if (SCEV *S =
-          findExistingSCEVInCache(scUDivExpr, ArrayRef<SCEVUse>({LHS, RHS})))
+  if (SCEV *S = findExistingSCEVInCache(IsSigned ? scSDivExpr : scUDivExpr,
+                                        ArrayRef<SCEVUse>({LHS, RHS})))
     return S;
 
-  // 0 udiv Y == 0
+  auto AnyExtend = [&](const SCEV *S, Type *Ty) {
+    return IsSigned ? getSignExtendExpr(S, Ty) : getZeroExtendExpr(S, Ty);
+  };
+
+  if (IsSigned && isKnownNonNegative(LHS) && isKnownNonNegative(RHS))
+    return getDivExpr(false, LHS, RHS);
+
+  // 0/y --> 0
   if (match(LHS, m_scev_Zero()))
     return LHS;
 
   if (const SCEVConstant *RHSC = dyn_cast<SCEVConstant>(RHS)) {
     if (RHSC->getValue()->isOne())
-      return LHS;                               // X udiv 1 --> x
-    // If the denominator is zero, the result of the udiv is undefined. Don't
-    // try to analyze it, because the resolution chosen here may differ from
-    // the resolution chosen in other parts of the compiler.
-    if (!RHSC->getValue()->isZero()) {
+      return LHS; // x/1 --> x
+    // If the denominator is zero, the result of the both udiv and sdiv are
+    // undefined. Similarly if the denominator of is -1, and the numerator is
+    // INT_MIN, sdiv is undefined. Don't try to analyze it, because the
+    // resolution chosen here may differ from the resolution chosen in other
+    // parts of the compiler.
+    Type *Ty = LHS->getType();
+    unsigned BW = Ty->getIntegerBitWidth();
+    bool DivIsUndefined = RHSC->getValue()->isZero();
+    bool SDivIsUndefined =
+        RHSC->getValue()->isAllOnesValue() &&
+        getSignedRangeMin(LHS) == APInt::getSignedMinValue(BW);
+    if (!DivIsUndefined && (!IsSigned || !SDivIsUndefined)) {
+      if (IsSigned && RHSC->getValue()->isAllOnesValue())
+        return getNegativeSCEV(LHS); // x/-1 --> -x
+
       // Determine if the division can be folded into the operands of
       // its operands.
       // TODO: Generalize this to non-constants by using known-bits information.
-      Type *Ty = LHS->getType();
-      unsigned LZ = RHSC->getAPInt().countl_zero();
+      unsigned LZ = IsSigned ? RHSC->getAPInt().countl_one()
----------------
artagnon wrote:

The code should be gone now.

https://github.com/llvm/llvm-project/pull/216862


More information about the llvm-commits mailing list