[llvm] [SCEVAA] Allowing to subtract two inttoptrs with different pointer bases (PR #91453)

via llvm-commits llvm-commits at lists.llvm.org
Tue May 28 20:43:34 PDT 2024


https://github.com/csstormq updated https://github.com/llvm/llvm-project/pull/91453

>From c2a51bca821c665af8a3ae96559628c00b3bf32d Mon Sep 17 00:00:00 2001
From: XiaoQiang Xu <swust_xiaoqiangxu at 163.com>
Date: Wed, 8 May 2024 17:45:53 +0800
Subject: [PATCH 1/4] [SCEVAA] Allowing to subtract two inttoptrs with
 different pointer bases

---
 llvm/include/llvm/Analysis/ScalarEvolution.h  | 25 +++++
 llvm/lib/Analysis/ScalarEvolution.cpp         | 98 ++++++++++++++++++-
 .../Analysis/ScalarEvolutionAliasAnalysis.cpp | 22 +++--
 llvm/test/Analysis/ScalarEvolution/scev-aa.ll | 26 +++++
 4 files changed, 158 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 72f3d94542496..17b2bcfe9045d 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -721,6 +721,11 @@ class ScalarEvolution {
   const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty,
                                       unsigned Depth = 0);
 
+  /// Return a SCEV corresponding to a conversion of the input value to the
+  /// specified type.  If the type must be extended, it is any extended.
+  const SCEV *getTruncateOrAnyExtend(const SCEV *V, Type *Ty,
+                                     unsigned Depth = 0);
+
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is zero extended.  The
   /// conversion must not be narrowing.
@@ -754,6 +759,26 @@ class ScalarEvolution {
   const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
                                          bool Sequential = false);
 
+  /// Promote the operands to the wider of the types using any-extension, and
+  /// then perform a addrec operation with them.
+  const SCEV *
+  getAddRecExprFromMismatchedTypes(const SmallVectorImpl<const SCEV *> &Ops,
+                                   const Loop *L, SCEV::NoWrapFlags Flags);
+
+  /// Promote the operands to the wider of the types using any-extension, and
+  /// then perform a add operation with them.
+  const SCEV *
+  getAddExprFromMismatchedTypes(const SmallVectorImpl<const SCEV *> &Ops,
+                                SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                                unsigned Depth = 0);
+  const SCEV *
+  getAddExprFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS,
+                                SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
+                                unsigned Depth = 0) {
+    SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
+    return getAddExprFromMismatchedTypes(Ops, Flags, Depth);
+  }
+
   /// Transitively follow the chain of pointer-type operands until reaching a
   /// SCEV that does not have a single pointer operand. This returns a
   /// SCEVUnknown pointer for well-formed pointer-type expressions, but corner
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index e46d7183a2a35..c5cc416dd2ad1 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4650,7 +4650,8 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
     Ops[0] = removePointerBase(Ops[0]);
     // Don't try to transfer nowrap flags for now. We could in some cases
     // (for example, if pointer operand of the AddRec is a SCEVUnknown).
-    return getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap);
+    return getAddRecExprFromMismatchedTypes(Ops, AddRec->getLoop(),
+                                            SCEV::FlagAnyWrap);
   }
   if (auto *Add = dyn_cast<SCEVAddExpr>(P)) {
     // The base of an Add is the pointer operand.
@@ -4665,12 +4666,31 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
     *PtrOp = removePointerBase(*PtrOp);
     // Don't try to transfer nowrap flags for now. We could in some cases
     // (for example, if the pointer operand of the Add is a SCEVUnknown).
-    return getAddExpr(Ops);
+    return getAddExprFromMismatchedTypes(Ops);
   }
+
+  if (auto *Unknown = dyn_cast<SCEVUnknown>(P)) {
+    if (auto *O = dyn_cast<Operator>(Unknown->getValue())) {
+      if (O->getOpcode() == Instruction::IntToPtr) {
+        Value *Op0 = O->getOperand(0);
+        if (isa<ConstantInt>(Op0))
+          return getConstant(dyn_cast<ConstantInt>(Op0));
+        return getSCEV(Op0);
+      }
+    }
+  }
+
   // Any other expression must be a pointer base.
   return getZero(P->getType());
 }
 
+static bool isIntToPtr(const SCEV *V) {
+  if (auto *Unknown = dyn_cast<SCEVUnknown>(V))
+    if (auto *Op = dyn_cast<Operator>(Unknown->getValue()))
+      return Op->getOpcode() == Instruction::IntToPtr;
+  return false;
+}
+
 const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
                                           SCEV::NoWrapFlags Flags,
                                           unsigned Depth) {
@@ -4678,12 +4698,15 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
   if (LHS == RHS)
     return getZero(LHS->getType());
 
-  // If we subtract two pointers with different pointer bases, bail.
+  // If we subtract two pointers except inttoptrs with different pointer bases,
+  // bail.
   // Eventually, we're going to add an assertion to getMulExpr that we
   // can't multiply by a pointer.
   if (RHS->getType()->isPointerTy()) {
+    const SCEV *LBase = getPointerBase(LHS);
+    const SCEV *RBase = getPointerBase(RHS);
     if (!LHS->getType()->isPointerTy() ||
-        getPointerBase(LHS) != getPointerBase(RHS))
+        (LBase != RBase && (!isIntToPtr(LBase) || !isIntToPtr(RBase))))
       return getCouldNotCompute();
     LHS = removePointerBase(LHS);
     RHS = removePointerBase(RHS);
@@ -4718,7 +4741,8 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
   // larger scope than intended.
   auto NegFlags = RHSIsNotMinSigned ? SCEV::FlagNSW : SCEV::FlagAnyWrap;
 
-  return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth);
+  return getAddExprFromMismatchedTypes(LHS, getNegativeSCEV(RHS, NegFlags),
+                                       AddFlags, Depth);
 }
 
 const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
@@ -4745,6 +4769,18 @@ const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
   return getSignExtendExpr(V, Ty, Depth);
 }
 
+const SCEV *ScalarEvolution::getTruncateOrAnyExtend(const SCEV *V, Type *Ty,
+                                                    unsigned Depth) {
+  Type *SrcTy = V->getType();
+  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
+         "Cannot truncate or any extend with non-integer arguments!");
+  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
+    return V; // No conversion
+  if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
+    return getTruncateExpr(V, Ty, Depth);
+  return getAnyExtendExpr(V, Ty);
+}
+
 const SCEV *
 ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) {
   Type *SrcTy = V->getType();
@@ -4839,6 +4875,58 @@ ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
   return getUMinExpr(PromotedOps, Sequential);
 }
 
+const SCEV *ScalarEvolution::getAddRecExprFromMismatchedTypes(
+    const SmallVectorImpl<const SCEV *> &Ops, const Loop *L,
+    SCEV::NoWrapFlags Flags) {
+  assert(!Ops.empty() && "At least one operand must be!");
+  // Trivial case.
+  if (Ops.size() == 1)
+    return Ops[0];
+
+  // Find the max type first.
+  Type *MaxType = nullptr;
+  for (const auto *S : Ops)
+    if (MaxType)
+      MaxType = getWiderType(MaxType, S->getType());
+    else
+      MaxType = S->getType();
+  assert(MaxType && "Failed to find maximum type!");
+
+  // Extend all ops to max type.
+  SmallVector<const SCEV *, 2> PromotedOps;
+  PromotedOps.reserve(Ops.size());
+  for (const auto *S : Ops)
+    PromotedOps.push_back(getNoopOrAnyExtend(S, MaxType));
+
+  return getAddRecExpr(PromotedOps, L, Flags);
+}
+
+const SCEV *ScalarEvolution::getAddExprFromMismatchedTypes(
+    const SmallVectorImpl<const SCEV *> &Ops, SCEV::NoWrapFlags Flags,
+    unsigned Depth) {
+  assert(!Ops.empty() && "At least one operand must be!");
+  // Trivial case.
+  if (Ops.size() == 1)
+    return Ops[0];
+
+  // Find the max type first.
+  Type *MaxType = nullptr;
+  for (const auto *S : Ops)
+    if (MaxType)
+      MaxType = getWiderType(MaxType, S->getType());
+    else
+      MaxType = S->getType();
+  assert(MaxType && "Failed to find maximum type!");
+
+  // Extend all ops to max type.
+  SmallVector<const SCEV *, 2> PromotedOps;
+  PromotedOps.reserve(Ops.size());
+  for (const auto *S : Ops)
+    PromotedOps.push_back(getNoopOrAnyExtend(S, MaxType));
+
+  return getAddExpr(PromotedOps, Flags, Depth);
+}
+
 const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
   // A pointer operand may evaluate to a nonpointer expression, such as null.
   if (!V->getType()->isPointerTy())
diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index af8232b03f1ed..c4e13989e17a2 100644
--- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -67,10 +67,13 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
     // Test whether the difference is known to be great enough that memory of
     // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
     // are non-zero, which is special-cased above.
-    if (!isa<SCEVCouldNotCompute>(BA) &&
-        ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
-        (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
-      return AliasResult::NoAlias;
+    if (!isa<SCEVCouldNotCompute>(BA)) {
+      if (SE.isSCEVable(BA->getType()))
+        BA = SE.getTruncateOrAnyExtend(BA, AS->getType());
+      if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
+          (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
+        return AliasResult::NoAlias;
+    }
 
     // Folding the subtraction while preserving range information can be tricky
     // (because of INT_MIN, etc.); if the prior test failed, swap AS and BS
@@ -82,10 +85,13 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
     // Test whether the difference is known to be great enough that memory of
     // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
     // are non-zero, which is special-cased above.
-    if (!isa<SCEVCouldNotCompute>(AB) &&
-        BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
-        (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
-      return AliasResult::NoAlias;
+    if (!isa<SCEVCouldNotCompute>(AB)) {
+      if (SE.isSCEVable(AB->getType()))
+        AB = SE.getTruncateOrAnyExtend(AB, AS->getType());
+      if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
+          (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
+        return AliasResult::NoAlias;
+    }
   }
 
   // If ScalarEvolution can find an underlying object, form a new query.
diff --git a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
index a81baa73a93bd..5610833e9c474 100644
--- a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
+++ b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
@@ -340,3 +340,29 @@ for.latch:
 for.end:
   ret void
 }
+
+; CHECK-LABEL: Function: test_different_pointer_bases_of_inttoptr: 2 pointers, 0 call sites
+; CHECK:   NoAlias:	<16 x i8>* %tmp5, <16 x i8>* %tmp7
+
+define void @test_different_pointer_bases_of_inttoptr() {
+entry:
+  br label %for.body
+
+for.body:
+  %tmp = phi i32 [ %next, %for.body ], [ 1, %entry ]
+  %tmp1 = shl nsw i32 %tmp, 1
+  %tmp2 = add nuw nsw i32 %tmp1, %tmp1
+  %tmp3 = mul nsw i32 %tmp2, 1408
+  %tmp4 = add nsw i32 %tmp3, 1408
+  %tmp5 = getelementptr inbounds i8, ptr inttoptr (i32 1024 to ptr), i32 %tmp1
+  %tmp6 = load <16 x i8>, ptr %tmp5, align 1
+  %tmp7 = getelementptr inbounds i8, ptr inttoptr (i32 4096 to ptr), i32 %tmp4
+  store <16 x i8> %tmp6, ptr %tmp7, align 1
+
+  %next = add i32 %tmp, 2
+  %exitcond = icmp slt i32 %next, 10
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:
+  ret void
+}

>From de57983b67a1d0230ec883c4faa3e6aa3c47ce00 Mon Sep 17 00:00:00 2001
From: XiaoQiang Xu <swust_xiaoqiangxu at 163.com>
Date: Thu, 9 May 2024 10:22:32 +0800
Subject: [PATCH 2/4] Revert "[SCEVAA] Allowing to subtract two inttoptrs with
 different pointer bases"

This reverts commit 60fd9995ea5cb8ecc07ad4184fffb5203fca8674.
---
 llvm/include/llvm/Analysis/ScalarEvolution.h  | 25 -----
 llvm/lib/Analysis/ScalarEvolution.cpp         | 98 +------------------
 .../Analysis/ScalarEvolutionAliasAnalysis.cpp | 22 ++---
 llvm/test/Analysis/ScalarEvolution/scev-aa.ll | 26 -----
 4 files changed, 13 insertions(+), 158 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 17b2bcfe9045d..72f3d94542496 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -721,11 +721,6 @@ class ScalarEvolution {
   const SCEV *getTruncateOrSignExtend(const SCEV *V, Type *Ty,
                                       unsigned Depth = 0);
 
-  /// Return a SCEV corresponding to a conversion of the input value to the
-  /// specified type.  If the type must be extended, it is any extended.
-  const SCEV *getTruncateOrAnyExtend(const SCEV *V, Type *Ty,
-                                     unsigned Depth = 0);
-
   /// Return a SCEV corresponding to a conversion of the input value to the
   /// specified type.  If the type must be extended, it is zero extended.  The
   /// conversion must not be narrowing.
@@ -759,26 +754,6 @@ class ScalarEvolution {
   const SCEV *getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
                                          bool Sequential = false);
 
-  /// Promote the operands to the wider of the types using any-extension, and
-  /// then perform a addrec operation with them.
-  const SCEV *
-  getAddRecExprFromMismatchedTypes(const SmallVectorImpl<const SCEV *> &Ops,
-                                   const Loop *L, SCEV::NoWrapFlags Flags);
-
-  /// Promote the operands to the wider of the types using any-extension, and
-  /// then perform a add operation with them.
-  const SCEV *
-  getAddExprFromMismatchedTypes(const SmallVectorImpl<const SCEV *> &Ops,
-                                SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                                unsigned Depth = 0);
-  const SCEV *
-  getAddExprFromMismatchedTypes(const SCEV *LHS, const SCEV *RHS,
-                                SCEV::NoWrapFlags Flags = SCEV::FlagAnyWrap,
-                                unsigned Depth = 0) {
-    SmallVector<const SCEV *, 2> Ops = {LHS, RHS};
-    return getAddExprFromMismatchedTypes(Ops, Flags, Depth);
-  }
-
   /// Transitively follow the chain of pointer-type operands until reaching a
   /// SCEV that does not have a single pointer operand. This returns a
   /// SCEVUnknown pointer for well-formed pointer-type expressions, but corner
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index c5cc416dd2ad1..e46d7183a2a35 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -4650,8 +4650,7 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
     Ops[0] = removePointerBase(Ops[0]);
     // Don't try to transfer nowrap flags for now. We could in some cases
     // (for example, if pointer operand of the AddRec is a SCEVUnknown).
-    return getAddRecExprFromMismatchedTypes(Ops, AddRec->getLoop(),
-                                            SCEV::FlagAnyWrap);
+    return getAddRecExpr(Ops, AddRec->getLoop(), SCEV::FlagAnyWrap);
   }
   if (auto *Add = dyn_cast<SCEVAddExpr>(P)) {
     // The base of an Add is the pointer operand.
@@ -4666,31 +4665,12 @@ const SCEV *ScalarEvolution::removePointerBase(const SCEV *P) {
     *PtrOp = removePointerBase(*PtrOp);
     // Don't try to transfer nowrap flags for now. We could in some cases
     // (for example, if the pointer operand of the Add is a SCEVUnknown).
-    return getAddExprFromMismatchedTypes(Ops);
+    return getAddExpr(Ops);
   }
-
-  if (auto *Unknown = dyn_cast<SCEVUnknown>(P)) {
-    if (auto *O = dyn_cast<Operator>(Unknown->getValue())) {
-      if (O->getOpcode() == Instruction::IntToPtr) {
-        Value *Op0 = O->getOperand(0);
-        if (isa<ConstantInt>(Op0))
-          return getConstant(dyn_cast<ConstantInt>(Op0));
-        return getSCEV(Op0);
-      }
-    }
-  }
-
   // Any other expression must be a pointer base.
   return getZero(P->getType());
 }
 
-static bool isIntToPtr(const SCEV *V) {
-  if (auto *Unknown = dyn_cast<SCEVUnknown>(V))
-    if (auto *Op = dyn_cast<Operator>(Unknown->getValue()))
-      return Op->getOpcode() == Instruction::IntToPtr;
-  return false;
-}
-
 const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
                                           SCEV::NoWrapFlags Flags,
                                           unsigned Depth) {
@@ -4698,15 +4678,12 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
   if (LHS == RHS)
     return getZero(LHS->getType());
 
-  // If we subtract two pointers except inttoptrs with different pointer bases,
-  // bail.
+  // If we subtract two pointers with different pointer bases, bail.
   // Eventually, we're going to add an assertion to getMulExpr that we
   // can't multiply by a pointer.
   if (RHS->getType()->isPointerTy()) {
-    const SCEV *LBase = getPointerBase(LHS);
-    const SCEV *RBase = getPointerBase(RHS);
     if (!LHS->getType()->isPointerTy() ||
-        (LBase != RBase && (!isIntToPtr(LBase) || !isIntToPtr(RBase))))
+        getPointerBase(LHS) != getPointerBase(RHS))
       return getCouldNotCompute();
     LHS = removePointerBase(LHS);
     RHS = removePointerBase(RHS);
@@ -4741,8 +4718,7 @@ const SCEV *ScalarEvolution::getMinusSCEV(const SCEV *LHS, const SCEV *RHS,
   // larger scope than intended.
   auto NegFlags = RHSIsNotMinSigned ? SCEV::FlagNSW : SCEV::FlagAnyWrap;
 
-  return getAddExprFromMismatchedTypes(LHS, getNegativeSCEV(RHS, NegFlags),
-                                       AddFlags, Depth);
+  return getAddExpr(LHS, getNegativeSCEV(RHS, NegFlags), AddFlags, Depth);
 }
 
 const SCEV *ScalarEvolution::getTruncateOrZeroExtend(const SCEV *V, Type *Ty,
@@ -4769,18 +4745,6 @@ const SCEV *ScalarEvolution::getTruncateOrSignExtend(const SCEV *V, Type *Ty,
   return getSignExtendExpr(V, Ty, Depth);
 }
 
-const SCEV *ScalarEvolution::getTruncateOrAnyExtend(const SCEV *V, Type *Ty,
-                                                    unsigned Depth) {
-  Type *SrcTy = V->getType();
-  assert(SrcTy->isIntOrPtrTy() && Ty->isIntOrPtrTy() &&
-         "Cannot truncate or any extend with non-integer arguments!");
-  if (getTypeSizeInBits(SrcTy) == getTypeSizeInBits(Ty))
-    return V; // No conversion
-  if (getTypeSizeInBits(SrcTy) > getTypeSizeInBits(Ty))
-    return getTruncateExpr(V, Ty, Depth);
-  return getAnyExtendExpr(V, Ty);
-}
-
 const SCEV *
 ScalarEvolution::getNoopOrZeroExtend(const SCEV *V, Type *Ty) {
   Type *SrcTy = V->getType();
@@ -4875,58 +4839,6 @@ ScalarEvolution::getUMinFromMismatchedTypes(SmallVectorImpl<const SCEV *> &Ops,
   return getUMinExpr(PromotedOps, Sequential);
 }
 
-const SCEV *ScalarEvolution::getAddRecExprFromMismatchedTypes(
-    const SmallVectorImpl<const SCEV *> &Ops, const Loop *L,
-    SCEV::NoWrapFlags Flags) {
-  assert(!Ops.empty() && "At least one operand must be!");
-  // Trivial case.
-  if (Ops.size() == 1)
-    return Ops[0];
-
-  // Find the max type first.
-  Type *MaxType = nullptr;
-  for (const auto *S : Ops)
-    if (MaxType)
-      MaxType = getWiderType(MaxType, S->getType());
-    else
-      MaxType = S->getType();
-  assert(MaxType && "Failed to find maximum type!");
-
-  // Extend all ops to max type.
-  SmallVector<const SCEV *, 2> PromotedOps;
-  PromotedOps.reserve(Ops.size());
-  for (const auto *S : Ops)
-    PromotedOps.push_back(getNoopOrAnyExtend(S, MaxType));
-
-  return getAddRecExpr(PromotedOps, L, Flags);
-}
-
-const SCEV *ScalarEvolution::getAddExprFromMismatchedTypes(
-    const SmallVectorImpl<const SCEV *> &Ops, SCEV::NoWrapFlags Flags,
-    unsigned Depth) {
-  assert(!Ops.empty() && "At least one operand must be!");
-  // Trivial case.
-  if (Ops.size() == 1)
-    return Ops[0];
-
-  // Find the max type first.
-  Type *MaxType = nullptr;
-  for (const auto *S : Ops)
-    if (MaxType)
-      MaxType = getWiderType(MaxType, S->getType());
-    else
-      MaxType = S->getType();
-  assert(MaxType && "Failed to find maximum type!");
-
-  // Extend all ops to max type.
-  SmallVector<const SCEV *, 2> PromotedOps;
-  PromotedOps.reserve(Ops.size());
-  for (const auto *S : Ops)
-    PromotedOps.push_back(getNoopOrAnyExtend(S, MaxType));
-
-  return getAddExpr(PromotedOps, Flags, Depth);
-}
-
 const SCEV *ScalarEvolution::getPointerBase(const SCEV *V) {
   // A pointer operand may evaluate to a nonpointer expression, such as null.
   if (!V->getType()->isPointerTy())
diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index c4e13989e17a2..af8232b03f1ed 100644
--- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -67,13 +67,10 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
     // Test whether the difference is known to be great enough that memory of
     // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
     // are non-zero, which is special-cased above.
-    if (!isa<SCEVCouldNotCompute>(BA)) {
-      if (SE.isSCEVable(BA->getType()))
-        BA = SE.getTruncateOrAnyExtend(BA, AS->getType());
-      if (ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
-          (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
-        return AliasResult::NoAlias;
-    }
+    if (!isa<SCEVCouldNotCompute>(BA) &&
+        ASizeInt.ule(SE.getUnsignedRange(BA).getUnsignedMin()) &&
+        (-BSizeInt).uge(SE.getUnsignedRange(BA).getUnsignedMax()))
+      return AliasResult::NoAlias;
 
     // Folding the subtraction while preserving range information can be tricky
     // (because of INT_MIN, etc.); if the prior test failed, swap AS and BS
@@ -85,13 +82,10 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
     // Test whether the difference is known to be great enough that memory of
     // the given sizes don't overlap. This assumes that ASizeInt and BSizeInt
     // are non-zero, which is special-cased above.
-    if (!isa<SCEVCouldNotCompute>(AB)) {
-      if (SE.isSCEVable(AB->getType()))
-        AB = SE.getTruncateOrAnyExtend(AB, AS->getType());
-      if (BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
-          (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
-        return AliasResult::NoAlias;
-    }
+    if (!isa<SCEVCouldNotCompute>(AB) &&
+        BSizeInt.ule(SE.getUnsignedRange(AB).getUnsignedMin()) &&
+        (-ASizeInt).uge(SE.getUnsignedRange(AB).getUnsignedMax()))
+      return AliasResult::NoAlias;
   }
 
   // If ScalarEvolution can find an underlying object, form a new query.
diff --git a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
index 5610833e9c474..a81baa73a93bd 100644
--- a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
+++ b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
@@ -340,29 +340,3 @@ for.latch:
 for.end:
   ret void
 }
-
-; CHECK-LABEL: Function: test_different_pointer_bases_of_inttoptr: 2 pointers, 0 call sites
-; CHECK:   NoAlias:	<16 x i8>* %tmp5, <16 x i8>* %tmp7
-
-define void @test_different_pointer_bases_of_inttoptr() {
-entry:
-  br label %for.body
-
-for.body:
-  %tmp = phi i32 [ %next, %for.body ], [ 1, %entry ]
-  %tmp1 = shl nsw i32 %tmp, 1
-  %tmp2 = add nuw nsw i32 %tmp1, %tmp1
-  %tmp3 = mul nsw i32 %tmp2, 1408
-  %tmp4 = add nsw i32 %tmp3, 1408
-  %tmp5 = getelementptr inbounds i8, ptr inttoptr (i32 1024 to ptr), i32 %tmp1
-  %tmp6 = load <16 x i8>, ptr %tmp5, align 1
-  %tmp7 = getelementptr inbounds i8, ptr inttoptr (i32 4096 to ptr), i32 %tmp4
-  store <16 x i8> %tmp6, ptr %tmp7, align 1
-
-  %next = add i32 %tmp, 2
-  %exitcond = icmp slt i32 %next, 10
-  br i1 %exitcond, label %for.body, label %for.end
-
-for.end:
-  ret void
-}

>From e15465d2952805f1ae21902c89f6c586fd9a128d Mon Sep 17 00:00:00 2001
From: XiaoQiang Xu <swust_xiaoqiangxu at 163.com>
Date: Thu, 9 May 2024 11:24:26 +0800
Subject: [PATCH 3/4] [SCEVAA] Try to handle two inttoptrs with different
 pointer bases

---
 .../Analysis/ScalarEvolutionAliasAnalysis.cpp | 12 +++++++++
 llvm/test/Analysis/ScalarEvolution/scev-aa.ll | 26 +++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index af8232b03f1ed..cc8eee9d0f763 100644
--- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -61,6 +61,18 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
                                  ? static_cast<uint64_t>(LocB.Size.getValue())
                                  : MemoryLocation::UnknownSize);
 
+    // Before calling getMinusSCEV(), we could try the ptrtpoint pointer
+    // operands so that you can handle two pointers with different pointer
+    // bases.
+    const SCEV *AInt =
+        SE.getPtrToIntExpr(AS, SE.getEffectiveSCEVType(AS->getType()));
+    if (!isa<SCEVCouldNotCompute>(AInt))
+      AS = AInt;
+    const SCEV *BInt =
+        SE.getPtrToIntExpr(BS, SE.getEffectiveSCEVType(BS->getType()));
+    if (!isa<SCEVCouldNotCompute>(BInt))
+      BS = BInt;
+
     // Compute the difference between the two pointers.
     const SCEV *BA = SE.getMinusSCEV(BS, AS);
 
diff --git a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
index a81baa73a93bd..5610833e9c474 100644
--- a/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
+++ b/llvm/test/Analysis/ScalarEvolution/scev-aa.ll
@@ -340,3 +340,29 @@ for.latch:
 for.end:
   ret void
 }
+
+; CHECK-LABEL: Function: test_different_pointer_bases_of_inttoptr: 2 pointers, 0 call sites
+; CHECK:   NoAlias:	<16 x i8>* %tmp5, <16 x i8>* %tmp7
+
+define void @test_different_pointer_bases_of_inttoptr() {
+entry:
+  br label %for.body
+
+for.body:
+  %tmp = phi i32 [ %next, %for.body ], [ 1, %entry ]
+  %tmp1 = shl nsw i32 %tmp, 1
+  %tmp2 = add nuw nsw i32 %tmp1, %tmp1
+  %tmp3 = mul nsw i32 %tmp2, 1408
+  %tmp4 = add nsw i32 %tmp3, 1408
+  %tmp5 = getelementptr inbounds i8, ptr inttoptr (i32 1024 to ptr), i32 %tmp1
+  %tmp6 = load <16 x i8>, ptr %tmp5, align 1
+  %tmp7 = getelementptr inbounds i8, ptr inttoptr (i32 4096 to ptr), i32 %tmp4
+  store <16 x i8> %tmp6, ptr %tmp7, align 1
+
+  %next = add i32 %tmp, 2
+  %exitcond = icmp slt i32 %next, 10
+  br i1 %exitcond, label %for.body, label %for.end
+
+for.end:
+  ret void
+}

>From cde0075d4c5d34f44f28d9636394e2f32b897a62 Mon Sep 17 00:00:00 2001
From: csstormq <swust_xiaoqiangxu at 163.com>
Date: Wed, 29 May 2024 11:40:34 +0800
Subject: [PATCH 4/4] fixup! do iff both pointers are used with ptrtoint

---
 llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
index cc8eee9d0f763..882426faa1e6c 100644
--- a/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/ScalarEvolutionAliasAnalysis.cpp
@@ -61,17 +61,19 @@ AliasResult SCEVAAResult::alias(const MemoryLocation &LocA,
                                  ? static_cast<uint64_t>(LocB.Size.getValue())
                                  : MemoryLocation::UnknownSize);
 
-    // Before calling getMinusSCEV(), we could try the ptrtpoint pointer
-    // operands so that you can handle two pointers with different pointer
-    // bases.
+    // Firstly, try to convert the two pointers into ptrtoint expressions to
+    // handle two pointers with different pointer bases.
+    // Either both pointers are used with ptrtoint or neither, so we can't end
+    // up with a ptr + int mix (not entirely sure whether it's possible for just
+    // one of the conversions to fail).
     const SCEV *AInt =
         SE.getPtrToIntExpr(AS, SE.getEffectiveSCEVType(AS->getType()));
-    if (!isa<SCEVCouldNotCompute>(AInt))
-      AS = AInt;
     const SCEV *BInt =
         SE.getPtrToIntExpr(BS, SE.getEffectiveSCEVType(BS->getType()));
-    if (!isa<SCEVCouldNotCompute>(BInt))
+    if (!isa<SCEVCouldNotCompute>(AInt) && !isa<SCEVCouldNotCompute>(BInt)) {
+      AS = AInt;
       BS = BInt;
+    }
 
     // Compute the difference between the two pointers.
     const SCEV *BA = SE.getMinusSCEV(BS, AS);



More information about the llvm-commits mailing list