This is the mail archive of the gcc@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: Functions that are CSEable but not pure


On Oct 11, 2012, Jason Merrill <jason@redhat.com> wrote:

> On 10/11/2012 11:14 AM, Alexandre Oliva wrote:
>> How about marking the singleton containing the call to the initializer
>> as always_inline, but not the initializer itself?
>> 
>> The compiler can then infer that initialized is set on the first inlined
>> call and optimize away subsequent tests and initializer calls
>> (call_some_function_that_may_modify_memory).

> That would require exporting the initialized flag in addition to the
> initializer function; currently it is private to the translation unit
> with the initializer function.  That is, the wrapper currently looks
> like

> int& i_wrap() { if (i_init) i_init(); return i; }

This is not entirely clear to me; where is i defined in the first place?
Is it i_init that defines and tests i_initialized?

I.e., do we translate:

[EXTERN] thread_local T i;

int f()
{
  T& j = i;
  ...
}

to:

[EXTERN] __thread T i;

#if !EXTERN
void
i_init()
{
  static __thread bool initialized;
  if (!initialized)
    {
      initialized = true;
      i.T();
    }
}
#endif

static T&
i_wrap ()
{
  if (i_init)
    i_init ();
  return i;
}

int
f()
{
  T& j = i_wrap();
  ...
}

?


Consider instead the following expansion:

[EXTERN] __thread T i;

#if !EXTERN
static void i_init (void);

__thread void (*i_initialize)(void) = i_init;

static void
i_init ()
{
  i_initialize = NULL;
  i.T();
}
#else
EXTERN __thread void (*i_initialize)(void);
#endif

static T& __attribute__((__always_inline__))
i_wrap ()
{
  if (i_initialize)
    {
      i_initialize ();
      // this is redundant, but it should enable removal of subsequent calls
      i_initialize = NULL;
    }
  return i;
}

or this:

[EXTERN] __thread T *i;

#if !EXTERN
static __thread T i_data;

void
i_init ()
{
  i = &i_data; // or maybe allocate it dynamically?
  i->T();
}
#else
extern void i_init ();
#endif

static T& __attribute__((__always_inline__))
i_wrap ()
{
  if (!i)
    i_init ();
  return *i; // dereference should enable cse
}

-- 
Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
You must be the change you wish to see in the world. -- Gandhi
Be Free! -- http://FSFLA.org/   FSF Latin America board member
Free Software Evangelist      Red Hat Brazil Compiler Engineer


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