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