-
Notifications
You must be signed in to change notification settings - Fork 13k
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
next_back for a Vec is optimized incorrectly on i686 #52026
Comments
I bisected the change to be between nightlies rustc 1.24.0-nightly (0077d12 2017-12-14) (good) and rustc 1.24.0-nightly (77efd68 2017-12-15) (bad) I saw two differences in LLVM IR between good and bad versions:
and good one has
bad IR also has an additional load instruction in the assertion panic branch |
cc @eddyb |
So, I think this is an LLVM issue: I tried to examine how the LLVM IR is optimized, and one transformation is quite.. suspicious It's comparing vec's length to 0xe000_0001 - comparing to 0x1 would be correct, but somehow the three highest bits of the constant are set?? I don't know if there's anything that would allow LLVM do that transformation intentionally, but I don't really have any experience with LLVM either. So I tried to reduce this to something that would reproduce, but modifying that IR to be something that opt accepts and running it through |
I've not examine the IR in detail but that does sound quite suspiciously like something is deeply broken in LLVM. It might be a miscompilation in our build, or a misuse of the APIs when running passes in-process, or a wild write somewhere messing up data structures. But since that sort of bug is very difficult to diagnose, it would be good to make sure whether we really can't reproduce it outside of rustc. For starters, you could add |
Okay, I've got LLVM-only reproduction =) https://gist.github.com/neivv/ae449690d80e0aad853251caa5a3863b#file-thing-ll Haven't tried to reduce from there / find if anything in the input module is actually suspicious yet. |
Figured it out. I haven't had a chance to test this hypothesis but noticed this while looking around how InstCombine works, and I'm confident that this is it: Here's also the best I was able to reduce IR while still reproducing the issue. ; ModuleID = 'tmp1-317d481089b8c8fe83113de504472633.rs'
source_filename = "tmp1-317d481089b8c8fe83113de504472633.rs"
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc"
%S = type { [0 x i32], [2 x i32], [0 x i32] }
; Function Attrs: uwtable
define internal void @_ZN3tmp4main17hcd108164c8e55929E() unnamed_addr {
%1 = call { [0 x %S]*, i32 } @"_ZN68_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..deref..Deref$GT$5deref17h968a5bfabac70869E"()
%2 = extractvalue { [0 x %S]*, i32 } %1, 0
%3 = extractvalue { [0 x %S]*, i32 } %1, 1
%4 = getelementptr inbounds [0 x %S], [0 x %S]* %2, i32 0, i32 0, i32 0, i32 0
%5 = getelementptr inbounds [0 x %S], [0 x %S]* %2, i32 0, i32 %3, i32 0, i32 0
%6 = bitcast i32* %4 to %S*
%7 = bitcast i32* %5 to %S*
%8 = getelementptr inbounds %S, %S* %7, i32 -1
%9 = bitcast %S* %8 to i32*
%10 = bitcast i32* %9 to %S*
%11 = icmp eq %S* %10, %6
br i1 %11, label %12, label %13
; <label>:12: ; preds = %24
ret void
; <label>:13: ; preds = %12, %50
ret void
}
declare hidden { [0 x %S]*, i32 } @"_ZN68_$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..deref..Deref$GT$5deref17h968a5bfabac70869E"() unnamed_addr |
Incredibly work! 👏 I've managed to reduce your test case a bit further. As should be expected from the root cause you identified, changing the pointer size to 64 bit makes the issue disappear. Trying to simplify the types and GEPs further runs into the problem that other (simpler and correct) GEP optimizations fire first. target datalayout = "p:32:32"
%S = type { [2 x i32] }
define i1 @foo([0 x %S]* %p, i32 %n) {
%start.cast = bitcast [0 x %S]* %p to %S*
%end = getelementptr inbounds [0 x %S], [0 x %S]* %p, i32 0, i32 %n, i32 0, i32 0
%end.cast = bitcast i32* %end to %S*
%last = getelementptr inbounds %S, %S* %end.cast, i32 -1
%cmp = icmp eq %S* %last, %start.cast
ret i1 %cmp
} Someone with a http://bugs.llvm.org/ account should report this issue upstream (I should really request one soon, but, well, I'm not doing that now). |
Update LLVM submodule Fixes rust-lang#52026. Fixes rust-lang#56618. r? @alexcrichton
Optimized code of the following program panics if
-C codegen-units
is not 1.The text was updated successfully, but these errors were encountered: