Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1248,6 +1248,72 @@ if (constantOffsetHeuristic(DecompGEP1.VarIndices, V1Size, V2Size, DecompGEP1.Offset, &AC, DT)) return NoAlias; + + if (DecompGEP1.VarIndices.size() == 2) { + const VariableGEPIndex &Var0 = DecompGEP1.VarIndices[0]; + const VariableGEPIndex &Var1 = DecompGEP1.VarIndices[1]; + + // Check all factors are same except V betwen Var0 and Var1. + bool HasSameFactor = false; + if (Var0.Scale == -Var1.Scale && Var0.ZExtBits == Var1.ZExtBits && + Var0.SExtBits == Var1.SExtBits && DecompGEP1.Offset == 0) + HasSameFactor = true; + + // Check V0 and V1 are PHIs and they have same incoming blocks. + const PHINode *PN0 = dyn_cast(Var0.V); + const PHINode *PN1 = dyn_cast(Var1.V); + bool HasSameIncomingBB = true; + if (PN0 && PN1) { + // Check the incoming blocks of two PHIs are same. + for (unsigned i = 0, e = PN0->getNumIncomingValues(); i != e; ++i) { + const BasicBlock *IncomingBB = PN0->getIncomingBlock(i); + if (PN1->getBasicBlockIndex(IncomingBB) == -1) { + HasSameIncomingBB = false; + break; + } + } + } else + HasSameIncomingBB = false; + + if (HasSameIncomingBB && HasSameFactor) { + // Now the two PHIs have same incoming blocks. Let's compare incoming + // values with same incoming block. + bool IsNonEqual = true; + for (unsigned i = 0, e = PN0->getNumIncomingValues(); i != e; ++i) { + const Value *IdxVal0 = PN0->getIncomingValue(i); + const BasicBlock *IncomingBB0 = PN0->getIncomingBlock(i); + const Value *IdxVal1 = PN1->getIncomingValueForBlock(IncomingBB0); + if (isKnownNonEqual(IdxVal0, IdxVal1, DL, &AC, /* CxtI */ nullptr, + DT)) + continue; + + // If it is not known NonEqual, check the PHI is for loop. + if (DT->dominates(PN0->getParent(), IncomingBB0)) { + // loop: + // %pos.0 = phi i32 [ 1, %entry ], [ %cmp.0, %loop ] + // %cmp.0 = phi i32 [ 3, %entry ], [ %mul, %loop ] + // ... + // %inc = add i32 %cmp.0, 1 + // br label %loop + // + // On above example, %pos.0 uses previous iteration's %cmp.0 with + // backedge according to PHI's instruction's defintion. As a result, + // we can say %pos.0 is not same with %cmp.0. Let's check this + // pattern. + if (PN0 == IdxVal1 || PN1 == IdxVal0) { + // FixMe: Do we have to check the IdxVal is not constant in detail? + continue; + } + } + + IsNonEqual = false; + break; + } + + if (IsNonEqual) + return NoAlias; + } + } } // Statically, we can see that the base objects are the same, but the Index: llvm/test/Analysis/BasicAA/alias-gep-phi.ll =================================================================== --- /dev/null +++ llvm/test/Analysis/BasicAA/alias-gep-phi.ll @@ -0,0 +1,50 @@ +; RUN: opt < %s -basic-aa -instcombine -S 2>&1 | FileCheck %s + +target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + +%struct.data = type { i32, i32 } + +define void @_Z11alias_issueP4datai(%struct.data* %data, i32 %max) { +entry: + br label %while.cond + +while.cond: ; preds = %while.body, %entry + %pos.0 = phi i32 [ 1, %entry ], [ %cmp.0, %while.body ] + %cmp.0 = phi i32 [ 3, %entry ], [ %mul, %while.body ] + %cmp1 = icmp slt i32 %cmp.0, %max + br i1 %cmp1, label %while.body, label %while.end + +while.body: ; preds = %while.cond + %sub = add nsw i32 %cmp.0, -1 + %idxprom = sext i32 %sub to i64 + %newVal = getelementptr inbounds %struct.data, %struct.data* %data, i64 %idxprom, i32 1 + +; CHECK: [[LOAD0:%[a-zA-Z0-9_]+]] = load i32, i32* %newVal, align 4, !tbaa !0 + %0 = load i32, i32* %newVal, align 4, !tbaa !0 + %sub2 = add nsw i32 %pos.0, -1 + %idxprom3 = sext i32 %sub2 to i64 + %arrayidx4 = getelementptr inbounds %struct.data, %struct.data* %data, i64 %idxprom3 + %newVal5 = getelementptr inbounds %struct.data, %struct.data* %data, i64 %idxprom3, i32 1 + store i32 %0, i32* %newVal5, align 4, !tbaa !0 + +; Above store blocks to remove below load becasue MayAlias between %newVal and +; %newVal5. The address %newVal has no alias with %newVal5. If BasicAA +; recognizes it, below load should be removed with instcombine. + +; CHECK-NOT: [[LOAD1:%[a-zA-Z0-9_]+]] = load i32, i32* %newVal, align 4, !tbaa !0 + %1 = load i32, i32* %newVal, align 4, !tbaa !0 + %oldVal = getelementptr inbounds %struct.data, %struct.data* %arrayidx4, i32 0, i32 0 + store i32 %1, i32* %oldVal, align 4, !tbaa !5 + %mul = mul nsw i32 %cmp.0, 2 + br label %while.cond + +while.end: ; preds = %while.cond + ret void +} + +!0 = !{!1, !2, i64 4} +!1 = !{!"_ZTS4data", !2, i64 0, !2, i64 4} +!2 = !{!"int", !3, i64 0} +!3 = !{!"omnipotent char", !4, i64 0} +!4 = !{!"Simple C++ TBAA"} +!5 = !{!1, !2, i64 0}