Issue 79175
Summary WRONG code, likely JumpThreadingPass
Labels llvm:transforms
Assignees
Reporter JonPsson1
    [wrong0.tar.gz](https://github.com/llvm/llvm-project/files/14027750/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`?

@jmorse @MatzeB @nikic 

_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to