-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Use getMetadataLayout offset instead of manual gep #29204
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
Use getMetadataLayout offset instead of manual gep #29204
Conversation
This looks right to me. Thanks for the cleanup! |
@swift-ci please test |
Build failed |
@compnerd thanks! I'll update the broken tests. Could you also run the benchmarks? |
Build failed |
I spent a bit of time debugging this. At least some of the tests are failing because Anyway, I'll keep debugging, but I'm curious if anyone has ideas as to the source of the issue. |
@swift-ci please benchmark |
I originally misdiagnosed the problem. I'm still not quite sure what the issue is but, somehow the standard library was miscompiled. Here are a few examples of failures, both these fail when being jitted but not compiled. The following triggers the assertion: let foo = (0 ..< 10).map { $0 } And the following hits a bad access in struct Foo { var x : Int }
let mirror = Mirror(reflecting: Foo(x: 0)) Still trying to find a reproducer that doesn't make use of the miscompiled standard library. |
You could try having the compiler generate both the old and new code patterns, and insert an assertion function call that the offsets match, to help track down where the behavior is changing. |
@jckarter thanks for the suggestion! I tried doing something similar. I dumped the LLVM IR modules and looked at a diff. I couldn't spot any issues and they both compiled and ran fine. It seems the issue is only when they're executed by the JIT. Is there a way to give the swift JIT an LLVM IR file? |
IIRC you can pass the frontend |
What I was thinking was that you could change the compiler to emit a runtime assertion that the two codegen paths produce equivalent results, which you could then use to run the test suite and hopefully catch a trap near the point where the runtime behavior diverges. |
@jckarter thanks, the define i32 @main(i32, i8**) {
%8 = alloca swifterror %swift.error*, align 8
store %swift.error* null, %swift.error** %8, align 8
; ...
%40 = call swiftcc %swift.bridge* @"$sSlsE3mapySayqd__Gqd__7ElementQzKXEKlF"(i8* bitcast (void (%TSi*, %TSi*, %swift.refcounted*, %swift.error**)* @"$sS2is5Error_pIgydzo_S2isAA_pIegnrzo_TRTA" to i8*), %swift.opaque* %32, %swift.type* %37, %swift.type* @"$sSiN", i8** %38, %swift.opaque* noalias nocapture swiftself %39, %swift.error** noalias nocapture swifterror dereferenceable(8) %8)
%41 = load %swift.error*, %swift.error** %8, align 8
%42 = icmp ne %swift.error* %41, null
br i1 %42, label %bar, label %foo
foo:
; ...
ret i32 0
bar:
store %swift.error* null, %swift.error** %8, align 8
call void @llvm.stackrestore(i8* %30)
unreachable
} The program errors because I'll try adding Sorry, but I still don't quite understand what you are suggesting with the runtime assertion. How would you suggest I test the codegen paths? |
For example, you could emit the old way, take the result, emit the new way using |
@jckarter ahh, I see! That's a really good idea. Now I see what you mean. I'll try that. |
The assertion was extremely helpful when debugging this. @jckarter What is Example (from the standard library):
Edit: I should add that the old code returned |
In the case of
so a metadata record layout is going to be like this:
so 40 looks to be right for |
@jckarter thanks a lot for that explanation. Very helpful. I understand the problem now, I thought that I could get the Anyway, I'll update the code later today, which should fix it. Thanks again for all the help/explaining. |
All fixed. The tests are passing now. @jckarter thanks again for the help. Edit: could someone re-trigger the bots? |
@swift-ci Please test |
Build failed |
Build failed |
This patch eliminates one GEP instruction in the llvm-ir. Do you think it would be worth running the benchmarks too? I know the original patch had code-size improvements but, I think those may not exist anymore (now that the codegen is correct). |
@swift-ci Please benchmark |
Performance: -O
Code size: -OPerformance: -Osize
Code size: -OsizePerformance: -Onone
Code size: -swiftlibsHow to read the dataThe tables contain differences in performance which are larger than 8% and differences in code size which are larger than 1%.If you see any unexpected regressions, you should consider fixing the Noise: Sometimes the performance results (not code size!) contain false Hardware Overview
|
Intresting-- those results are not at all what I would have expected. The Osize performance regressions are especially unexpected. I wish there was also a table for Onone code size. Anyway, at least there's a small improvement in one of the Onone benchmarks. Should I be worried about any of the regressions? Is there any way they're incorrect? |
The performance numbers all look like noise to me. I wouldn't worry about them. I think this is good to go. |
Sounds good. Thanks for all the help with this patch! |
This patch updates
getOffsetForIndex
to useStructMetadataLayout::getFieldOffset
instead of emitting a swift type metadata call. In some cases, this generates smaller/faster assembly because there is now only an alloc and gep instead of also having the previous swift type metadata calls.All the IRGen tests succeed but I'm not very familiar with this part of the codebase so, there may be things I am missing (tests, other methods that need to be updated, etc.).