BasicAA fails to return NoAlias from aliasGEP with PHI index. Let's see code snippet.
typedef struct data { int oldVal; int newVal; } data_t; void alias_issue(data_t *data, int max) { int pos = 1; int cmp = 3; while(cmp < max) { data[pos].newVal = data[cmp].newVal; data[pos].oldVal = data[cmp].newVal; pos = cmp; cmp *= 2; } return; }
From above code, we can imagine that we need to load data[cmp].newVal one time. Let's see LLVM IR output from above code.
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 %0 = load i32, i32* %newVal, align 4, !tbaa !6 ==> data[cmp].newVal %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 !6 ==> data[pos].newVal = data[cmp].newVal; %1 = load i32, i32* %newVal, align 4, !tbaa !6 ==> data[cmp].newVal %oldVal = getelementptr inbounds %struct.data, %struct.data* %arrayidx4, i32 0, i32 0 store i32 %1, i32* %oldVal, align 4, !tbaa !11 %mul = mul nsw i32 %cmp.0, 2 br label %while.cond
As you can see, there are %0 and %1 which are same load instruction for data[cmp].newVal. Optimization passes like instcombine, GVN check the the address of store i32 %0, i32* %newVal5, align 4, !tbaa !6 has alias with %1 load. BasicAA returns MayAlias for it. If GEP has index with PHI, it look aliasGEP fails to detect NoAlias. Let's see the situation.
loop: %pos.0 = phi i32 [ 1, %entry ], [ %cmp.0, %loop ] %cmp.0 = phi i32 [ 3, %entry ], [ %mul, %loop ] ... %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 ... %sub2 = add nsw i32 %pos.0, -1 %idxprom3 = sext i32 %sub2 to i64 %newVal5 = getelementptr inbounds %struct.data, %struct.data* %data, i64 %idxprom3, i32 1 ... %mul = mul nsw i32 %cmp.0, 2 br label %loop
On above example, %pos.0 uses previous iteration's %cmp.0 with backedge according to PHI's instruction's definition. In this case, I think we can say %pos.0 is not same with %cmp.0. This patch is to detect above pattern.
If the parents are the same, then you don't need to check the incoming blocks, they must be the same.
You also don't need to check PN1 and PN2 for null, they are expected to be non-null in this function.