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 +}