<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 - WRONG code CFGOpt? InstCombine?"
   href="https://bugs.llvm.org/show_bug.cgi?id=49688">49688</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>WRONG code CFGOpt? InstCombine?
          </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>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=24682" name="attach_24682" title="reduced testcase">attachment 24682</a> <a href="attachment.cgi?id=24682&action=edit" title="reduced testcase">[details]</a></span>
reduced testcase

This program (wrong0.i):

static int *a;
int b, d;
int *c = &b;
int main() {
  int e[3] = {2, 1, -2139220656};
  a = &e[0];
  d = (e[2] < 0) || (e[2] > (7 >> e[2]));
  *c = d;
  printf("%d\n", b);
}

I beleive the right-shift with a known negative value is undefined, but since
the first expression is always true, the program as a whole is still
well-defined, or?

Since e[2] is always less than 0, I would expect the second expression (after
the '||') to never be evaluated. However, SimplifyCFGPass does not understand
that the first expression is always true and so merges them so that they are
always both executed. I wonder why this is allowed...?

  %1 = load i32, i32* %arrayidx1, align 4, !tbaa !6
  %cmp = icmp slt i32 %1, 0
  %shr = ashr i32 7, %1
  %cmp4 = icmp sgt i32 %1, %shr
  %2 = select i1 %cmp, i1 true, i1 %cmp4

Then InstCombine decides to remove the first check against less than zero:

  %arrayidx1 = getelementptr inbounds [3 x i32], [3 x i32]* %e, i64 0, i64 2
  %1 = load i32, i32* %arrayidx1, align 4, !tbaa !6
  %shr = lshr i32 7, %1
  %2 = icmp ugt i32 %1, %shr
  %lor.ext = zext i1 %2 to i32
  store i32 %lor.ext, i32* @d, align 4, !tbaa !6

So it seems that the user has written a well-defined program, but the compiler
has failed to realize this through the known constants.


clang -march=arch13 -O1 wrong0.i -o a.out -w; ./a.out
1
clang -march=arch13 -O2 wrong0.i -o a.out -w; ./a.out
0
clang -march=arch13 -O2 wrong0.i -o a.out -mllvm -enable-gvn-memdep=false -w;
./a.out
1
clang -march=arch13 -O2 wrong0.i -o a.out -mllvm -memssa-check-limit=0 -w;
./a.out
0

The store of '0' to @d is then later produced by GVN:

*** IR Dump After MergedLoadStoreMotionPass ***
; Function Attrs: nofree nounwind
define dso_local signext i32 @main() local_unnamed_addr #0 {
entry:
  %e = alloca [3 x i32], align 4
  %0 = bitcast [3 x i32]* %e to i8*
  call void @llvm.lifetime.start.p0i8(i64 12, i8* nonnull %0) #2
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 4
dereferenceable(12) %0, i8* noundef nonnull align 4 dereferenceable(12) bitcast
([3 x i32]* @__const.main.e to i8*), i64 12, i1 false)
  %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %e, i64 0, i64 0
  store i32* %arrayidx, i32** @a, align 8, !tbaa !2
  %arrayidx1 = getelementptr inbounds [3 x i32], [3 x i32]* %e, i64 0, i64 2
  %1 = load i32, i32* %arrayidx1, align 4, !tbaa !6
  %shr = lshr i32 7, %1
  %2 = icmp ugt i32 %1, %shr
  %lor.ext = zext i1 %2 to i32
  store i32 %lor.ext, i32* @d, align 4, !tbaa !6
  %3 = load i32*, i32** @c, align 8, !tbaa !2
  store i32 %lor.ext, i32* %3, align 4, !tbaa !6
  %4 = load i32, i32* @b, align 4, !tbaa !6
  %call = call signext i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1)
getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 signext
%4)
  call void @llvm.lifetime.end.p0i8(i64 12, i8* nonnull %0) #2
  ret i32 0
}

*** IR Dump After GVN ***
; Function Attrs: nofree nounwind
define dso_local signext i32 @main() local_unnamed_addr #0 {
entry:
  %e = alloca [3 x i32], align 4
  %0 = bitcast [3 x i32]* %e to i8*
  call void @llvm.lifetime.start.p0i8(i64 12, i8* nonnull %0) #2
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* noundef nonnull align 4
dereferenceable(12) %0, i8* noundef nonnull align 4 dereferenceable(12) bitcast
([3 x i32]* @__const.main.e to i8*), i64 12, i1 false)
  %arrayidx = getelementptr inbounds [3 x i32], [3 x i32]* %e, i64 0, i64 0
  store i32* %arrayidx, i32** @a, align 8, !tbaa !2
  %arrayidx1 = getelementptr inbounds [3 x i32], [3 x i32]* %e, i64 0, i64 2
  store i32 0, i32* @d, align 4, !tbaa !6
  %1 = load i32*, i32** @c, align 8, !tbaa !2
  store i32 0, i32* %1, align 4, !tbaa !6
  %2 = load i32, i32* @b, align 4, !tbaa !6
  %call = call signext i32 (i8*, ...) @printf(i8* nonnull dereferenceable(1)
getelementptr inbounds ([4 x i8], [4 x i8]* @.str, i64 0, i64 0), i32 signext
%2)
  call void @llvm.lifetime.end.p0i8(i64 12, i8* nonnull %0) #2
  ret i32 0
}</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>