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
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.
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.
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 }
https://reviews.llvm.org/D109440
Should be fixed after: https://reviews.llvm.org/rG97a4e7b7ff9f