Skip to content

[BasicAA] Make use of nusw+nuw -> nneg implication #102141

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 7, 2024

Conversation

nikic
Copy link
Contributor

@nikic nikic commented Aug 6, 2024

If the GEP is both nuw and inbounds/nusw, the offset is non-negative. Pass this information to CastedValue and make use of it when determining the value range.

Proof for nusw+nuw->nneg: https://alive2.llvm.org/ce/z/a_CKAw
Proof for the test case: https://alive2.llvm.org/ce/z/yJ3ymP

If the GEP is both nuw and inbounds/nusw, the offset is
non-negative. Pass this information to CastedValue and make use
of it when determining the value range.

Proof for nusw+nuw->nneg: https://alive2.llvm.org/ce/z/a_CKAw
Proof for the test case: https://alive2.llvm.org/ce/z/yJ3ymP
@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Aug 6, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 6, 2024

@llvm/pr-subscribers-llvm-analysis

Author: Nikita Popov (nikic)

Changes

If the GEP is both nuw and inbounds/nusw, the offset is non-negative. Pass this information to CastedValue and make use of it when determining the value range.

Proof for nusw+nuw->nneg: https://alive2.llvm.org/ce/z/a_CKAw
Proof for the test case: https://alive2.llvm.org/ce/z/yJ3ymP


Full diff: https://github.com/llvm/llvm-project/pull/102141.diff

2 Files Affected:

  • (modified) llvm/lib/Analysis/BasicAliasAnalysis.cpp (+8-2)
  • (added) llvm/test/Analysis/BasicAA/nusw_nuw_nonneg.ll (+20)
diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
index 33131d80b35fa..7bfb23e14aaa7 100644
--- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp
+++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp
@@ -337,6 +337,10 @@ struct CastedValue {
     assert(N.getBitWidth() == V->getType()->getPrimitiveSizeInBits() &&
            "Incompatible bit width");
     if (TruncBits) N = N.truncate(N.getBitWidth() - TruncBits);
+    if (IsNonNegative && !N.isAllNonNegative())
+      N = N.intersectWith(
+          ConstantRange(APInt::getZero(N.getBitWidth()),
+                        APInt::getSignedMinValue(N.getBitWidth())));
     if (SExtBits) N = N.signExtend(N.getBitWidth() + SExtBits);
     if (ZExtBits) N = N.zeroExtend(N.getBitWidth() + ZExtBits);
     return N;
@@ -693,15 +697,17 @@ BasicAAResult::DecomposeGEPExpression(const Value *V, const DataLayout &DL,
 
       // If the integer type is smaller than the index size, it is implicitly
       // sign extended or truncated to index size.
+      bool NUSW = GEPOp->hasNoUnsignedSignedWrap();
+      bool NonNeg = NUSW && GEPOp->hasNoUnsignedWrap();
       unsigned Width = Index->getType()->getIntegerBitWidth();
       unsigned SExtBits = IndexSize > Width ? IndexSize - Width : 0;
       unsigned TruncBits = IndexSize < Width ? Width - IndexSize : 0;
       LinearExpression LE = GetLinearExpression(
-          CastedValue(Index, 0, SExtBits, TruncBits, false), DL, 0, AC, DT);
+          CastedValue(Index, 0, SExtBits, TruncBits, NonNeg), DL, 0, AC, DT);
 
       // Scale by the type size.
       unsigned TypeSize = AllocTypeSize.getFixedValue();
-      LE = LE.mul(APInt(IndexSize, TypeSize), GEPOp->hasNoUnsignedSignedWrap());
+      LE = LE.mul(APInt(IndexSize, TypeSize), NUSW);
       Decomposed.Offset += LE.Offset.sext(MaxIndexSize);
       APInt Scale = LE.Scale.sext(MaxIndexSize);
 
diff --git a/llvm/test/Analysis/BasicAA/nusw_nuw_nonneg.ll b/llvm/test/Analysis/BasicAA/nusw_nuw_nonneg.ll
new file mode 100644
index 0000000000000..84df62938e2f5
--- /dev/null
+++ b/llvm/test/Analysis/BasicAA/nusw_nuw_nonneg.ll
@@ -0,0 +1,20 @@
+; RUN: opt < %s -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
+
+; CHECK-LABEL: test
+; CHECK: NoAlias:	i8* %p.minus.2, i8* %p.plus.2
+; CHECK: MayAlias:	i8* %p.idx.maybeneg, i8* %p.minus.2
+; CHECK: MayAlias:	i8* %p.idx.maybeneg, i8* %p.plus.2
+; CHECK: NoAlias:	i8* %p.idx.nneg, i8* %p.minus.2
+; CHECK: MayAlias:	i8* %p.idx.nneg, i8* %p.plus.2
+; CHECK: MustAlias:	i8* %p.idx.maybeneg, i8* %p.idx.nneg
+define void @test(ptr %p, i64 %idx) {
+  %p.minus.2 = getelementptr i8, ptr %p, i64 -2
+  %p.plus.2 = getelementptr i8, ptr %p, i64 2
+  %p.idx.maybeneg = getelementptr inbounds i8, ptr %p, i64 %idx
+  %p.idx.nneg = getelementptr nuw nusw i8, ptr %p, i64 %idx
+  load i8, ptr %p.minus.2
+  load i8, ptr %p.plus.2
+  load i8, ptr %p.idx.maybeneg
+  load i8, ptr %p.idx.nneg
+  ret void
+}

Copy link
Contributor

@hazzlim hazzlim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thanks for the change :)

@nikic nikic merged commit 3c87f66 into llvm:main Aug 7, 2024
9 checks passed
@nikic nikic deleted the basicaa-nusw-nuw-nonneg branch August 7, 2024 10:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
llvm:analysis Includes value tracking, cost tables and constant folding
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants