-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[IRGen] Avoid generating mergeable traps #14729
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
Conversation
Factor out and reuse logic in the lowering of CondFailInst to emit non-mergeable traps, everywhere we emit traps. This should address a debugging quality issue with ambiguous ud2 instructions. rdar://32772768
@swift-ci smoke test |
@swift-ci Please smoke test compiler performance |
Ah, I don't think this is a sure shot to fix the ambiguous ud2 issue for good. We should look at unreachable instructions too. Edit: At least, test/CodeGen/X86/empty-function.ll in llvm indicates that we may generate ud2/int3 without a call to llvm.trap(). |
I feel like the ultimate solution to this belongs at the LLVM level, with some kind of llvm.nonmergeable.trap intrinsic. The asm barriers have the unfortunate side effect of impeding other LLVM-level optimizations we want. |
It would be worth having a non-mergeable trap intrinsic just to avoid inline-asm hacks in the frontend. Out of curiosity though, which optimizations would we unblock with such an intrinsic? At a quick glance I see that GVN and SimplifyCFG treat inline asm instructions as barriers. Both of these passes would have to treat non-mergeable traps as barriers too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, but yes it would be great if we had an LLVM IR trap that was guaranteed to remain unique so that we can post-mortem debug code and know how we reached the trap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Awesome!
|
||
void IRGenFunction::emitTrap(bool EmitUnreachable) { | ||
if (IGM.IRGen.Opts.shouldOptimize()) { | ||
// Emit unique side-effecting inline asm calls in order to eliminate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be the Doxygen comment for the function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this describes the implementation details at too low a level. The doxygen comment I added in the header file describes the high-level effect more succinctly.
@@ -3851,9 +3850,7 @@ static bool hasReferenceSemantics(IRGenSILFunction &IGF, | |||
static llvm::Value *emitIsUnique(IRGenSILFunction &IGF, SILValue operand, | |||
SourceLoc loc, bool checkPinned) { | |||
if (!hasReferenceSemantics(IGF, operand->getType())) { | |||
llvm::Function *trapIntrinsic = llvm::Intrinsic::getDeclaration( | |||
&IGF.IGM.Module, llvm::Intrinsic::ID::trap); | |||
IGF.Builder.CreateCall(trapIntrinsic, {}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way we could prevent this from being called by accident in new code, maybe by hiding access to that particular intrinsic behind a private method? It may not be feasible because it is just modeled as a call...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's possible to interpose a custom builder over llvm::IRBuilder, e.g clang does it. And if we can do that, we can prevent calls to ID::trap from being created. I'll look into it.
PR swiftlang#14729 made more calls to llvm.trap() non-mergeable. This follow-up adds asserts to IRBuilder which make it harder to accidentally introduce mergeable calls to llvm.trap() in the future. The newly-added assertions exposed an issue in GenBuiltin while compiling parts of the stdlib. This PR fixes the issue. Suggested by Adrian Prantl! rdar://32772768
PR #14729 made more calls to llvm.trap() non-mergeable. This follow-up adds asserts to IRBuilder which make it harder to accidentally introduce mergeable calls to llvm.trap() in the future. The newly-added assertions exposed an issue in GenBuiltin while compiling parts of the stdlib. This PR fixes the issue. Suggested by Adrian Prantl! rdar://32772768
Factor out and reuse logic in the lowering of CondFailInst to emit
non-mergeable traps, everywhere we emit traps. This should address a
debugging quality issue with ambiguous ud2 instructions.
rdar://32772768