Index: lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- lib/Analysis/BasicAliasAnalysis.cpp +++ lib/Analysis/BasicAliasAnalysis.cpp @@ -1806,6 +1806,28 @@ } } +static bool checkFormOddNumSubOffset(const Value *V1, const Value *V2, + unsigned BitWidth) { + if (const BinaryOperator *BOp = dyn_cast(V1)) { + if (ConstantInt *LHSC = dyn_cast(BOp->getOperand(0))) { + APInt LHS = LHSC->getValue().zextOrSelf(BitWidth); + // Check odd number. + if ((LHS.getLoBits(1)) == 0) { + return false; + } + + // Check sub with same object. + if (BOp->getOpcode() == Instruction::Sub) { + if (BOp->getOperand(1) == V2) { + return true; + } + } + } + } + + return false; +} + bool BasicAAResult::constantOffsetHeuristic( const SmallVectorImpl &VarIndices, LocationSize V1Size, LocationSize V2Size, int64_t BaseOffset, AssumptionCache *AC, @@ -1838,8 +1860,34 @@ 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) || + checkFormOddNumSubOffset(V1, V0, BitWidth)) { + return true; + } + return false; + } // We have a hit - Var0 and Var1 only differ by a constant offset! 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 +}