<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 - [DAGCombiner, BigEndian] wrong-code resulting in visitSRL()"
   href="https://bugs.llvm.org/show_bug.cgi?id=46239">46239</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[DAGCombiner, BigEndian] wrong-code resulting in visitSRL()
          </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>Common Code Generator Code
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>paulsson@linux.vnet.ibm.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=23589" name="attach_23589" title="reduced testcase">attachment 23589</a> <a href="attachment.cgi?id=23589&action=edit" title="reduced testcase">[details]</a></span>
reduced testcase

I came across a csmith wrong-code test case which seems to involve the
DAGCombiner, more precisely visitSRL().

In the reduced test case, two i16 values are loaded and and:ed after the first
load having been shifted right logically 8 bits.

The DAGCombiner inteds to replace the srl + load with a zero-extending load
into @d with an added immediate offset. The offset is however incorrectly
computed to 0, which then gives the result of simply dropping the srl, which is
wrong:

llc -mtriple=s390x-linux-gnu -mcpu=z15 -O3 -o out.s tc_lshr_load.ll

define i32 @fun() {
entry:
  %0 = load i16, i16* @d, align 2
  %1 = lshr i16 %0, 8
  %2 = load i16, i16* @g, align 2
  %and7 = and i16 %1, %2
  store i16 %and7, i16* @d, align 2
  ret i32 0
}

Initial selection DAG: %bb.0 'fun:entry'
SelectionDAG has 17 nodes:
  t0: ch = EntryToken
  t2: i64 = Constant<0>
  t4: i16,ch = load<(dereferenceable load 2 from @d)> t0,
GlobalAddress:i64<i16* @d> 0, undef:i64
  t5: i16 = Constant<8>
  t9: i16,ch = load<(dereferenceable load 2 from @g)> t0,
GlobalAddress:i64<i16* @g> 0, undef:i64
      t11: ch = TokenFactor t4:1, t9:1
        t7: i16 = srl t4, Constant:i32<8>
      t10: i16 = and t7, t9
    t12: ch = store<(store 2 into @d)> t11, t10, GlobalAddress:i64<i16* @d> 0,
undef:i64
  t15: ch,glue = CopyToReg t12, Register:i32 $r2l, Constant:i32<0>
  t16: ch = SystemZISD::RET_FLAG t15, Register:i32 $r2l, t15:1

...
Combining: t7: i16 = srl t4, Constant:i32<8>
 ... into: t21: i16,ch = load<(dereferenceable load 1 from @d, align 2), zext
from i8> t0, GlobalAddress:i64<i16* @d> 0, undef:i64
...

Optimized lowered selection DAG: %bb.0 'fun:entry'
SelectionDAG has 13 nodes:
  t0: ch = EntryToken
  t9: i16,ch = load<(dereferenceable load 2 from @g)> t0,
GlobalAddress:i64<i16* @g> 0, undef:i64
        t10: i16 = and t21, t9
      t17: ch = store<(store 2 into @d)> t21:1, t10, GlobalAddress:i64<i16* @d>
0, undef:i64
    t19: ch = TokenFactor t17, t9:1
  t15: ch,glue = CopyToReg t19, Register:i32 $r2l, Constant:i32<0>
  t21: i16,ch = load<(dereferenceable load 1 from @d, align 2), zext from i8>
t0, GlobalAddress:i64<i16* @d> 0, undef:i64
  t16: ch = SystemZISD::RET_FLAG t15, Register:i32 $r2l, t15:1

The end result is an NC (AND mem/mem) with two 0 offsets, which is clearly
wrong:

        larl    %r1, d
        larl    %r2, g
        nc      0(2,%r1), 0(%r2)
        lhi     %r2, 0
        br      %r14

I beleive the problem to lie in DAGCombiner::ReduceLoadWidth():

  auto AdjustBigEndianShift = [&](unsigned ShAmt) {
    unsigned LVTStoreBits = LN0->getMemoryVT().getStoreSizeInBits();
    unsigned EVTStoreBits = ExtVT.getStoreSizeInBits();
    return LVTStoreBits - EVTStoreBits - ShAmt;
  };

  // For big endian targets, we need to adjust the offset to the pointer to
  // load the correct bytes.
  if (DAG.getDataLayout().isBigEndian())
    ShAmt = AdjustBigEndianShift(ShAmt);

ShAmt is 8 when passed to AdjustBigEndianShift(), but a 0 is returned. It looks
to me that 8 is actually the correct value which in this case should not be
altered.</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>