This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC/PATCH] Optimize code based on asserts even in NDEBUG mode



On Apr 9, 2004, at 2:22 AM, Paolo Bonzini wrote:


This patch optimizes code in NDEBUG mode based on the conditions
that the program asserts.  This patch, in other words, allows a
function like this

 #include <assert.h>
 #define NDEBUG

 int f(char *x)
 {
   assert (x != NULL);
   return x ? *x : 0;
 }

to be compiled simply as

        movl    4(%esp), %eax
        movsbl  (%eax), %eax
        ret

The trick is to have assert invoke a const/noreturn function (returning
void) in NDEBUG mode, and to remove such invocations in ifcvt.  I see
that this may likely not be the best way, hence the RFC.  To link
this to assert, there will be a GCC-specific assert.h like

#ifndef __GCC_ASSERT_H
#define __GCC_ASSERT_H

#include_next <assert.h>

#if defined __OPTIMIZE__ && defined NDEBUG
#undef assert
extern void __gcc_verify (void) __attribute__ ((__const__, __noreturn__));
#define assert(expr) ((void) ((expr) ? 0 : (__gcc_verify(), 0)))
#endif
#endif

Having implemented exactly the same optimization in another compiler, I can safely point out that this isn't a legal transformation as shown. (And if the staff patent attorney hadn't gone on maternity leave at exactly that time, there's probably be a patent here to worry about too.)


assert() is defined by the C99 standard 7.2 p1-2. p1 says that if NDEBUG is defined, the expression is not evaluated. That means that you would need to ensure that the expression has no side-effects, including overflow, FP traps, and other esoterica.

One approach would be to to define some kind of __builtin_side_effects_p(x) function that checks an expression for side-effects early on in translation without executing it:

#define assert(expr) ((void) (__builtin_side_effects_p(expr) || (expr) ? 0 : (__gcc_verify(), 0)))

p1 also says that each time <assert.h> is included, assert() is redefined according to the current value of NDEBUG. This means that the __GCC_ASSERT_H include guard shown here is illegal.

+------------------------------------------------------------+
| Alexander M. Rosenberg           <mailto:alexr@_spies.com> |
| Nobody cares what I say. Remove the underscore to mail me. |


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]