<html>
    <head>
      <base href="https://llvm.org/bugs/" />
    </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 --- - Scalarizer generates incorrect code" href="https://urldefense.proofpoint.com/v2/url?u=https-3A__llvm.org_bugs_show-5Fbug.cgi-3Fid-3D24248&d=AwMBaQ&c=8hUWFZcy2Z-Za5rBPlktOQ&r=pF93YEPyB-J_PERP4DUZOJDzFVX5ZQ57vQk33wu0vio&m=jGaTs4HFSPuA2vy0Zc7bODT3DpDaJKO9DL-ul4FL2vE&s=zF0N3LvzDMhLorEDqG9orrOQ16HFoUiEV7lC6CAvzMg&e=">24248</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>Scalarizer generates incorrect code
          </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>Scalar Optimizations
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>fraser@codeplay.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvmbugs@cs.uiuc.edu
          </td>
        </tr>

        <tr>
          <th>Classification</th>
          <td>Unclassified
          </td>
        </tr></table>
      <p>
        <div>
        <pre>I think it's best to explain this with an example program.

C-like pseudo code:

void foo(int x) {
  int2 pos = { 0, x };
  pos.y++;
  for (int i = 0; i < 1; ++i) {
    pos.y++;
  }
}

LLVM IR:

define void @foo(i32 %x) {
entry:
  %vecinit = insertelement <2 x i32> <i32 0, i32 0>, i32 %x, i32 1
  %inc = add i32 %x, 1
  %0 = insertelement <2 x i32> %vecinit, i32 %inc, i32 1
  br label %loop

loop:                                        ; preds = %loop, %entry
  %pos = phi <2 x i32> [ %0, %entry ], [ %new.pos.y, %loop ]
  %i = phi i32 [ 0, %entry ], [ %new.i, %loop ]
  %pos.y = extractelement <2 x i32> %pos, i32 1
  %inc.pos.y = add i32 %pos.y, 1
  %new.pos.y = insertelement <2 x i32> %pos, i32 %inc.pos.y, i32 1
  %new.i = add i32 %i, 1
  %cmp2 = icmp slt i32 %new.i, 1
  br i1 %cmp2, label %loop, label %exit

exit:                                        ; preds = %loop
  ret void
}

Note that the vector %pos is (0, %inc) when it enters the loop. Now, if we run
the scalarizer on this program:

opt -scalarizer -S -o - test.ll

define void @foo(i32 %x) {
entry:
  %vecinit = insertelement <2 x i32> zeroinitializer, i32 %x, i32 1
  %inc = add i32 %x, 1
  %0 = insertelement <2 x i32> %vecinit, i32 %inc, i32 1
  br label %loop

loop:                                             ; preds = %loop, %entry
  %pos.i0 = phi i32 [ 0, %entry ], [ %pos.i01, %loop ]
  %pos.i1 = phi i32 [ %x, %entry ], [ %inc.pos.y, %loop ]
  %i = phi i32 [ 0, %entry ], [ %new.i, %loop ]
  %pos.upto0 = insertelement <2 x i32> undef, i32 %pos.i0, i32 0
  %pos = insertelement <2 x i32> %pos.upto0, i32 %pos.i1, i32 1
  %pos.y = extractelement <2 x i32> %pos, i32 1
  %inc.pos.y = add i32 %pos.y, 1
  %new.pos.y = insertelement <2 x i32> %pos, i32 %inc.pos.y, i32 1
  %pos.i01 = extractelement <2 x i32> %pos, i32 0
  %new.i = add i32 %i, 1
  %cmp2 = icmp slt i32 %new.i, 1
  br i1 %cmp2, label %loop, label %exit

exit:                                             ; preds = %loop
  ret void
}

The scalarizer has scalarized %pos to be (0, %x) when it enters the loop,
instead of (0, %inc). The first operand to the second PHI should be %inc, not
%x.

>From what I've observed while debugging, the bug is in Scatterer::operator[].

What happens is that when scalarizing the PHI, it first deals with element 0.
For this, it walks up the chain of insertelement instructions to find the value
to substitute.

The first insertelement instruction it finds, %0, inserts %inc to element 1. It
caches %inc in CV[1]. Since it hasn't found element 0 yet, it walks up to
%vecinit. This again inserts into element 1, this time %x. It then caches %x in
CV[1], overwriting %inc. Since it still hasn't found element 0, it walks up to
the initializer and returns zero.

Then it scalarizes element 1. It checks its cache and finds CV[1], which is %x.
It uses that in the new PHI instruction. This is the problem. The cache is
overwritten when walking a series of insertelement instructions that don't deal
with the element it's actually searching for.

Perhaps it should only cache elements it's not searching for if they're not
already cached? This would mean the latest insertelement instruction is always
used.</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>