Il 26/05/19 12:36, René J. V. Bertin ha scritto:
Giuseppe D'Angelo via Interest wrote:Hi,On the other hand, Q_ASSUME(cond) tells the compiler that cond is true,After reading the MS doc I sort of understand how you can use the construct to implement a Q_UNREACHABLE (but in the example given I don't see the codegen advantage of `default: Q_UNREACHABLE` vs. not adding a `default:` at all).
There isn't usually a codegen advantage between the two (or maybe there is only in some corner cases; to my book that's a bug report for "missed optimization"). For instance: on compilers lacking a dedicated builtin, Q_ASSUME(x) is indeed implemented as
if (x) {} else { __builtin_unreachable(); }
which clearly shows the semantics of Q_ASSUME, and that it can be implemented in terms of Q_UNREACHABLE.
Look here at a possible example at how it can improve codegen: https://gcc.godbolt.org/z/KlWBRYNot really, I'm afraid. The only thing that's evident to me from there is that there is much fewer generated machine code when you add the assume statement. I don't see at all why that would be, what difference it would make for the loop that it is always iterated over a multiple of 16. I thought the difference might be in evaluating the `i < count` expression, but even after trying to factor that out the difference remains: https://gcc.godbolt.org/z/2Zclp5
In my example, if we tell the compiler that count is a multiple of 16, then the compiler can do a better job at generating code. In the specifics, the compiler can use a vectorized loop using AVX to to the sum 8 integers at a time. If the compiler knows that count is a multiple of 16, then that loop is enough, and indeed only that loop gets emitted. If the compiler does NOT know, then it does the vectorized loop as much as it can, but then it has to deal with the remaining 0-7 integers, which get dealt in the following generated code, which is an unrolled for loop.
In your example, the compiler can easily deduce that i and count are _both_ multiple of 16 (because they have the same value), so it applies the same optimization. Maybe the codegen is slightly different due to the decreasing loop induction variable that could throw the optimizer off.
Take home message for me is that this is a construct that's probably useful only if you have very intimate knowledge about code generation, and thus not very cross-platform/compiler (and even less cross-architecture). Except for the Q_UNREACHABLE thing.
The optimization is probably the most compelling aspect of it, because Q_ASSUMEs are left in release builds. The other aspect is of course an indication for who reads the code -- that you're making an assumption on certain conditions, so the following code is valid IFF those conditions hold.
What I was hoping it might do is what the Qt documentation suggests, a more graceful version of a Q_ASSERT. That is, a version that does the usual abort in debug builds, but becomes a regular if in production code. I've seen too many examples of coding where a Q_ASSERT is used to guard against situations that are *assumed* never to occur, and then forgotten (or the devs assume everyone else uses debug/development builds). In many if not most of those cases it's trivial to add a graceful handling of the situation.
In production code Q_ASSUME is left (as a hint to the compiler); Q_ASSERT disappears. That's why they're different macros (although, as you point out, conceptually they indicate the same thing -- that a condition is always true, else UB).
In debug builds, Q_ASSUME becomes a Q_ASSERT, so you can debug the case in which the assumption is false.
Hope this helps, -- Giuseppe D'Angelo | giuseppe.dang...@kdab.com | Senior Software Engineer KDAB (France) S.A.S., a KDAB Group company Tel. France +33 (0)4 90 84 08 53, http://www.kdab.com KDAB - The Qt, C++ and OpenGL Experts
smime.p7s
Description: Firma crittografica S/MIME
_______________________________________________ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest