Since C++11, the C++ standard has a forward progress guarantee
[intro.progress], so all such functions must have the mustprogress
requirement. In addition, from C11 and onwards, loops without a non-zero
constant conditional or no conditional are also required to make
progress (C11 6.8.5p6). This patch implements these attribute deductions
so they can be used by the optimization passes.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Time | Test | |
---|---|---|
90 ms | windows > Clang.CodeGen::attr-noprogress.cpp |
Event Timeline
Does that wording apply to both the C and C++ (OpenCL?)?
Regardless, might be good to test that.
clang/test/CodeGen/attr-noprogress.c | ||
---|---|---|
2–3 | Please just FileCheck the expected output. Bonus points for using llvm/utils/update_cc_test_checks.py |
Sorry, Fixed the test, added a C++ test. I checked the C++, OpenCL C, and OpenCL C++ specs and couldn't find anything that diverged from C spec in this regard, but none of them explicitly stated this behavior either.
clang/lib/CodeGen/CGLoopInfo.h | ||
---|---|---|
211 | I'd drop the top-level const on the declaration of NoProgress (that's not a style we typically use in the project). |
clang/lib/CodeGen/CGLoopInfo.h | ||
---|---|---|
211 | My bad, thanks! |
In Summary:
- I changed the llvm loop metadata name to mustprogress, to indicate that loops with this attribute are required to have side-effects.
- The mayprogress function attribute is applied to functions where an infinite loop is found with a constant conditional.
- The mustprogress attribute is applied to loops within a mayprogress function that do not have a constant conditional.
More tightly follows both the C and C++ standards. maynotprogress is only added to C functions when compiled with C11 or later.
In what situation do we generate mustprogress function attributes now? I was expecting them in clang/test/CodeGen/attr-mustprogress.cpp but did not see any.
Split them into pre and post forward progress requirement tests, now the difference is much easier to catch.
clang/test/CodeGen/attr-mustprogress-0.cpp | ||
---|---|---|
2 ↗ | (On Diff #294569) | changing this asap. |
clang/test/CodeGen/attr-mustprogress-1.cpp | ||
---|---|---|
24 ↗ | (On Diff #294773) | Now here, and below with while(1) I would *not* expect mustprogress. |
185 ↗ | (On Diff #294773) | Here I would not expect the function attr but the metadata on the second loop. I guess we might want to add the metadata always for loops w/o a constant condition especially because the order of the two loops might be swapped (please add a test). |
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
774 | Also in C? And C2x in the end is probably CPLusPlus2x? | |
862 | Maybe call this FnIsMustProgress or the other one LoopMustProgress. | |
866 | same as above | |
910 | same as above. Don't we have to update IsMustProgress here too? | |
clang/lib/CodeGen/CodeGenFunction.cpp | ||
1150 | no braces. why the mustprogress check? | |
1156 | Say that we do this late because we need to see the body. |
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
774 |
Not quite sure what you mean here. But LangOptions.def seems to say that C2x is the upcoming C standard, not any upcoming C++ standard. |
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
774 | A silly question: does old C/C++ not guarantee that loops should make forward progress? |
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
774 | Nope, it was introduced explicitly simultaneously in C11 (6.8.5p6) and C++11 has it implicitly through [intro.progress]. |
One minor nit from me.
@jyknight @aaron.ballman @rjmccall any more thoughts?
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
774 | Move this condition into a helper function somewhere with documentation. If we use another (similar) condition the same. This has to be updated over time and that way makes it much easier (also to read). |
- Added triple to fix mangling errors in test
- Modified (unrelated) recently added test to have the mustprogress attribute
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
770 | Shouldn't this only apply for C? http://eel.is/c++draft/intro.progress#1 does not seem to have this escape hatch? See the example by @xbolva00 for which we fail to eliminate the loops from a C++ source https://godbolt.org/z/jW7son |
I'm happy to add a patch amending this, the reason it wasn't done that way was because at the time and even now, out of icc/clang/msvc/gcc, gcc seems to be the only one that happily removed such loops in C++ (https://godbolt.org/z/W9vj99), and I didn't have a particularly strong opinion on which way we should lean at the time.
I think ideally we would make this decision on what the standard allows. AFAICT the C++ spec for iteration statements (http://eel.is/c++draft/stmt.iter) does not have the same escape hatch as C. So IMO the current behavior is surprising and potentially leads to confusion for users (e.g. wondering why are some loops removed, but others not, even if the C++ spec allows for both to be removed).
There may be practical reasons for opting to be more conservative (e.g. if it would break a large number of user codes), but so far there seems to be no such indication in the discussion. It would probably be good to also implement -ffinite-loops as suggested by @xbolva00 so users can better control this.
I'd drop the top-level const on the declaration of NoProgress (that's not a style we typically use in the project).