-
Notifications
You must be signed in to change notification settings - Fork 349
Remove -funique-traps
and replace it with a better implementation (rdar://158088410)
#11455
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
@swift-ci test llvm |
d500767
to
1a7169d
Compare
@swift-ci test llvm |
1a7169d
to
2752ea9
Compare
The |
@swift-ci test llvm |
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 don't quite follow why the unique_traps
attribute needs this extra complexity, or why we need to specify -fbounds-safety-unique-traps
instead of just -unique-traps
etc. Can't we just have one flag/attribute that applies to both bounds safety and ubsan?
// OPT0-NEXT: [[TMP2:%.*]] = icmp ule ptr [[TMP1]], [[WIDE_PTR_UB]], !annotation [[META2]] | ||
// OPT0-NEXT: br i1 [[TMP2]], label %[[CONT:.*]], label %[[TRAP:.*]], !prof [[PROF3:![0-9]+]], !annotation [[META2]] | ||
// OPT0: [[TRAP]]: | ||
// OPT0-NEXT: call void asm sideeffect "", "n"(i64 0), !annotation [[META2]] |
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.
Why are these calls removed now?
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.
These were never really wanted in the first place. The original -funique-traps
added them because that's how Swift "uniqued" its traps and prevented the backend from merging them.
I took a different approach so these shouldn't be needed anymore.
int other = i_want_to_be_inlined(ptr2, idx); | ||
return ptr[idx]; | ||
} | ||
// |
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.
Are these extra comments emitted by UTC? Seems like a bug imo
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.
If you mean the ones after the closing brace of consume
then I think so.
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.
yeah
@hnrklssn Good questions. Sorry I didn't explain this clearly enough.
UBSan already has
I was trying to make the attribute as general as possible so that it can be upstreamed. If I make it |
Do we want to mirror this by naming this flag something like
The attribute doesn't necessarily have to mirror the flags. It could still be Right now it's constructed generically, but there's only one acceptable use. If upstreamability is important, I suggest implementing the attribute in upstream first: that way it's black on white whether the design of the attribute is actually acceptable for upstream Clang. |
Not really. I think the name in this PR is a lot clearer than
While that's true I did this to simplify the implementation and reduce the chance of a merge conflict because all the logic is in What you propose does simplify things from a user perspective though.
We do not know because we have not approached upstream with this design yet.
It's a nice to have. For the sake of time constraints I'd much rather land what we have now and upstream this after and amend the design as necessary because upstreaming stuff is almost always very slow. |
@swift-ci test llvm |
We could still have it apply only in
The reason I push for this is that these attributes are not a write-once kind of thing, but only used during debugging. Making them quick to write, easy to remember, and hard to use incorrectly lowers the friction to actually use them.
I'm not a huge fan of guessing what upstream wants.
If we don't know whether we'll upstream it, we could just as well tailor it for our specific use case and amend that design afterwards.
It can be slow, but not necessarily - especially for small, targeted things. |
If that's all you're concerned about we can side step a lot of this problem by putting a macro in
|
clang/include/clang/Basic/Attr.td
Outdated
} | ||
|
||
def UniqueTrap : InheritableAttr { | ||
let Spellings = [Clang<"unique_traps">]; |
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.
How are you imagining UniqueTrapKind
will evolve when you get to upstream it? Are you imagining UBSan traps will be controlled by each individual trap kind?
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.
The simplest version would be to have a single enum value for UBSan. A more complicated version would be to allow fine grained control of the different UBSan trap kinds so that it mirrors the behavior of the existing compiler flag.
I will start the process of trying to upstream the attribute but I don’t really want to block this PR on doing that.
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.
Do we need the attributes to land in the builds urgently? Alternatively, you could land the first two commits first unless attributes are urgent. The benefit would be then we don't need to deal with diverging changes there after upstreaming, e.g., if the attribute name has to change or implementation should be different.
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.
We don't so I'll land the first two commits, and work on the commit that adds the attribute in open source.
The implementation was a bit hacky and interacted badly with the hot-cold splitting pass. So it is going to be removed in favor of a different implementation that's simpler. I also investated why `clang/test/BoundsSafety/CodeGen/unique-trap-blocks-O2.c` broke (rdar://150559639). It turns outthat the "trap blocks" started being unintentionally split by the hot-cold splitting pass because in upstream we started adding branch profiling weights (llvm#134310) which the hot-cold splitting pass used as a signal to split the "trap blocks" into their own function (by-passing the logic I originally added to prevent the splitting). While we could fix this it would be very fragile and given that we are removing the implementation anyway it doesn't matter anymore. rdar://158088410
This patch adds a driver/cc1 flag that prevents `-fbounds-safety` traps from being merged. This improves debuggability (because now it is possible to see which check lead to the trap) at the cost of increased code size. It is currently off by default. This implementation adds the `nomerge` attribute on call instructions to `-fbounds-safety` traps at the LLVM IR level and prevents re-using trap blocks during Clang's IRGen when the compiler flag is passed. This was basically already implemented upstream for trapping UBSan which meant the only thing we needed to do was set the `NoMerge` parameter to `true` when calling `EmitTrapCheck`. This is the replacement for the recently removed `-funique-traps` which was less than ideal for several reasons: * The use of `asm` instructions in the trap blocks made analyzing LLVM IR more challenging than it needed to be. * The trap blocks interacted poorly with the hot-cold splitting pass and required fragile workarounds to prevent the trap blocks from being split into their own function. The implementation of `-fbound-safety-unique-traps` has none of these problems. rdar://158088410
2752ea9
to
5890357
Compare
@swift-ci test llvm |
The macOS test failures are known existing issues:
|
This PR does
threetwo things (each done as a separate commit).-funique-traps
flag and implementation. See the commit that does this for a list of the problems with that implementation.-fbounds-safety-unique-traps
flag that uses a completely different implementation to-funique-traps
. The implementation is better becauseasm
instructions in trap block. These caused problems with the hot-cold splitting pass and also made LLVM IR harder to read.nomerge
attribute on calls to the trap intrinsic). So the implementation here is much less likely to conflict with upstream.3. Adds aunique_traps
Clang attribute that can be used to control trap merging at a per-function level. This is intended to be used in situations where code size is really important where it is not feasible to disable trap merging everywhere. The attributes interface is deliberately made generic so that it can be re-used by other compiler instrumentation that emits trap instructions. This is something I will likely try to upstream.rdar://158088410