[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:40:58 PDT 2024
https://github.com/csstormq updated https://github.com/llvm/llvm-project/pull/91453
>From 60fd9995ea5cb8ecc07ad4184fffb5203fca8674 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 5828cc156cc78..694d2dee9e875 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 93f885c5d5ad8..60bba380f66d6 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 7d18c0b7a4291288f709c00af69703eb2d2e078a 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 694d2dee9e875..5828cc156cc78 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 60bba380f66d6..93f885c5d5ad8 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 8e3edade065c0698addba84cdc60e9f02581a64a 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 6495c966fd2842205c1dedfee9fc8d35d53d720d 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