Description
wrong0.tar.gz
(reduced c test case, should print 0)
runline:
clang -O3 -march=arch13 wrong0.i -o a.out -w -mllvm -available-load-scan-limit=12
The function n() below is called two times in the reduced test case. The first time f[0] has a value of 0 at the start of the function, and a value of 1 at the end. The second time n() is called, f[0] has a value of 1 at the top, while it is then set to 0 by k().
long k(long l, int m); // returns 0
const int *n() {
for (; C <= 0;) {
A = (f[0] == 0 ? 1 : A % f[0]);
f[C] = k(A, 0);
g = &f[0];
f[C] = 1 > *g;
if (f[C])
return &e;
break;
}
return 0;
}
This is the transformation of jump threading:
> *** IR Dump After JumpThreadingPass on n ***
> ; Function Attrs: nounwind
define dso_local ptr @n() local_unnamed_addr #1 { define dso_local ptr @n() local_unnamed_addr #1 {
entry: entry:
%0 = load i64, ptr @C, align 8, !tbaa !4 %0 = load i64, ptr @C, align 8, !tbaa !4
%cmp = icmp slt i64 %0, 1 %cmp = icmp slt i64 %0, 1
br i1 %cmp, label %for.body, label %for.end br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %entry for.body: ; preds = %entry
%1 = load i32, ptr @f, align 4, !tbaa !8 %1 = load i32, ptr @f, align 4, !tbaa !8
%cmp1 = icmp eq i32 %1, 0 %cmp1 = icmp eq i32 %1, 0
br i1 %cmp1, label %cond.end, label %cond.false | br i1 %cmp1, label %cond.end.thread, label %cond.end
cond.false: ; preds = %for.body | cond.end.thread: ; preds = %for.body
> store i64 1, ptr @A, align 8, !tbaa !4
> br label %3
>
> cond.end: ; preds = %for.body
%2 = load i64, ptr @A, align 8, !tbaa !4 %2 = load i64, ptr @A, align 8, !tbaa !4
%conv = sext i32 %1 to i64 %conv = sext i32 %1 to i64
%rem = srem i64 %2, %conv %rem = srem i64 %2, %conv
br label %cond.end | store i64 %rem, ptr @A, align 8, !tbaa !4
> %cmp.i = icmp sgt i64 %rem, 0
> %cond.fr = freeze i1 %cmp.i
> br i1 %cond.fr, label %3, label %4
>
> 3: ; preds = %cond.end.
> %.pr = load i32, ptr @f, align 4, !tbaa !8
> br label %4
cond.end: ; preds = %for.body, | 4: ; preds = %cond.end,
%cond = phi i64 [ %rem, %cond.false ], [ 1, %for.body ] | %5 = phi i32 [ %1, %cond.end ], [ %.pr, %3 ]
store i64 %cond, ptr @A, align 8, !tbaa !4 | %6 = phi i64 [ 0, %3 ], [ %rem, %cond.end ]
%cmp.i = icmp sgt i64 %cond, 0 | %conv2 = trunc i64 %6 to i32
%cond.i = select i1 %cmp.i, i64 0, i64 %cond <
%conv2 = trunc i64 %cond.i to i32 <
%arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0 %arrayidx = getelementptr inbounds [1 x i32], ptr @f, i64 0, i64 %0
store i32 %conv2, ptr %arrayidx, align 4, !tbaa !8 store i32 %conv2, ptr %arrayidx, align 4, !tbaa !8
store ptr @f, ptr @g, align 8, !tbaa !10 store ptr @f, ptr @g, align 8, !tbaa !10
%3 = load i32, ptr @f, align 4, !tbaa !8 | %cmp3 = icmp slt i32 %5, 1
%cmp3 = icmp slt i32 %3, 1 <
%conv4 = zext i1 %cmp3 to i32 %conv4 = zext i1 %cmp3 to i32
store i32 %conv4, ptr %arrayidx, align 4, !tbaa !8 store i32 %conv4, ptr %arrayidx, align 4, !tbaa !8
br i1 %cmp3, label %return, label %for.end br i1 %cmp3, label %return, label %for.end
for.end: ; preds = %cond.end, | for.end: ; preds = %4, %entry
br label %return br label %return
return: ; preds = %cond.end, | return: ; preds = %4, %for.e
%retval.0 = phi ptr [ null, %for.end ], [ @e, %cond.end ] | %retval.0 = phi ptr [ null, %for.end ], [ @e, %4 ]
ret ptr %retval.0 ret ptr %retval.0
} }
~
Before (left), @f
is reloaded for the final icmp in cond.end (%3), which is necessary as the store to %conv2 just above goes to the same address. However, to the right JumpThreading has changed the final icmp to use the %5 value, which does not reflect the stored value of %conv2. This seems wrong and maybe JT has missed the fact that %arrayidx aliases @f
?
Metadata
Metadata
Assignees
Type
Projects
Status