Re: [boost] BOOST_ASSERT and __assume on MSVC

In-Reply-To: <200509282055.j8SKtbXI017230@shannonhoon.balstatdev.susq.com> stewart@sig.com (Rob Stewart) wrote (abridged):
if (!e) { BOOST_ASSERT(false); __assume(false); }
The optimizer can't elide the entire else clause because BOOST_ASSERT(false) is in it.
Do you agree that if the code was: int x = 0; if (!e) { ++x; __assume(false); } cout << x; then the compiler can elide the increment? At this stage I am trying to convince myself that you understand the point I was making, whether or not you agree with how it applies to BOOST_ASSERT. __assume(false) can have retrospective effects. -- Dave Harris, Nottingham, UK.

From: brangdon@cix.compulink.co.uk (Dave Harris)
In-Reply-To: <200509282055.j8SKtbXI017230@shannonhoon.balstatdev.susq.com> stewart@sig.com (Rob Stewart) wrote (abridged):
if (!e) { BOOST_ASSERT(false); __assume(false); }
The optimizer can't elide the entire else clause because BOOST_ASSERT(false) is in it.
Do you agree that if the code was:
int x = 0; if (!e) { ++x; __assume(false); } cout << x;
then the compiler can elide the increment?
No. Having said that, do let me explain that I have *no* experience with __assume(). I am working only from the previously linked documentation and intuition.
At this stage I am trying to convince myself that you understand the point I was making, whether or not you agree with how it applies to BOOST_ASSERT. __assume(false) can have retrospective effects.
If it can, indeed, apply retroactively, as I think you meant, then I'm thoroughly confused as to how it works and how one can apply it consistently. To my way of thinking, it tells the optimizer than any code following the directive, until the end of the scope, can be optimized assuming the condition holds. I can't imagine how the optimizer could safely assume that the condition holds throughout the scope in which it appears, including previous to the directive, but compiler magic can often do wondrous things! (Note that __assume(false) is useless, for it is an expression that the optimizer cannot use to optimize anything. So, while I understand that you were trying to simplify things for the discussion, let's also not lose sight of what is really meant when writing __assume(false) in the above examples.) -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

On 10/3/05, Rob Stewart <stewart@sig.com> wrote:
(Note that __assume(false) is useless, for it is an expression that the optimizer cannot use to optimize anything. So, while I understand that you were trying to simplify things for the discussion, let's also not lose sight of what is really meant when writing __assume(false) in the above examples.)
I think you're wrong. __assume(false) means that this code will never be executed, and as such isnt useless for the optimizer. if(x) { // do something here } else { __assume(false); BOOST_LOG(dbg) << "Error! this code should never execute!" << std::endl; } tells the optimizer that the else will never be taken and that the compiler can elide this and do not write the LOG code. When you write __assume(x != 0) it means to the optimizer that he can assume that x will always be different from 0. When you write __assume(false) it means that that place can never be reached. -- Felipe Magno de Almeida Developer from synergy and Computer Science student from State University of Campinas(UNICAMP). Unicamp: http://www.ic.unicamp.br Synergy: http://www.synergy.com.br "There is no dark side of the moon really. Matter of fact it's all dark."

From: Felipe Magno de Almeida <felipe.m.almeida@gmail.com>
On 10/3/05, Rob Stewart <stewart@sig.com> wrote:
(Note that __assume(false) is useless, for it is an expression that the optimizer cannot use to optimize anything. So, while I understand that you were trying to simplify things for the discussion, let's also not lose sight of what is really meant when writing __assume(false) in the above examples.)
I think you're wrong. __assume(false) means that this code will never be executed, and as such isnt useless for the optimizer.
Hmmm. I guess you're right. Still, it only means that the code following __assume(false) can be elided, not any preceeding code, right? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

On 10/3/05, Rob Stewart <stewart@sig.com> wrote:
Hmmm. I guess you're right. Still, it only means that the code following __assume(false) can be elided, not any preceeding code, right?
I think it wouldnt be impossible to elide the preceeding either, since that cant be executed if the __assume(false) is right after, since __assume(false) can never be reached. IMO we shouldnt rely that neither preceding nor the code that follows __assume(false) couldnt be elided. Independent of how MSVC implements it right now. best regards, -- Felipe Magno de Almeida Developer from synergy and Computer Science student from State University of Campinas(UNICAMP). Unicamp: http://www.ic.unicamp.br Synergy: http://www.synergy.com.br "There is no dark side of the moon really. Matter of fact it's all dark."

Rob Stewart wrote:
From: Felipe Magno de Almeida <felipe.m.almeida@gmail.com>
On 10/3/05, Rob Stewart <stewart@sig.com> wrote:
(Note that __assume(false) is useless, for it is an expression that the optimizer cannot use to optimize anything. So, while I understand that you were trying to simplify things for the discussion, let's also not lose sight of what is really meant when writing __assume(false) in the above examples.)
I think you're wrong. __assume(false) means that this code will never be executed, and as such isnt useless for the optimizer.
Hmmm. I guess you're right. Still, it only means that the code following __assume(false) can be elided, not any preceeding code, right?
The preceding code can be elided if the compiler can prove that it doesn't affect the reachability of __assume(false). ++x can, a function call cannot (in general) without whole program optimization.

From: "Peter Dimov" <pdimov@mmltd.net>
Rob Stewart wrote:
From: Felipe Magno de Almeida <felipe.m.almeida@gmail.com>
On 10/3/05, Rob Stewart <stewart@sig.com> wrote:
(Note that __assume(false) is useless, for it is an expression that the optimizer cannot use to optimize anything. So, while I understand that you were trying to simplify things for the discussion, let's also not lose sight of what is really meant when writing __assume(false) in the above examples.)
I think you're wrong. __assume(false) means that this code will never be executed, and as such isnt useless for the optimizer.
Hmmm. I guess you're right. Still, it only means that the code following __assume(false) can be elided, not any preceeding code, right?
The preceding code can be elided if the compiler can prove that it doesn't affect the reachability of __assume(false). ++x can, a function call cannot (in general) without whole program optimization.
We're talking about the optimizer here, so yes, it can do analysis to prove whether a particular block of code affects whether __assume(false) can be reached. However, I was trying to speak of generalities--which I didn't make clear--such that the appearance of __assume(false) in a block doesn't mean the entire block may be elided, including preceeding code. The optimizer must prove also that the foregoing statements don't have observable side effects before eliding them. In the (elided ;-) example, ++x has a side effect so while it doesn't affect whether __assume(false) is reached, the optimizer shouldn't elide the increment unless it can prove that the new value of x is not used. Are you suggesting that __assume(false) would override that? -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
In the (elided ;-) example, ++x has a side effect so while it doesn't affect whether __assume(false) is reached, the optimizer shouldn't elide the increment unless it can prove that the new value of x is not used. Are you suggesting that __assume(false) would override that?
Yes, I am. __assume( false ) asserts that this point is unreachable. Since ++x always completes, it follows that ++x is unreachable as well, so it can be elided.

From: "Peter Dimov" <pdimov@mmltd.net>
Rob Stewart wrote:
In the (elided ;-) example, ++x has a side effect so while it doesn't affect whether __assume(false) is reached, the optimizer shouldn't elide the increment unless it can prove that the new value of x is not used. Are you suggesting that __assume(false) would override that?
Yes, I am. __assume( false ) asserts that this point is unreachable. Since ++x always completes, it follows that ++x is unreachable as well, so it can be elided.
If that is the behavior of __assume(false), or at least given that it is a reasonable interpretation of what it could do, then including __assume() in BOOST_ASSERT() seems a little dangerous. Its inclusion should only follow the examination of a large set of extant uses of BOOST_ASSERT() (and perhaps even assert()) to see what effect adding __assume() would have on the generated code. If there are reasonable cases in which the (possible) effects of using __assume() would be deleterious, then there are two possibilities: - Do not include __assume() in BOOST_ASSERT(), but consider adding BOOST_ASSUME() to enable explicit use. - Codify the counterexamples in another macro and document BOOST_ASSERT()'s __assume() functionality and point to the new macro for cases in which that isn't desirable. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

If that is the behavior of __assume(false), or at least given that it is a reasonable interpretation of what it could do, then including __assume() in BOOST_ASSERT() seems a little dangerous.
Which brings up back to the start of this thread :-). But what I've not understood is why the assert macro cannot just define the use of assume when not using asserts (i.e. in the release version), i.e. #if USE_ASSERTS #define BOOST_ASSERT(x) assert(x) #else #if OKAY_TO_USE_ASSUME #define BOOST_ASSERT(x) __assume(x) #else #define BOOST_ASSERT(x) ((void)0) #endif #endif I think it is fair to assume people don't have assert(false) in code that is ready for release - it is just used temporarily during debugging. But just to be sure OKAY_TO_USE_ASSUME should be off by default. Darren
participants (5)
-
brangdon@cix.compulink.co.uk
-
Darren Cook
-
Felipe Magno de Almeida
-
Peter Dimov
-
Rob Stewart