Skip to content

Wrong code at -O2 on x86_64-linux_gnu since 3ddd1ff #68260

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
shao-hua-li opened this issue Oct 4, 2023 · 2 comments
Closed

Wrong code at -O2 on x86_64-linux_gnu since 3ddd1ff #68260

shao-hua-li opened this issue Oct 4, 2023 · 2 comments
Assignees
Labels

Comments

@shao-hua-li
Copy link

clang at -O2 produced the wrong code.

Bisected to 3ddd1ff, which was committed by @nikic

Compiler explorer: https://godbolt.org/z/rEv69ovMj

% cat a.c
int printf(const char *, ...);
char *a;
long b, c, d, m;
int e, f, j, l;
short g;
int *k = &j;
int main() {
  int *n[] = {&f, &f, &f, &f, &f, &e};
  d = 0;
  for (; d <= 1; d++) {
    g = 0;
    for (; g <= 4; g++) {
      char h[] = {0, 0, 4};
      char *i = h;
      a = i;
      do {
        a++;
        b /= 10;
      } while (b);
      c = a - i;
      while (i < a){
        *i = *(i+1);
        i++;
      }
      *k ^= c;
      k = n[d + g];
      l ^= m;
    }
  }
  printf("%d\n", e);
}
%
% clang -O0 a.c && ./a.out
0
% clang -O2 a.c && ./a.out
1
%
@EugeneZelenko EugeneZelenko added the llvm:SCEV Scalar Evolution label Oct 5, 2023
@nikic
Copy link
Contributor

nikic commented Oct 6, 2023

I believe the problem here is that we have a load from an addrec based on a constant global. The SCEV for the load will indeed always be Unknown, but the SCEVAtScope may not be: We can determine the exit value of the addrec and based on that determine the exit value of the load.

@nikic
Copy link
Contributor

nikic commented Oct 6, 2023

I think this is a nice reduction:

; RUN: opt -S -passes='print<scalar-evolution>,loop(loop-unroll-full,indvars)' < %s
@g = constant [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4]

declare void @use(i32)

define void @test() {
entry:
  br label %loop

loop:
  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
  %iv.next = add i64 %iv, 1
  br label %loop2

loop2:
  %iv2 = phi i64 [ 0, %loop ], [ %iv2.next, %loop2 ]
  %iv2.next = add i64 %iv2, 1
  %idx = add i64 %iv, %iv2
  %gep = getelementptr i32, ptr @g, i64 %idx
  %load = load i32, ptr %gep
  %cmp2 = icmp ne i64 %iv2, 3
  br i1 %cmp2, label %loop2, label %loop.latch, !llvm.loop !0

loop.latch:
  %load.lcssa = phi i32 [ %load, %loop2 ]
  call void @use(i32 %load)
  %cmp = icmp ne i64 %iv, 1
  br i1 %cmp, label %loop, label %exit

exit:
  ret void
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.disable", i1 true}

Results in:

@g = constant [5 x i32] [i32 0, i32 1, i32 2, i32 3, i32 4]

declare void @use(i32)

define void @test() {
entry:
  br label %loop

loop:                                             ; preds = %entry
  br label %loop2

loop2:                                            ; preds = %loop2, %loop
  br i1 false, label %loop2, label %loop.latch, !llvm.loop !0

loop.latch:                                       ; preds = %loop2
  call void @use(i32 4)
  br label %loop2.1

loop2.1:                                          ; preds = %loop2.1, %loop.latch
  br i1 false, label %loop2.1, label %loop.latch.1, !llvm.loop !0

loop.latch.1:                                     ; preds = %loop2.1
  call void @use(i32 4)
  ret void
}

!0 = distinct !{!0, !1}
!1 = !{!"llvm.loop.unroll.disable", i1 true}

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants