-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
miscompile with -O2 (suspected incorrect loop trip count computation) #23169
Comments
anyone? |
Looks like a bug in LSR. This simplified IR looks ok to me: target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" define i32 @main() { preheader: ; preds = %for.inc.1, %entry for.body: ; preds = %preheader for.inc: ; preds = %for.body, %preheader end: ; preds = %for.inc.1 for.body.1: ; preds = %for.inc for.inc.1: ; preds = %for.body.1, %for.inc ; Function Attrs: nounwind |
$ ./llc temp.ll -o - | ./clang -x assembler - ; ./a.out ; echo $? |
I think SCEV is feeding bad data to LSR. From "opt -analyze -scalar-evolution" on your reduced testcase: %zext = zext i32 %iv to i64 This is: %iv = phi i32 [ -1, %entry ], [ %next.1, %for.inc.1 ] If you remove the 'nsw' and 'nuw' parts from the .ll, you get: %zext = zext i32 %iv to i64 I think the nsw and nuw bits are all correct in the .ll, it's something inside SCEV going wrong with wrapping handling. Reasoning I think the no-wrap bits are correct: %next is correct, its first computation is "-1 + 1" which unsigned-wraps but does not signed-wrap. It then does [0..12]+1 none of which wrap in any way. %next.1 is correct, its first add is "0 + 1" which doesn't wrap, and it goes through [0..13]+1, none of which wrap. |
Oh, the problem isn't %zext, it's %iv: %iv = phi i32 [ -1, %entry ], [ %next.1, %for.inc.1 ] That's not right. Starting -1, then iteration 1 it goes "-1 + 2" which clearly violates nuw. Here's the bug in createNodeForPHI: 3531 // If the increment doesn't overflow, then neither the add OBO in this case is "%next12.1 = add nuw nsw i64 %next12, 1" but that's not enough because OBO is just the tail of a chain of computation; OBO->getOperand(0) != PN. |
Fixed in r232134. |
Extended Description
% cat z.cc
#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(int argc, char **argv) {
const int n = 16;
int64_t bins[n] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
for (int ix = 0; ix < n; ++ix)
for (int jx = 0; jx < ix; ++jx)
bins[ix]++;
fprintf(stderr, "%ld\n", bins[10]);
}
% clang++ -O1 z.cc && ./a.out
10
% clang++ -O2 z.cc && ./a.out
4294967306
%
Something is messed up in computation of the loop trip count.
This is r231268 on x86_64 linux.
The text was updated successfully, but these errors were encountered: