Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[InstCombine] infinite loop in InstCombinerImpl::visitZExt() #51104

Closed
haoxintu opened this issue Sep 6, 2021 · 6 comments
Closed

[InstCombine] infinite loop in InstCombinerImpl::visitZExt() #51104

haoxintu opened this issue Sep 6, 2021 · 6 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla

Comments

@haoxintu
Copy link

haoxintu commented Sep 6, 2021

Bugzilla Link 51762
Resolution FIXED
Resolved on Sep 09, 2021 08:56
Version trunk
OS Linux
CC @rotateright

Extended Description

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 fa69ccd)
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

@haoxintu
Copy link
Author

haoxintu commented Sep 6, 2021

assigned to @rotateright

@rotateright
Copy link
Contributor

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.

@rotateright
Copy link
Contributor

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.

@rotateright
Copy link
Contributor

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 @​#51762 (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
}

@rotateright
Copy link
Contributor

@rotateright
Copy link
Contributor

Should be fixed after:
https://reviews.llvm.org/rG97a4e7b7ff9f

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla
Projects
None yet
Development

No branches or pull requests

2 participants