<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - loop-reroll rerolls loops with unrerollable instructions"
   href="https://bugs.llvm.org/show_bug.cgi?id=47627">47627</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>loop-reroll rerolls loops with unrerollable instructions
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Loop Optimizer
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>t-kawashima@fujitsu.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=23995" name="attach_23995" title="unrerollable1.ll; IR with unrerollable instructions">attachment 23995</a> <a href="attachment.cgi?id=23995&action=edit" title="unrerollable1.ll; IR with unrerollable instructions">[details]</a></span>
unrerollable1.ll; IR with unrerollable instructions

Problem Description
===================

loop-reroll rerolls loops with unrerollable instructions.

See the following IR (same as the attached one).

--------------------------------
define dso_local void @foo([2 x i32]* nocapture %a) local_unnamed_addr {
entry:
  br label %loop

loop:
  ; base instruction
  %indvars = phi i64 [ 0, %entry ], [ %indvars.next, %loop ]

  ; unrerollable instructions
  %stptrx = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %indvars, i64
0
  store i32 999, i32* %stptrx, align 4

  ; extra simple arithmetic operations
  %plus20 = add nuw nsw i64 %indvars, 20
  %plus10 = add nuw nsw i64 %indvars, 10

  ; root instruction 0
  %ldptr0 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %plus20, i64 0
  %value0 = load i32, i32* %ldptr0, align 4
  %stptr0 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %plus10, i64 0
  store i32 %value0, i32* %stptr0, align 4

  ; root instruction 1
  %ldptr1 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %plus20, i64 1
  %value1 = load i32, i32* %ldptr1, align 4
  %stptr1 = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %plus10, i64 1
  store i32 %value1, i32* %stptr1, align 4

  ; latch
  %indvars.next = add nuw nsw i64 %indvars, 1
  %exitcond = icmp eq i64 %indvars.next, 5
  br i1 %exitcond, label %exit, label %loop

exit:
  ret void
}
--------------------------------

This IR is generated from the following C program.

--------------------------------
void foo(int a[][2]) {
  for (int i = 0; i < 5; i++) {
    a[i][0] = 999;
    a[10+i][0] = a[20+i][0];
    a[10+i][1] = a[20+i][1];
  }
}
--------------------------------

This program is unrerollable because of the existence of
`a[i][0] = 999`. However, `opt -loop-reroll` rerolls this to
the following IR.

--------------------------------
define dso_local void @foo([2 x i32]* nocapture %a) local_unnamed_addr {
entry:
  br label %loop

loop:
  %indvars = phi i64 [ 0, %entry ], [ %indvars.next, %loop ]
  %scevgep1 = getelementptr [2 x i32], [2 x i32]* %a, i64 20, i64 %indvars
  %scevgep = getelementptr [2 x i32], [2 x i32]* %a, i64 10, i64 %indvars
  %stptrx = getelementptr inbounds [2 x i32], [2 x i32]* %a, i64 %indvars, i64
0
  store i32 999, i32* %stptrx, align 4
  %value0 = load i32, i32* %scevgep1, align 4
  store i32 %value0, i32* %scevgep, align 4
  %indvars.next = add nuw nsw i64 %indvars, 1
  %exitcond2 = icmp eq i64 %indvars, 9
  br i1 %exitcond2, label %exit, label %loop

exit:
  ret void
}
--------------------------------

This IR is equivalent to the following C program.

--------------------------------
void foo(int a[][2]) {
  for (int i = 0; i < 10; i++) {
    a[i][0] = 999;
    a[10][i] = a[20][i];
  }
}
--------------------------------

a[5][0], a[6][0], ..., a[9][0] should not be updated, but they
are updated. It's a bug.

I confirmed this problem with at least the latest master branch
(commit 10092291d7a) and LLVM 7.1.0.

This problem is not limited to two dimensional array. Also,
not limited to a store operation. Compiling the following C
programs with `clang -O1 -freroll-loops` also has the problem.

--------------------------------
void bar(int x);

void foo(int a[]) {
  #pragma clang loop unroll(disable)
  for (int i = 0; i < 5; i++) {
    bar(a[i]);
    a[20+2*i+0] = a[40+2*i+0];
    a[20+2*i+1] = a[40+2*i+1];
  }
}
--------------------------------

--------------------------------
struct x {
  int m1;
  int m2;
};

void foo(struct x *a) {
  #pragma clang loop unroll(disable)
  for (int i = 0; i < 5; i++) {
    a[i].m1 = 999;
    a[10+i].m1 = a[20+i].m1;
    a[10+i].m2 = a[20+i].m2;
  }
}
--------------------------------</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>