public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Pure function for only some arguments
@ 2021-05-21 15:00 Florian Weimer
  2021-05-21 16:54 ` Martin Sebor
  0 siblings, 1 reply; 2+ messages in thread
From: Florian Weimer @ 2021-05-21 15:00 UTC (permalink / raw)
  To: gcc-help

Is it possible to declare an extern function pure for just some
arguments?

To clarify, let's assume I have a function

  extern int *func (int);

and I want it to be pure for func (0), func (1), func (3), but not for
func (2).  Is this possible?

Will something like this work?

static inline int *
func (int i)
{
  if (i == 2)
    {
      extern int *func_alias_1 (int) __asm__ ("func");
      return func_alias_1 (i);
    }
  else
    {
      extern int *func_alias_2 (int) __asm__ ("func") __attribute__ ((pure));
      return func_alias_2 (i);
    }
}

Thanks,
Florian


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Pure function for only some arguments
  2021-05-21 15:00 Pure function for only some arguments Florian Weimer
@ 2021-05-21 16:54 ` Martin Sebor
  0 siblings, 0 replies; 2+ messages in thread
From: Martin Sebor @ 2021-05-21 16:54 UTC (permalink / raw)
  To: Florian Weimer, gcc-help

On 5/21/21 9:00 AM, Florian Weimer via Gcc-help wrote:
> Is it possible to declare an extern function pure for just some
> arguments?
> 
> To clarify, let's assume I have a function
> 
>    extern int *func (int);
> 
> and I want it to be pure for func (0), func (1), func (3), but not for
> func (2).  Is this possible?
> 
> Will something like this work?
> 
> static inline int *
> func (int i)
> {
>    if (i == 2)
>      {
>        extern int *func_alias_1 (int) __asm__ ("func");
>        return func_alias_1 (i);
>      }
>    else
>      {
>        extern int *func_alias_2 (int) __asm__ ("func") __attribute__ ((pure));
>        return func_alias_2 (i);
>      }
> }

It's tricky but I'd say it should work provided func() is declared with
attribute always_inline to make sure all calls to the wrapper function
are inlined.  Without it, some calls may not be treated as pure, and
some might be recursive.  The asm renaming is done very late so it
shouldn't matter for the attribute.

Expanding your test case a bit is a good experiment (the tree dumps
show what happens when):

extern int a[];

static inline int *
func (int i)
{
   if (i == 2)
     {
       extern int *func_alias_1 (int) __asm__ ("func");
       return func_alias_1 (i);
     }
   else
     {
       extern int *func_alias_2 (int) __asm__ ("func") __attribute__ 
((pure));
       return func_alias_2 (i);
     }
}

int* f1 ()
{
   int t = a[1];
   int *p = func (1);    // pure call
   if (t != a[1])        // folded to false
     __builtin_abort ();
   return p;
}

int* f2 ()
{
   int t = a[1];
   int *p = func (2);    // not a pure call
   if (t != a[1])        // not folded
     __builtin_abort ();
   return p;
}

Attribute pure is considered during Gimplification as well during
later stages.  The former clears the side-effects bit for a call
so that might mean that some very early optimizations that depend
on the side-effects bit being clear won't happen.

Martin

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-05-21 16:54 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-21 15:00 Pure function for only some arguments Florian Weimer
2021-05-21 16:54 ` Martin Sebor

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).