Mordante planned changes to this revision.
Mordante marked 14 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:
> 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?


================
Comment at: clang/include/clang/Basic/AttrDocs.td:1697
+It's not allowed to annotate a statement with both ``likely`` and
+``unlikely``.  It's not recommended to annotate both branches of an ``if``
+statement with an attribute.
----------------
Quuxplusone wrote:
> aaron.ballman wrote:
> > Why? I would expect this to be reasonable code:
> > ```
> > if (foo) [[likely]] {
> >   ...
> > } else if (bar) [[unlikely]] {
> >   ...
> > } else if (baz) [[likely]] {
> >   ...
> > } else {
> >   ...
> > }
> > ```
> > Especially because I would expect this to be reasonable code:
> > ```
> > switch (value) {
> > [[likely]] case 0: ... break;
> > [[unlikely]] case 1: ... break;
> > [[likely]] case 2: ... break;
> > [[unlikely]] default: ... break;
> > }
> > ```
> > As motivating examples, consider a code generator that knows whether a 
> > particular branch is likely or not and it writes out the attribute on all 
> > branches. Or, something like this:
> > ```
> > float rnd_value = get_super_random_number_between_zero_and_one();
> > if (rnd_value < .1) [[unlikely]] {
> > } else if (rnd_value > .9) [[unlikely]] {
> > } else [[likely]] {
> > }
> > ```
> Right, annotating both/multiple branches of a control statement should be 
> perfectly fine. Even `if (x) [[likely]] { } else [[likely]] { }` should be 
> perfectly okay as far as the code generator is concerned (and we should have 
> a test for that); it's silly, but there's no reason to warn against it in the 
> compiler docs.
> 
> Aaron, notice that `if (x) [[likely]] { } else if (y) [[likely]] { }` is not 
> actually annotating "both" branches of any single `if`-statement. There 
> you're annotating the true branch of an if (without annotating the else 
> branch), and then annotating the true branch of another if (which doesn't 
> have an else branch).
> 
> Mordante, in these docs, please document the "interesting" behavior of the 
> standard attribute on labels — annotating a label is different from 
> annotating the labeled statement itself. In particular,
> 
>     [[likely]] case 1: case 2: foo(); break;
>     case 3: [[likely]] case 4: foo(); break;
>     case 5: case 6: [[likely]] foo(); break;
> 
> indicates that the likely cases are 1, 4, 5, and 6. (1 and 4 because their 
> labels are annotated; 5 and 6 because their control flow passes through an 
> annotated statement. Case 3's control flow passes through an annotated label, 
> but that doesn't matter to the standard attribute.)
Aaron, the current `CodeGen` code for the `switch` statement allows all 
branches to have a weight, for the `if` there are only two weights allowed. As 
Arthur explained the chained `if`s are different statements, so this will work 
properly.

Arthur, I agree we should add the documentation about the `switch`, but I'd 
rather do that when the attributes are implemented for the `switch`. For now I 
think it would make sense to add some documentation about the fact that the 
attribute can be placed inside the `CompoundStmt`.


================
Comment at: clang/include/clang/Basic/AttrDocs.td:1702
+
+At the moment the attribute is only implemented for an ``if`` statement.
+
----------------
aaron.ballman wrote:
> We should document whether we silently accept the attribute in other 
> locations and do nothing with it (I'm not keen on this approach because it 
> surprises users) or that we loudly diagnose the attribute in situations that 
> we don't support it in (I think this is a more user-friendly approach, but 
> may require a separate warning flag).
I'll update the documentation. I intend to continue to work on implementing 
these attributes so I feel adding a temporary diagnostic is not worth the 
effort.


================
Comment at: clang/include/clang/Basic/AttrDocs.td:1708
+
+  // compile with -Wimplicit-fallthrough
+  if (b) [[likely]] {
----------------
aaron.ballman wrote:
> Why does `-Wimplicit-fallthrough` matter?
It doesn't, thanks for spotting the copy-paste error.


================
Comment at: clang/include/clang/Basic/DiagnosticGroups.td:659
 def IgnoredAttributes : DiagGroup<"ignored-attributes">;
+def LikelihoodAttributeIf : DiagGroup<"likelihood-attribute-if">;
 def Attributes : DiagGroup<"attributes", [UnknownAttributes,
----------------
aaron.ballman wrote:
> Is this because you expect people will want to control diagnostics on `if` 
> statements separate from diagnostics in other syntactic locations?
This is about warning about `[[likely]]` in both branches. Due to your an 
Arthur's remarks I've decided to remove them. Especially since Arthur correctly 
pointed out the attribute doesn't need to be directly after the `if(x)`.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:2399
 def err_repeat_attribute : Error<"%0 attribute cannot be repeated">;
+def err_attribute_compatibility : Error<
+  "incompatible attributes '%0' and '%1'">;
----------------
aaron.ballman wrote:
> This isn't needed, we already have `err_attributes_are_not_compatible`.
Thanks I didn't find them before, removed.


================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:2401
+  "incompatible attributes '%0' and '%1'">;
+def note_attribute_compatibility_here : Note<
+  "attribute '%0' declarered here">;
----------------
aaron.ballman wrote:
> We've already got `note_conflicting_attribute` for this as well.
Thanks I didn't find them before, removed.


================
Comment at: clang/lib/CodeGen/CGStmt.cpp:679-680
+
+  // The code doesn't protect against the same attribute on both branches.
+  // The frontend already issued a diagnostic.
+  std::pair<bool, bool> LH = getLikelihood(Then);
----------------
aaron.ballman wrote:
> I don't think the frontend should issue a diagnostic for that situation. I 
> think codegen should handle chains appropriately instead as those seem 
> plausible in reasonable code.
This is the diagnostic about `if(b) [[likely]] {...} else [[likely]] {...}`. 
I'll remove the diagnostic, however the CodeGen will still prioritize the 
`[[likely]]` attribute in the `ThenStmt`. With Arthur's information the user 
can even do more unwise things:
```
if(b) [[likely]] {
    [[unlikely]] ...
} else [[likely]] {
    [[unlikely]]...
}
```
If the user provided conflicting attributes the CodeGen will not fail, but 
might not do what the user wanted.
This doesn't affect the chained `if`:
```
if(b) [[likely]] {
    ...
} else if(c) [[likely]] {
    ...
}
```

For the `switch` it will be allowed to annotate multiple `case`s with the same 
attribute and that should work as intended. (In a `case` it won't 'protect' 
against conflicting attributes in one `case`).


================
Comment at: clang/lib/Sema/SemaStmt.cpp:585
+  // Warn when both the true and false branch of an if statement have the same
+  // likelihood attribute. It's not prohibited, but makes no sense.
+  const LikelyAttr *Likely = nullptr;
----------------
Quuxplusone wrote:
> I agree with Aaron, this doesn't deserve a warning. Or at least there should 
> be some thought put into the "threat model." (Are we protecting against 
> someone typoing `[[likely]]`/`[[likely]]` when they meant 
> `[[likely]]`/`[[unlikely]]`? But they weren't supposed to annotate both 
> branches in the first place...)
Yes it protects against `[[likely]]/[[likely]]`. I've decided to remove the 
warning.


================
Comment at: clang/test/SemaCXX/attr-likelihood.cpp:101
+}
+#endif
----------------
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
    }
}
```



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