when dealing with the case below:
extern int foo2(int a, int b,int c);
void foo(int *a, int len){
for(int i=0;i<len;i++) {
int tmp;
tmp = foo2(tmp, a[i], 0);
tmp = foo2(tmp, a[i], 1);
a[i] = tmp;
}
}
there will be an redundant phi node %9 after SORA pass:
define dso_local void @foo(i32* nocapture, i32) local_unnamed_addr #0 {
%3 = icmp sgt i32 %1, 0
br i1 %3, label %4, label %6
; <label>:4: ; preds = %2
%5 = zext i32 %1 to i64
br label %7
; <label>:6: ; preds = %7, %2
ret void
; <label>:7: ; preds = %7, %4
%8 = phi i64 [ 0, %4 ], [ %15, %7 ]
%9 = phi i32 [ undef, %4 ], [ %14, %7 ]
%10 = getelementptr inbounds i32, i32* %0, i64 %8
%11 = load i32, i32* %10, align 4, !tbaa !2
%12 = tail call i32 @foo2(i32 %9, i32 %11, i32 0) #2
%13 = load i32, i32* %10, align 4, !tbaa !2
%14 = tail call i32 @foo2(i32 %12, i32 %13, i32 1) #2
store i32 %14, i32* %10, align 4, !tbaa !2
%15 = add nuw nsw i64 %8, 1
%16 = icmp eq i64 %15, %5
br i1 %16, label %6, label %7
}
when the result we expect is:
; <label>:7: ; preds = %7, %4
%8 = phi i64 [ 0, %4 ], [ %15, %7 ]
%10 = getelementptr inbounds i32, i32* %0, i64 %8
%11 = load i32, i32* %10, align 4, !tbaa !2
%12 = tail call i32 @foo2(i32 undef, i32 %11, i32 0) #2
%13 = load i32, i32* %10, align 4, !tbaa !2
%14 = tail call i32 @foo2(i32 %12, i32 %13, i32 1) #2
store i32 %14, i32* %10, align 4, !tbaa !2
%15 = add nuw nsw i64 %8, 1
%16 = icmp eq i64 %15, %5
br i1 %16, label %6, label %7
}
and I found this problem is caused by the function ComputeLiveInBlocks, it will work though all predecessors if this value is load before store, ignoring the lifetime_start intrinsic which was deleted before in function removeIntrinsicUsers.