Mordante marked 8 inline comments as done.
Mordante added inline comments.
================
Comment at: clang/include/clang/Basic/Attr.td:1288
+def Likely : StmtAttr {
+ let Spellings = [CXX11<"", "likely", 201803>];
+ let Documentation = [LikelihoodDocs];
----------------
aaron.ballman wrote:
> Mordante wrote:
> > Mordante wrote:
> > > aaron.ballman wrote:
> > > > Mordante wrote:
> > > > > aaron.ballman wrote:
> > > > > > Hmm, I'm on the fence about specifying `201803` for these
> > > > > > attributes. Given that this is only the start of supporting the
> > > > > > attribute, do we want to claim it already matches the standard's
> > > > > > behavior? Or do we just want to return `1` to signify that we
> > > > > > understand this attribute but we don't yet fully support it in
> > > > > > common cases (such as on labels in switch statements, etc)?
> > > > > >
> > > > > > As another question, should we consider adding a C2x spelling
> > > > > > `[[clang::likely]]` and `[[clang::unlikely]]` to add this
> > > > > > functionality to C?
> > > > > I was also somewhat on the fence, for now I'll change it to specify
> > > > > `1`.
> > > > >
> > > > > I'll have a look at the C2x changes. Just curious do you know whether
> > > > > there's a proposal to add this to C2x?
> > > > > I'll have a look at the C2x changes. Just curious do you know whether
> > > > > there's a proposal to add this to C2x?
> > > >
> > > > There isn't one currently because there is no implementation experience
> > > > with the attributes in C. This is a way to get that implementation
> > > > experience so it's easier to propose the feature to WG14.
> > > > I was also somewhat on the fence, for now I'll change it to specify `1`.
> > >
> > > There seems to be an issue using the `1` so I used `2` instead. (Didn't
> > > want to look closely at the issue.)
> > >
> > > > I'll have a look at the C2x changes. Just curious do you know whether
> > > > there's a proposal to add this to C2x?
> > >
> > > There isn't one currently because there is no implementation experience
> > > with the attributes in C. This is a way to get that implementation
> > > experience so it's easier to propose the feature to WG14.
> >
> > Nice to know. It seems the C2x wasn't at straightforward as I hoped, so I
> > didn't implement it yet. I intend to look at it later. I first want the
> > initial part done to see whether this is the right approach.
> What issues are you running into? 1 is the default value when you don't
> specify a value specifically.
It give the error "clang/include/clang/Basic/Attr.td:265:7: error: Standard
attributes must have valid version information."
================
Comment at: clang/include/clang/Basic/Attr.td:1288
+def Likely : StmtAttr {
+ let Spellings = [CXX11<"", "likely", 201803>];
+ let Documentation = [LikelihoodDocs];
----------------
Mordante wrote:
> aaron.ballman wrote:
> > Mordante wrote:
> > > Mordante wrote:
> > > > aaron.ballman wrote:
> > > > > Mordante wrote:
> > > > > > aaron.ballman wrote:
> > > > > > > Hmm, I'm on the fence about specifying `201803` for these
> > > > > > > attributes. Given that this is only the start of supporting the
> > > > > > > attribute, do we want to claim it already matches the standard's
> > > > > > > behavior? Or do we just want to return `1` to signify that we
> > > > > > > understand this attribute but we don't yet fully support it in
> > > > > > > common cases (such as on labels in switch statements, etc)?
> > > > > > >
> > > > > > > As another question, should we consider adding a C2x spelling
> > > > > > > `[[clang::likely]]` and `[[clang::unlikely]]` to add this
> > > > > > > functionality to C?
> > > > > > I was also somewhat on the fence, for now I'll change it to specify
> > > > > > `1`.
> > > > > >
> > > > > > I'll have a look at the C2x changes. Just curious do you know
> > > > > > whether there's a proposal to add this to C2x?
> > > > > > I'll have a look at the C2x changes. Just curious do you know
> > > > > > whether there's a proposal to add this to C2x?
> > > > >
> > > > > There isn't one currently because there is no implementation
> > > > > experience with the attributes in C. This is a way to get that
> > > > > implementation experience so it's easier to propose the feature to
> > > > > WG14.
> > > > > I was also somewhat on the fence, for now I'll change it to specify
> > > > > `1`.
> > > >
> > > > There seems to be an issue using the `1` so I used `2` instead. (Didn't
> > > > want to look closely at the issue.)
> > > >
> > > > > I'll have a look at the C2x changes. Just curious do you know whether
> > > > > there's a proposal to add this to C2x?
> > > >
> > > > There isn't one currently because there is no implementation experience
> > > > with the attributes in C. This is a way to get that implementation
> > > > experience so it's easier to propose the feature to WG14.
> > >
> > > Nice to know. It seems the C2x wasn't at straightforward as I hoped, so I
> > > didn't implement it yet. I intend to look at it later. I first want the
> > > initial part done to see whether this is the right approach.
> > What issues are you running into? 1 is the default value when you don't
> > specify a value specifically.
> It give the error "clang/include/clang/Basic/Attr.td:265:7: error: Standard
> attributes must have valid version information."
> > > I'll have a look at the C2x changes. Just curious do you know whether
> > > there's a proposal to add this to C2x?
> >
> > There isn't one currently because there is no implementation experience
> > with the attributes in C. This is a way to get that implementation
> > experience so it's easier to propose the feature to WG14.
>
> Nice to know. It seems the C2x wasn't at straightforward as I hoped, so I
> didn't implement it yet. I intend to look at it later. I first want the
> initial part done to see whether this is the right approach.
I had another look and I got it working in C.
================
Comment at: clang/test/SemaCXX/attr-likelihood.cpp:101
+}
+#endif
----------------
aaron.ballman wrote:
> Quuxplusone wrote:
> > aaron.ballman wrote:
> > > Mordante wrote:
> > > > aaron.ballman wrote:
> > > > > Mordante wrote:
> > > > > > Quuxplusone wrote:
> > > > > > > I'd like to see a case like `if (x) [[likely]] i=1;` just to
> > > > > > > prove that it works on statements that aren't blocks or empty
> > > > > > > statements. (My understanding is that this should already work
> > > > > > > with your current patch.)
> > > > > > >
> > > > > > > I'd like to see a case like `if (x) { [[likely]] i=1; }` to prove
> > > > > > > that it works on arbitrary statements. This //should// have the
> > > > > > > same effect as `if (x) [[likely]] { i=1; }`. My understanding is
> > > > > > > that your current patch doesn't get us there //yet//. If it's
> > > > > > > unclear how we'd get there by proceeding along your current
> > > > > > > trajectory, then I would question whether we want to commit to
> > > > > > > this trajectory at all, yet.
> > > > > > I agree it would be a good idea to add a test like `if (x)
> > > > > > [[likely]] i=1;` but I don't feel adding an additional test in this
> > > > > > file proves anything. I'll add a test to
> > > > > > `clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp` to
> > > > > > prove it not only accepts the code but also honours the attribute.
> > > > > > This is especially important due to your correct observation that
> > > > > > `if (x) { [[likely]] i=1; }` doesn't have any effect. The code is
> > > > > > accepted but the CodeGen won't honour the attribute.
> > > > > >
> > > > > > I think we can use the current approach, but I need to adjust
> > > > > > `getLikelihood`. Instead of only testing whether the current `Stmt`
> > > > > > is an `AttributedStmt` it needs to iterate over all `Stmt`s and
> > > > > > test them for the attribute. Obviously it should avoid looking into
> > > > > > `Stmt`s that also use the attribute, e.g:
> > > > > > ```
> > > > > > if(b) {
> > > > > > switch(c) {
> > > > > > [[unlikely]] case 0: ... break; // The attribute "belongs"
> > > > > > to the switch not to the if
> > > > > > [[likely]] case 1: ... break; // The attribute "belongs" to
> > > > > > the switch not to the if
> > > > > > }
> > > > > > }
> > > > > > ```
> > > > > >
> > > > > > This is especially important due to your correct observation that
> > > > > > if (x) { [[likely]] i=1; } doesn't have any effect.
> > > > >
> > > > > This code should diagnose the attribute as being ignored.
> > > > What I understood from Arthur and rereading the standard this should
> > > > work, but the initial version of the patch didn't handle this properly.
> > > > What I understood from Arthur and rereading the standard this should
> > > > work, but the initial version of the patch didn't handle this properly.
> > >
> > > My original belief was that it's acceptable for the attribute to be
> > > placed there in terms of syntax, but the recommended practice doesn't
> > > apply to this case because there's no alternative paths of execution once
> > > you've entered the compound statement. That means:
> > > ```
> > > if (x) [[likely]] { i = 1; }
> > > // is not the same as
> > > if (x) { [[likely]] i = 1; }
> > > ```
> > > That said, I can squint at the words to get your interpretation and your
> > > interpretation matches what's in the original paper
> > > (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0479r2.html#examples).
> > >
> > > Ultimately, I think we should strive for consistency between
> > > implementations, and I think we should file an issue with WG21 to clarify
> > > the wording once we figure out how implementations want to interpret
> > > questions like these.
> > I don't know WG21's actual rationale, but I can imagine a programmer
> > wanting to annotate something like this:
> >
> > #define FATAL(msg) [[unlikely]] log_and_abort("Fatal error!", msg);
> > ...
> > auto packet = receive();
> > if (packet.malformed()) {
> > save_to_log(packet);
> > FATAL("malformed packet");
> > }
> > ...
> >
> > The "absolute unlikeliness" of the malformed-packet codepath is
> > encapsulated within the `FATAL` macro so that the programmer doesn't have
> > to tediously repeat `[[unlikely]]` at some branch arbitrarily far above the
> > `FATAL` point. Compilers actually do this already, every time they see a
> > `throw` — every `throw` is implicitly "unlikely" and taints its whole
> > codepath. We want to do something similar for `[[unlikely]]`.
> >
> > It's definitely going to be unsatisfyingly fuzzy logic, though, similar to
> > how inlining heuristics and `inline` are today.
> >
> > My understanding is that
> >
> > if (x) { [[likely]] i = 1; }
> > if (x) [[likely]] { i = 1; }
> >
> > have exactly the same surface reading: the same set of codepaths exist in
> > both cases, and the same "x true, i gets 1" codepath is `[[likely]]` in
> > both cases. Of course your heuristic might //choose// to treat them
> > differently, just as you might //choose// to treat
> >
> > struct S { int f() { ... } };
> > struct S { inline int f() { ... } };
> >
> > differently for inlining purposes despite their identical surface readings.
> > Compilers actually do this already, every time they see a throw — every
> > throw is implicitly "unlikely" and taints its whole codepath. We want to do
> > something similar for [[unlikely]].
>
> Heh, fun story, one of the use cases I was told was critical when discussing
> this feature in the committee came from the safety-critical space where they
> want to mark `catch` blocks as being likely in order to force the optimizer
> to do its best on the failure path, because that's the code path which had
> the hard requirements for bailing out quickly (so the elevator doesn't kill
> you, car doesn't crash, etc). They needed to be able to write:
> ```
> try {
> ...
> } catch (something& s) [[likely]] {
> ...
> } catch (...) [[likely]] {
> ...
> }
> ```
>
> > My understanding is that ... have exactly the same surface reading
>
> I can read the standard to get to that understanding, but am skeptical that
> programmers will be able to predict what these attributes do anywhere they're
> written for anything but contrived examples with that interpretation. I think
> limiting the impact to only being at branch points is at least explicable
> behavior, otherwise programmers are left reasoning through code like:
> ```
> auto what = []{ FATAL("malformed packet"); };
> if (foo) {
> what();
> } else {
> if (something) {
> what();
> }
> }
> ```
> (Does this make the `foo` branch unlikely? What impact is there on the `else`
> branch?) Now replace the lambda with a call to an inline function, or a GNU
> statement expression, an RAII constructor you can see the definition of, etc
> and ask the same questions.
>
> My fear is that by going with the least restrictive design, programmers will
> eventually treat these attributes the same way they treat use of the
> `register` keyword -- something to be avoided because the best you can hope
> for is the implementation ignores it.
>
> This isn't to say that I'm *opposed* to that approach, it's more that I'm
> skeptical of it unless we have some implementation agreement between major
> compilers about how to set user expectations appropriately.
> > Compilers actually do this already, every time they see a throw — every
> > throw is implicitly "unlikely" and taints its whole codepath. We want to do
> > something similar for [[unlikely]].
>
> Heh, fun story, one of the use cases I was told was critical when discussing
> this feature in the committee came from the safety-critical space where they
> want to mark `catch` blocks as being likely in order to force the optimizer
> to do its best on the failure path, because that's the code path which had
> the hard requirements for bailing out quickly (so the elevator doesn't kill
> you, car doesn't crash, etc). They needed to be able to write:
> ```
> try {
> ...
> } catch (something& s) [[likely]] {
> ...
> } catch (...) [[likely]] {
> ...
> }
> ```
Interesting use case, not sure how feasible it would be to implement it. I
don't know how much it would affect the implementation if the exception
handling. I tested with GCC and ICC and this doesn't compile. Looking at the
standard it shouldn't compile. `catch` http://eel.is/c++draft/except.pre
requires a compound statement http://eel.is/c++draft/stmt.block. (Obviously the
attribute can be placed in the compound statement.)
A use-case I found where placing the attribute inside the compound statement is
when using `goto`. I think this might be especially interesting when using it
in C code.
```
int foo()
{
int result = 0;
struct bar *ptr;
ptr = malloc(sizeof(struct bar));
if(!ptr) {
result = -ENOMEM;
goto err;
}
...
if(!f(ptr)) {
result = -ENOMDEV;
goto err_free;
}
[[unlikely]] err_free:
free(ptr);
[[unlikely]] err:
return result;
}
```
This allows to mark the error paths as `[[unlikely]]` by only placing the
attribute on the label and every `goto` will mark the branch unlikely.
================
Comment at: clang/test/SemaCXX/attr-likelihood.cpp:101
+}
+#endif
----------------
Mordante wrote:
> aaron.ballman wrote:
> > Quuxplusone wrote:
> > > aaron.ballman wrote:
> > > > Mordante wrote:
> > > > > aaron.ballman wrote:
> > > > > > Mordante wrote:
> > > > > > > Quuxplusone wrote:
> > > > > > > > I'd like to see a case like `if (x) [[likely]] i=1;` just to
> > > > > > > > prove that it works on statements that aren't blocks or empty
> > > > > > > > statements. (My understanding is that this should already work
> > > > > > > > with your current patch.)
> > > > > > > >
> > > > > > > > I'd like to see a case like `if (x) { [[likely]] i=1; }` to
> > > > > > > > prove that it works on arbitrary statements. This //should//
> > > > > > > > have the same effect as `if (x) [[likely]] { i=1; }`. My
> > > > > > > > understanding is that your current patch doesn't get us there
> > > > > > > > //yet//. If it's unclear how we'd get there by proceeding along
> > > > > > > > your current trajectory, then I would question whether we want
> > > > > > > > to commit to this trajectory at all, yet.
> > > > > > > I agree it would be a good idea to add a test like `if (x)
> > > > > > > [[likely]] i=1;` but I don't feel adding an additional test in
> > > > > > > this file proves anything. I'll add a test to
> > > > > > > `clang/test/CodeGenCXX/attr-likelihood-if-branch-weights.cpp` to
> > > > > > > prove it not only accepts the code but also honours the
> > > > > > > attribute. This is especially important due to your correct
> > > > > > > observation that `if (x) { [[likely]] i=1; }` doesn't have any
> > > > > > > effect. The code is accepted but the CodeGen won't honour the
> > > > > > > attribute.
> > > > > > >
> > > > > > > I think we can use the current approach, but I need to adjust
> > > > > > > `getLikelihood`. Instead of only testing whether the current
> > > > > > > `Stmt` is an `AttributedStmt` it needs to iterate over all
> > > > > > > `Stmt`s and test them for the attribute. Obviously it should
> > > > > > > avoid looking into `Stmt`s that also use the attribute, e.g:
> > > > > > > ```
> > > > > > > if(b) {
> > > > > > > switch(c) {
> > > > > > > [[unlikely]] case 0: ... break; // The attribute
> > > > > > > "belongs" to the switch not to the if
> > > > > > > [[likely]] case 1: ... break; // The attribute "belongs"
> > > > > > > to the switch not to the if
> > > > > > > }
> > > > > > > }
> > > > > > > ```
> > > > > > >
> > > > > > > This is especially important due to your correct observation that
> > > > > > > if (x) { [[likely]] i=1; } doesn't have any effect.
> > > > > >
> > > > > > This code should diagnose the attribute as being ignored.
> > > > > What I understood from Arthur and rereading the standard this should
> > > > > work, but the initial version of the patch didn't handle this
> > > > > properly.
> > > > > What I understood from Arthur and rereading the standard this should
> > > > > work, but the initial version of the patch didn't handle this
> > > > > properly.
> > > >
> > > > My original belief was that it's acceptable for the attribute to be
> > > > placed there in terms of syntax, but the recommended practice doesn't
> > > > apply to this case because there's no alternative paths of execution
> > > > once you've entered the compound statement. That means:
> > > > ```
> > > > if (x) [[likely]] { i = 1; }
> > > > // is not the same as
> > > > if (x) { [[likely]] i = 1; }
> > > > ```
> > > > That said, I can squint at the words to get your interpretation and
> > > > your interpretation matches what's in the original paper
> > > > (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0479r2.html#examples).
> > > >
> > > > Ultimately, I think we should strive for consistency between
> > > > implementations, and I think we should file an issue with WG21 to
> > > > clarify the wording once we figure out how implementations want to
> > > > interpret questions like these.
> > > I don't know WG21's actual rationale, but I can imagine a programmer
> > > wanting to annotate something like this:
> > >
> > > #define FATAL(msg) [[unlikely]] log_and_abort("Fatal error!", msg);
> > > ...
> > > auto packet = receive();
> > > if (packet.malformed()) {
> > > save_to_log(packet);
> > > FATAL("malformed packet");
> > > }
> > > ...
> > >
> > > The "absolute unlikeliness" of the malformed-packet codepath is
> > > encapsulated within the `FATAL` macro so that the programmer doesn't have
> > > to tediously repeat `[[unlikely]]` at some branch arbitrarily far above
> > > the `FATAL` point. Compilers actually do this already, every time they
> > > see a `throw` — every `throw` is implicitly "unlikely" and taints its
> > > whole codepath. We want to do something similar for `[[unlikely]]`.
> > >
> > > It's definitely going to be unsatisfyingly fuzzy logic, though, similar
> > > to how inlining heuristics and `inline` are today.
> > >
> > > My understanding is that
> > >
> > > if (x) { [[likely]] i = 1; }
> > > if (x) [[likely]] { i = 1; }
> > >
> > > have exactly the same surface reading: the same set of codepaths exist in
> > > both cases, and the same "x true, i gets 1" codepath is `[[likely]]` in
> > > both cases. Of course your heuristic might //choose// to treat them
> > > differently, just as you might //choose// to treat
> > >
> > > struct S { int f() { ... } };
> > > struct S { inline int f() { ... } };
> > >
> > > differently for inlining purposes despite their identical surface
> > > readings.
> > > Compilers actually do this already, every time they see a throw — every
> > > throw is implicitly "unlikely" and taints its whole codepath. We want to
> > > do something similar for [[unlikely]].
> >
> > Heh, fun story, one of the use cases I was told was critical when
> > discussing this feature in the committee came from the safety-critical
> > space where they want to mark `catch` blocks as being likely in order to
> > force the optimizer to do its best on the failure path, because that's the
> > code path which had the hard requirements for bailing out quickly (so the
> > elevator doesn't kill you, car doesn't crash, etc). They needed to be able
> > to write:
> > ```
> > try {
> > ...
> > } catch (something& s) [[likely]] {
> > ...
> > } catch (...) [[likely]] {
> > ...
> > }
> > ```
> >
> > > My understanding is that ... have exactly the same surface reading
> >
> > I can read the standard to get to that understanding, but am skeptical that
> > programmers will be able to predict what these attributes do anywhere
> > they're written for anything but contrived examples with that
> > interpretation. I think limiting the impact to only being at branch points
> > is at least explicable behavior, otherwise programmers are left reasoning
> > through code like:
> > ```
> > auto what = []{ FATAL("malformed packet"); };
> > if (foo) {
> > what();
> > } else {
> > if (something) {
> > what();
> > }
> > }
> > ```
> > (Does this make the `foo` branch unlikely? What impact is there on the
> > `else` branch?) Now replace the lambda with a call to an inline function,
> > or a GNU statement expression, an RAII constructor you can see the
> > definition of, etc and ask the same questions.
> >
> > My fear is that by going with the least restrictive design, programmers
> > will eventually treat these attributes the same way they treat use of the
> > `register` keyword -- something to be avoided because the best you can hope
> > for is the implementation ignores it.
> >
> > This isn't to say that I'm *opposed* to that approach, it's more that I'm
> > skeptical of it unless we have some implementation agreement between major
> > compilers about how to set user expectations appropriately.
> > > Compilers actually do this already, every time they see a throw — every
> > > throw is implicitly "unlikely" and taints its whole codepath. We want to
> > > do something similar for [[unlikely]].
> >
> > Heh, fun story, one of the use cases I was told was critical when
> > discussing this feature in the committee came from the safety-critical
> > space where they want to mark `catch` blocks as being likely in order to
> > force the optimizer to do its best on the failure path, because that's the
> > code path which had the hard requirements for bailing out quickly (so the
> > elevator doesn't kill you, car doesn't crash, etc). They needed to be able
> > to write:
> > ```
> > try {
> > ...
> > } catch (something& s) [[likely]] {
> > ...
> > } catch (...) [[likely]] {
> > ...
> > }
> > ```
> Interesting use case, not sure how feasible it would be to implement it. I
> don't know how much it would affect the implementation if the exception
> handling. I tested with GCC and ICC and this doesn't compile. Looking at the
> standard it shouldn't compile. `catch` http://eel.is/c++draft/except.pre
> requires a compound statement http://eel.is/c++draft/stmt.block. (Obviously
> the attribute can be placed in the compound statement.)
>
> A use-case I found where placing the attribute inside the compound statement
> is when using `goto`. I think this might be especially interesting when using
> it in C code.
> ```
> int foo()
> {
> int result = 0;
> struct bar *ptr;
>
> ptr = malloc(sizeof(struct bar));
> if(!ptr) {
> result = -ENOMEM;
> goto err;
> }
>
> ...
> if(!f(ptr)) {
> result = -ENOMDEV;
> goto err_free;
> }
>
> [[unlikely]] err_free:
> free(ptr);
> [[unlikely]] err:
> return result;
> }
> ```
> This allows to mark the error paths as `[[unlikely]]` by only placing the
> attribute on the label and every `goto` will mark the branch unlikely.
> Ultimately, I think we should strive for consistency between implementations,
> and I think we should file an issue with WG21 to clarify the wording once we
> figure out how implementations want to interpret questions like these.
I agree having consistency would be a good. I did some testing.
It seems GCC's implementation is quite mature and does indeed handle the
attributes inside the compound statements.
It seems MSVC's implementation seems a WIP.
It seems ICC accepts the attribute but it doesn't seem to change its branch
weights.
What would be the best way to discuss this question with the other vendors? I
assume I first need to write a paper, but would it then be best to discuss this
with the other vendors or directly send it to the committee?
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D85091/new/
https://reviews.llvm.org/D85091
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits