public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Andy Gibbs <andyg1001@hotmail.co.uk>
To: "Richard Guenther" <richard.guenther@gmail.com>
Cc: <gcc-patches@gcc.gnu.org>
Subject: Re: [C++ Patch] __builtin_choose_expr *bump*
Date: Fri, 21 Oct 2011 14:29:00 -0000	[thread overview]
Message-ID: <BLU0-SMTP3832C5A09DCDC2BCBE85AADE7E80@phx.gbl> (raw)
In-Reply-To: <CAFiYyc3GkPgsvcm=S23qD9=Gt+4JuMh+xaUWk0tKRBM4yT=a+A@mail.gmail.com>

On Friday, October 21, 2011 12:04 PM, Richard Guenther wrote:
> What's the motivation for this?  Why can't it be implemented using C++
> features such as templates and specialization?

Sorry for the delay in my reply.

The motivation, simply put, is to be able to create both templates and 
macros that choose between two or more courses of action at compile time and 
do not generate code for the unchosen action(s), nor (importantly) cause 
compiler errors if the unchosen action(s) should be ill-formed.  The end aim 
is in the generation of source code libraries for compile-time evaluation.

An example in the template domain would be, having template specialisation 
without actually needing to specialise the template.  Ordinarily, 
specialising a template requires a copy to be made and modified according to 
the specialisation.  If the "base" template is changed, the specialisation 
also needs to be so adapted.  Missing one specialisation in a long list 
leads to unpredictable problems (yes, there is bitter experience here!).  If 
the majority of code is identical then it makes sense to try to either 
factor out the identical code and use some meta-template If struct or other 
such magic to limit the scope of the template specialisation.  This can 
become brain-bending if not impossible if, for example, any of the relevant 
expressions cannot be parameters into a meta-template construct.  It can 
also make the code very difficult to follow and debug.  In these cases, 
__builtin_choose_expr can be beneficial to avoid the need to specialise, 
while keeping the clarity and breadth of the template's intended function.

When it comes to macros, the use of __builtin_choose_expr can be very useful 
where one of the expressions would cause a compiler error.  An example of 
such a macro is as follows:

#define CONST(v) \
   __builtin_choose_expr(util::can_use_const_wrapper<decltype(v)>::value, \
       (util::const_wrapper<decltype(v),(v)>::value) : \
       ([&](){ constexpr auto o = (v); return o; })())

namespace util
 {
 template <typename T, T t>
 struct const_wrapper
  { static constexpr T value = t; };

 template <typename T>
 struct can_use_const_wrapper; /* code removed to keep example short! */
 /* value = true for types that can be used in template value parameters */
 }

This is a part of a larger library of code for constexpr functions, a 
majority of which implement algorithms in such a way that the compiler can 
evaluate them but which if evaluated at run-time would have a huge 
performance hit (e.g. CRC calculation on a string).  In this library, a 
second macro FORCE_CONSTEXPR is used to ensure these functions cannot be 
called at run-time or even inlined, but only evaluated at compile-time.  The 
CONST macro is then used, among other things, to hint to the compiler that 
it needs to evaluate at compile-time.

If __builtin_choose_expr in the CONST macro was replaced with "? :" then the 
code using it would fail to compile in certain situations, notably because 
C++ only permits certain types as template value parameters.  However, it is 
not sufficient either to simply use the lambda expression alone since this 
fails with compiler errors in other situations.  This is, I think, one 
example where it is not possible to use templates to get round the 
problem?...

There is a further use of __builtin_choose_expr in this constexpr library, 
which is similar to its use in C, which is to enable a macro function to 
wrap and choose between a compile-time version of the algorithm and a 
run-time version of the algorithm, for example:

#define CrcString(str) (__builtin_choose_expr(__builtin_constant_p(str), \
                                       CONST(CrcString_compiler(str)),   \
                                       CrcString_runtime(str)))

auto string = CrcString("test");

This might of course be implemented using "? :", but only if 
CrcString_compiler(...) and CrcString_runtime(...) return compatible types, 
which need not be so with __builtin_choose_expr.

I hope this gives you some feeling for how __builtin_choose_expr may be 
used, or for that matter how I use it.  I expect that others will find much 
more impressive uses!

Thanks

Andy



  reply	other threads:[~2011-10-21 13:55 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-19 12:26 [C++ Patch] __builtin_choose_expr Andy Gibbs
2011-10-21 10:40 ` [C++ Patch] __builtin_choose_expr *bump* Andy Gibbs
2011-10-21 10:47   ` Richard Guenther
2011-10-21 14:29     ` Andy Gibbs [this message]
2011-10-21 15:28   ` Joseph S. Myers
2011-10-21 15:39     ` Andy Gibbs

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=BLU0-SMTP3832C5A09DCDC2BCBE85AADE7E80@phx.gbl \
    --to=andyg1001@hotmail.co.uk \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).