LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 51762 - [InstCombine] infinite loop in InstCombinerImpl::visitZExt()
Summary: [InstCombine] infinite loop in InstCombinerImpl::visitZExt()
Status: RESOLVED FIXED
Alias: None
Product: libraries
Classification: Unclassified
Component: Scalar Optimizations (show other bugs)
Version: trunk
Hardware: PC Linux
: P normal
Assignee: Sanjay Patel
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-09-05 18:23 PDT by Haoxin Tu
Modified: 2021-09-09 08:56 PDT (History)
2 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Haoxin Tu 2021-09-05 18:23:42 PDT
Hi all.

The following valid program makes the trunk version of clang hang at -O1.

$cat small.c
#include <stdint.h>
int a, c, d, e, f;
int16_t b;
void g() {
  uint64_t i;
  uint64_t *r = &i;
  int16_t j;
  uint64_t *k;
  uint64_t **l = &r;
  for (; *k;) {
    int32_t *m = d;
    if (e ? **l = c : 0) {
      int16_t n;
      int32_t o = d;
      if (a)
        m = *l;
      for (n = 4; n; *m = o)
        ;
      int16_t *p = j;
    q:
      j = *p;
    }
  }
  if (*r /= (b % *r || 0 == *r) % (f += d >= b))
    goto q;
}

$clang -w -O1 small.c
//endless compiling

$clang -v
clang version 14.0.0 (https://github.com/llvm/llvm-project fa69ccd189694d0b992323738443ac05a2bcb9ca)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/haoxin/haoxin-data/compilers/llvm-project/build/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Candidate multilib: x32;@mx32
Selected multilib: .;@m64

Thanks,
Haoxin
Comment 1 Sanjay Patel 2021-09-06 11:56:07 PDT
This is an infinite loop from opposing transforms in InstCombine (updated bug title). 

I'm not sure exactly yet, but transformZExtICmp() does something unusual where it checks if it can eliminate instructions before creating new ones. 

If that doesn't work as expected, we could be creating extra instructions which some other transform then tries to reduce.
Comment 2 Sanjay Patel 2021-09-07 09:53:21 PDT
transformZExtICmp() is called twice: first to determine if we have a suitable pattern to reduce and second to actually reduce that pattern. 

The problem is that transformZExtICmp() calls computeKnownBits (ValueTracking) with different parameters (context instruction) on the successive calls. 

On this example, that makes a difference on the bits that are reported as known. 

So we determine that a transform is possible, but then fail to adequately reduce the instructions, so it triggers some other transform to invert this sequence.
Comment 3 Sanjay Patel 2021-09-07 09:56:14 PDT
I don't know exactly what is required to cause the loop, but it seems to take quite a bit to get computeKnownBits to behave differently.

Here is my current IR reduction:

declare void @llvm.assume(i1 noundef) #0

define i1 @PR51762(i32 *%i, i32 %t0, i16 %t1, i64* %p, i32* %d, i32* %f) {
entry:
  br label %for.cond

for.cond:
  %i.sroa.8.0 = phi i32 [ undef, %entry ], [ %i.sroa.8.0.extract.trunc, %cond.true ]
  br i1 undef, label %cond.true, label %for.end11

cond.true:
  %i.sroa.8.0.extract.trunc = ashr i32 %t0, 31
  br label %for.cond

for.end11:
  %s1 = sext i16 %t1 to i64
  %sroa38 = load i32, i32* %i, align 8
  %insert.ext51 = zext i32 %i.sroa.8.0 to i64
  %insert.shift52 = shl nuw i64 %insert.ext51, 32
  %insert.ext39 = zext i32 %sroa38 to i64
  %insert.insert41 = or i64 %insert.shift52, %insert.ext39
  %rem = urem i64 %s1, %insert.insert41
  %ne = icmp ne i64 %rem, 0
  %cmp = icmp eq i64 %insert.insert41, 0
  %spec.select57 = or i1 %ne, %cmp

  %lor.ext = zext i1 %spec.select57 to i32
  %t2 = load i32, i32* %d, align 4
  %conv15 = sext i16 %t1 to i32
  %cmp16 = icmp sge i32 %t2, %conv15
  %conv17 = zext i1 %cmp16 to i32
  %t3 = load i32, i32* %f, align 4
  %add = add nsw i32 %t3, %conv17
  store i32 %add, i32* %f, align 4
  %rem18 = srem i32 %lor.ext, %add
  %conv19 = zext i32 %rem18 to i64
  %div = udiv i64 %insert.insert41, %conv19
  %trunc33 = trunc i64 %div to i32
  store i32 %trunc33, i32* %d, align 8
  %r = icmp ult i64 %insert.insert41, %conv19
  call void @llvm.assume(i1 %r)
  ret i1 %r
}
Comment 4 Sanjay Patel 2021-09-08 08:17:19 PDT
https://reviews.llvm.org/D109440
Comment 5 Sanjay Patel 2021-09-09 08:56:12 PDT
Should be fixed after:
https://reviews.llvm.org/rG97a4e7b7ff9f