-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
wrong code at -Os and above on x86_64-linux-gnu #18374
Comments
-O2 is the same thing as -Os according to the output of: Here are the optimization passes added by -O2 vs -O1:
|
Oops...no-vectorize doesn't make any difference. The bug is somewhere else. |
bugpoint reduced test case opt bugpoint-passinput.bc -instcombine > bugpoint-passinput.out.bc clang bugpoint-passinput.bc clang bugpoint-passinput.out.bc |
Looks like maybe an LSR bug: $ clang t.c -O3 -mllvm -disable-lsr && ./a.out |
Fix without test-cases A = 258 + (-258) It replaces A & 510 with "zext (trunc A to i9) to i32". Since A is a sum, it applies zext(trunc) to its operands. Possible fixes is to add "-" operation for SCEV and keep all constants positive. But IMHO it a bit ridiculous. I propose just use i10 for zext(trunc()) operation instead of i9. See my fix as example. Test case and full featured patch is coming. P.S.: Currently it brakes some tests the checks expressions zext(trunc()) expressions. Though there is nothing special, since inner integer type becomes one bit wider. |
[quote] Sorry for typo. I mean, that solution I could see is to take into account sign bit. While calculating size of effective mask we risk nothing adding 1 more bit. |
I've also been looking at this issue but I have not come to the same conclusion as you. Unfortunately I haven't been able to isolate this so I have no suggestion for a solution yet but I thought it was best to share what I have so far. There is a fair chance that I've misunderstood something on the way, any pointers are appreciated. See inlined comments below.
Inside getZeroExtendExpr() there is a code path with comment: From my understanding this is what causes the problem. I've tried forcing generation of a zero extend expression instead of the addrec and this gave the correct result.
|
Even more reduced test-case. This is my test-case. I just cut off all possible parts and reduced to minimum all the values. So minimum value is not a 179, but 129. Try this with -loop-reduce. Both -258 and -358 values are 10bit width, not 9. So it is incorrect to trunc it to 9 bits. That means, the trouble happened before zext, in trunc operation. Though, perhaps it is also incorrect to perform zext here. Since we have only '+' operation in SCEV, it is obvious, operands could be negative (or how we could implement decrements otherwise?). So it is obvious we should treat operands as signed integers. I think that we have to use sext here. |
Hopefully the paste below wont be too messed up with regards to formatting. if.end: ; preds = %for.body4 When the SCEV for %conv7 is created the %shl register is identified as a user which leads to SCEV creation for the and-expression. Since we have a constant value of 510 as operand to the and-expression we know that at most 9 bits are required for the result. This leads us to calling getZeroExtendExpr(getTruncateExpr(getSCEV(U->getOperand(0), ..., i9) where operand(0) is "%conv7 = mul i32 %indvars.iv".
|
Am I right, that you want to transform zext(358+154=512) into 0 somehow? |
This is my first time looking at this code so I would like someone who is more experienced to give their opinion whether this is the correct approach. |
But you right. there were nothing wrong with trunc. In getZeroExtendExpr look at this: // If the input value is a chrec scev, and we can prove that the value I'll explain what happens in my case here: So I have overflowed counting here. Yet method finished in branch: While we need to analyze Start value as well. I think we have to return: return getAddRecExpr(getSignExtendExpr(Start, Ty), // i9 -254 => i32 -254 That should be correct IMHO. |
After this check... What constant value do you get for "N"?
|
|
Another possible fix |
So, below is summary of my explanation, and how I came, that the reason was typo figured in fix I attached yesterday. Just run "Even more reduced test-case" with -loop-reduce option: And stop debugger in getZeroExtendExpr, on "if (isKnownPositive(Step)) {" line. If you will dump "L", you will see, that loop counter starts from 1; iteration counter is decremented straight before to be checked, and that the condition is "counter > -1.". Though, this story about another SCEV expr, that starts from i9 258 (aka i9 -254), and decreased by 258 every iteration, so on first iteration it is 258, on the second it is 0, and that's it. Now look inside getZeroExtendExpr; for test case: [code] Method "isLoopBackedgeGuardedByCond(L, ICmpInst::ICMP_ULT, AR, N)" returns "true", that was cause of Start and Step zero exstention. Why isLoopBackedgeGuardedByCond returns true anyway? isLoopBackedgeGuardedByCond invokes isImpliedCond inside. In this method though it checks whether Pred is signed and then it does FoundLHS and FoundRHS extension. I just suppose its wrong. Pred is unsigned, and we do zext on FoundLHS/RHS. Originally FoundLHS and FoundRHS are i8 0, and i8 -1, and FoundPred is SGT. |
Zhendong, |
Stepan, just checked. Yes, it's been fixed. Thanks. |
Extended Description
The following code is miscompiled by the current clang trunk and clang 3.3 at -Os and above on x86_64-linux-gnu in both 32-bit and 64-bit modes.
It also affects clang 3.2 at -Os (but neither -O2 nor -O3).
This is a regression from clang 3.1.
$ clang-trunk -v
clang version 3.4 (trunk 195148)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4.6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.4.7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6.3
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/4.6
$
$
$ clang-trunk -O1 small.c; a.out
0
$ clang-3.1 -Os small.c; a.out
0
$
$ clang-trunk -Os small.c; a.out
512
$ clang-3.3 -Os small.c; a.out
512
$ clang-3.2 -Os small.c; a.out
512
$
int printf (const char *, ...);
int a, b, c, d;
char e;
void
foo ()
{
a = 0;
}
int
main ()
{
unsigned char f;
for (; b < 1; b++)
for (e = 1; e >= 0; e--)
{
d = 0;
if (a)
break;
f = 179 * e;
c = f << 1;
foo ();
}
printf ("%d\n", c);
return 0;
}
The text was updated successfully, but these errors were encountered: