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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to