Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -254,7 +254,10 @@ Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension, DL, Depth+1, AT, DT); Scale = Scale.zext(OldWidth); - Offset = Offset.zext(OldWidth); + + // we have to sign-extend even if Extension == EK_ZeroExt as we can't + // decompose a sign extension (i.e. zext(x - 1) != zext(x) - zext(-1)) + Offset = Offset.sext(OldWidth); return Result; } @@ -1055,8 +1058,14 @@ // Grab the least significant bit set in any of the scales. if (!GEP1VariableIndices.empty()) { uint64_t Modulo = 0; - for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) + bool AllPositive = true; + for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) { Modulo |= (uint64_t)GEP1VariableIndices[i].Scale; + + // if the variable's been zero-extended, then we know it's positive, + // regardless of whether the value is signed or unsigned + AllPositive &= GEP1VariableIndices[i].Extension == EK_ZeroExt; + } Modulo = Modulo ^ (Modulo & (Modulo - 1)); // We can compute the difference between the two addresses @@ -1066,6 +1075,12 @@ if (V1Size != UnknownSize && V2Size != UnknownSize && ModOffset >= V2Size && V1Size <= Modulo - ModOffset) return NoAlias; + + // If we know all the variables are positive, then GEP1 >= GEP1BasePtr. + // If GEP1BasePtr > V2 (GEP1BaseOffset > 0) then we know the pointers + // don't alias if V2Size can fit in the gap between V2 and GEP1BasePtr. + if(AllPositive && GEP1BaseOffset > 0 && V2Size <= (uint64_t) GEP1BaseOffset) + return NoAlias; } // Statically, we can see that the base objects are the same, but the @@ -1208,6 +1223,21 @@ break; } + // The Alias we just calculated only holds if all the Values come from + // the same cycle as the Phi-node. If not, subsequent memory stores could + // mean these Values no longer alias, or now alias when we reach PN, so + // we'll just return MayAlias ("don't know"). + DominatorTreeWrapperPass *DTWP = + getAnalysisIfAvailable(); + DominatorTree *DT = DTWP ? &DTWP->getDomTree() : nullptr; + LoopInfo *LI = getAnalysisIfAvailable(); + + for (unsigned i = 0, e = V1Srcs.size(); i != e; ++i) { + const Instruction *Inst = dyn_cast(V1Srcs[i]); + if(Inst && isPotentiallyReachable(PN, Inst, DT, LI)) + return MayAlias; + } + return Alias; } Index: test/Analysis/BasicAA/phi-aa.ll =================================================================== --- test/Analysis/BasicAA/phi-aa.ll +++ test/Analysis/BasicAA/phi-aa.ll @@ -38,7 +38,8 @@ ; PR18068 ; CHECK-LABEL: pr18068 -; CHECK: MayAlias: i32* %0, i32* %arrayidx5 +; CHECK: MayAlias: i32* %arrayidx5, i32* %phi +; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5 define i32 @pr18068(i32* %jj7, i32* %j) { entry: @@ -46,21 +47,21 @@ br label %codeRepl codeRepl: - %0 = phi i32* [ %arrayidx13, %for.body ], [ %j, %entry ] + %phi = phi i32* [ %arrayidx13, %for.body ], [ %j, %entry ] %targetBlock = call i1 @cond(i32* %jj7) br i1 %targetBlock, label %for.body, label %bye for.body: - %1 = load i32* %jj7, align 4 - %idxprom4 = zext i32 %1 to i64 + %0 = load i32* %jj7, align 4 + %idxprom4 = zext i32 %0 to i64 %arrayidx5 = getelementptr inbounds [100 x i32]* %oa5, i64 0, i64 %idxprom4 - %2 = load i32* %arrayidx5, align 4 - %sub6 = sub i32 %2, 6 + %1 = load i32* %arrayidx5, align 4 + %sub6 = sub i32 %1, 6 store i32 %sub6, i32* %arrayidx5, align 4 - ; %0 and %arrayidx5 can alias! It is not safe to DSE the above store. - %3 = load i32* %0, align 4 - store i32 %3, i32* %arrayidx5, align 4 - %sub11 = add i32 %1, -1 + ; %phi and %arrayidx5 can alias! It is not safe to DSE the above store. + %2 = load i32* %phi, align 4 + store i32 %2, i32* %arrayidx5, align 4 + %sub11 = add i32 %0, -1 %idxprom12 = zext i32 %sub11 to i64 %arrayidx13 = getelementptr inbounds [100 x i32]* %oa5, i64 0, i64 %idxprom12 call void @inc(i32* %jj7) Index: test/Analysis/BasicAA/zext.ll =================================================================== --- /dev/null +++ test/Analysis/BasicAA/zext.ll @@ -0,0 +1,53 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +; CHECK-LABEL: test +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test() { + %1 = tail call i8* @malloc(i64 120) + %a = getelementptr inbounds i8* %1, i64 8 + %2 = getelementptr inbounds i8* %1, i64 16 + %3 = zext i32 3 to i64 + %b = getelementptr inbounds i8* %2, i64 %3 + ret void +} + +; CHECK-LABEL: test_with_a_loop +; CHECK: NoAlias: i8* %a, i8* %b + +define void @test_with_a_loop() { + %1 = tail call i8* @malloc(i64 120) + %a = getelementptr inbounds i8* %1, i64 8 + %2 = getelementptr inbounds i8* %1, i64 16 + br label %for.loop + +for.loop: + %i = phi i32 [ 0, %0 ], [ %i.next, %for.loop ] + %3 = zext i32 %i to i64 + %b = getelementptr inbounds i8* %2, i64 %3 + %i.next = add nuw nsw i32 %i, 1 + %4 = icmp eq i32 %i.next, 10 + br i1 %4, label %for.loop.exit, label %for.loop + +for.loop.exit: + ret void +} + +; CHECK-LABEL: test_sign_extension +; CHECK: PartialAlias: i64* %b.i64, i8* %a + +define void @test_sign_extension(i32 %p) { + %1 = tail call i8* @malloc(i64 120) + %p.64 = zext i32 %p to i64 + %a = getelementptr inbounds i8* %1, i64 %p.64 + %p.minus1 = add i32 %p, -1 + %p.minus1.64 = zext i32 %p.minus1 to i64 + %b.i8 = getelementptr inbounds i8* %1, i64 %p.minus1.64 + %b.i64 = bitcast i8* %b.i8 to i64* + ret void +} + +; Function Attrs: nounwind +declare noalias i8* @malloc(i64)