Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -1806,6 +1806,30 @@ } } +static bool checkFormOddNumSubOffset(const Value *V1, const Value *V2, + unsigned BitWidth, const DataLayout &DL) { + if (const BinaryOperator *BOp = dyn_cast(V1)) { + if (BOp->getOpcode() != Instruction::Sub) + return false; + + if (BOp->getOperand(1) != V2) + return false; + + KnownBits KnownLHS = computeKnownBits(BOp->getOperand(0), DL); + KnownBits KnownRHS = computeKnownBits(BOp->getOperand(1), DL); + + if (KnownLHS.Zero.countTrailingZeros() == + (KnownRHS.Zero.shl(1) | 1).countTrailingZeros() && + KnownLHS.One.countTrailingOnes() == + KnownRHS.One.shl(1).countTrailingOnes()) + return false; + + return true; + } + + return false; +} + bool BasicAAResult::constantOffsetHeuristic( const SmallVectorImpl &VarIndices, LocationSize V1Size, LocationSize V2Size, int64_t BaseOffset, AssumptionCache *AC, @@ -1838,9 +1862,33 @@ V1SExtBits, DL, 0, AC, DT, NSW, NUW); if (V0Scale != V1Scale || V0ZExtBits != V1ZExtBits || - V0SExtBits != V1SExtBits || !isValueEqualInPotentialCycles(V0, V1)) + V0SExtBits != V1SExtBits) return false; + if (!isValueEqualInPotentialCycles(V0, V1)) { + // Let's look at following C code snippet. + // + // char buf[4]; + // int idx = any value; + // char *a = buf[3 - idx]; + // char *b = buf[idx]; + // + // a and b are not aliased. As a result, if the offsets has form as below, + // we can say it is not aliased. + // + // offset1 = odd number - index; + // offset2 = index; + if (V1Size != V2Size) + return false; + + unsigned BitWidth = V1Offset.getBitWidth(); + if (checkFormOddNumSubOffset(V0, V1, BitWidth, DL) || + checkFormOddNumSubOffset(V1, V0, BitWidth, DL)) + return true; + + return false; + } + // We have a hit - Var0 and Var1 only differ by a constant offset! // If we've been sext'ed then zext'd the maximum difference between Var0 and Index: test/Analysis/AliasSet/oddnum-sub-index.ll =================================================================== --- /dev/null +++ test/Analysis/AliasSet/oddnum-sub-index.ll @@ -0,0 +1,17 @@ +; RUN: opt -basicaa -print-alias-sets -S -o - < %s 2>&1 | FileCheck %s --check-prefix=CHECK + +@buf = common local_unnamed_addr global [4 x i8] zeroinitializer, align 1 + +; CHECK: AliasSet[{{.*}}, 1] must alias, Mod Pointers: (i8* %arrayidx, 1) +; CHECK: AliasSet[{{.*}}, 1] must alias, Mod Pointers: (i8* %arrayidx2, 1) +define void @test(i32 %idx) { +entry: + %sub = sub nsw i32 3, %idx + %idxprom = sext i32 %sub to i64 + %arrayidx = getelementptr inbounds [4 x i8], [4 x i8]* @buf, i64 0, i64 %idxprom + %idxprom1 = sext i32 %idx to i64 + %arrayidx2 = getelementptr inbounds [4 x i8], [4 x i8]* @buf, i64 0, i64 %idxprom1 + store i8 1, i8* %arrayidx, align 1 + store i8 2, i8* %arrayidx2, align 1 + ret void +}