Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -1393,6 +1393,9 @@ if (V1Size == 0 || V2Size == 0) return NoAlias; + Type *V1Type = V1->getType(); + Type *V2Type = V2->getType(); + // Strip off any casts if they exist. V1 = V1->stripPointerCasts(); V2 = V2->stripPointerCasts(); @@ -1520,6 +1523,33 @@ return AliasCache[Locs] = Result; } + // inttoptr(Const1) NoAlias inttoptr(Const2) + // if (Const1 + V1Size <= Const2) || (Const2 + V2Size <= Const1) + // Only if types are equal + if (V1Type == V2Type) { + ConstantInt *C1 = 0; + ConstantInt *C2 = 0; + if (auto *I1 = dyn_cast(V1)) + C1 = dyn_cast(I1->getOperand(0)); + else if (auto *I1 = dyn_cast(V1)) + if (I1->getOpcode() == Instruction::IntToPtr) + C1 = dyn_cast(I1->getOperand(0)); + if (auto *I2 = dyn_cast(V2)) + C2 = dyn_cast(I2->getOperand(0)); + else if (auto *I2 = dyn_cast(V2)) + if (I2->getOpcode() == Instruction::IntToPtr) + C2 = dyn_cast(I2->getOperand(0)); + if (C1 && C2 && C1->getBitWidth() == C2->getBitWidth()) { + uint64_t C1Val = C1->getZExtValue(); + uint64_t C2Val = C2->getZExtValue(); + if (C1Val + V1Size <= C2Val || C2Val + V2Size <= C1Val) + return AliasCache[Locs] = NoAlias; + if (C1Val == C2Val && V1Size == V2Size) + return AliasCache[Locs] = MustAlias; + return AliasCache[Locs] = PartialAlias; + } + } + // If both pointers are pointing into the same object and one of them // accesses the entire object, then the accesses must overlap in some way. if (O1 == O2) Index: test/Analysis/BasicAA/noalias-consts.ll =================================================================== --- test/Analysis/BasicAA/noalias-consts.ll +++ test/Analysis/BasicAA/noalias-consts.ll @@ -0,0 +1,58 @@ +; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s + +declare i32* @captures(i32* %cap) nounwind readonly + +define void @no() nounwind { +entry: + store i32 1, i32* inttoptr (i32 16 to i32*) + %l = load i32, i32* inttoptr (i32 20 to i32*) + ret void +} + +; CHECK: NoAlias: i32* inttoptr (i32 16 to i32*), i32* inttoptr (i32 20 to i32*) + +define void @no2() nounwind { +entry: + %a = inttoptr i32 32 to i32* + %b = inttoptr i32 36 to i32* + store i32 1, i32* %a + %cap = call i32* @captures(i32* %b) nounwind readonly + %l = load i32, i32* %b + ret void +} + +; CHECK: NoAlias: i32* %a, i32* %b + +define void @partial() nounwind { +entry: + store i32 1, i32* inttoptr (i32 16 to i32*) + %l = load i32, i32* inttoptr (i32 18 to i32*) + ret void +} + +; CHECK: PartialAlias: i32* inttoptr (i32 16 to i32*), i32* inttoptr (i32 18 to i32*) + +define void @partial2() nounwind { +entry: + %c = inttoptr i32 16 to i32* + %d = inttoptr i32 18 to i32* + store i32 1, i32* %c + %cap = call i32* @captures(i32* %c) nounwind readonly + %l = load i32, i32* %d + ret void +} + +; CHECK: PartialAlias: i32* %c, i32* %d + +define void @must() nounwind { +entry: + %e = inttoptr i32 28 to i32* + %f = inttoptr i32 28 to i32* + store i32 1, i32* %e + %cap = call i32* @captures(i32* %e) nounwind readonly + %l = load i32, i32* %f + ret void +} + +; CHECK: MustAlias: i32* %e, i32* %f +