public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Don't emit diagnostic about redefined extern inline always_inline functions (PR tree-optimization/33763)
@ 2007-11-06 15:47 Jakub Jelinek
  2007-11-12  1:47 ` Mark Mitchell
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2007-11-06 15:47 UTC (permalink / raw)
  To: gcc-patches

Hi!

No GCC so far has been able to inline extern inline functions when they
are redefined, because that means have two different bodies for a function,
one for the out of line copy and one for inlining.  While this is now
technically possible with current cgraph stuff, it is a lot of work,
something unlikely to happen in time for 4.3.

So for now redefined extern inline function implies no inlining of that
function, something people are able to live with for now.
Then there is always_inline attribute, which says that the function must be
inlined, or diagnostic issued.
But we never actually documented what happens if you redefine extern
always_inline inline function.  Older GCCs silently didn't inline it,
4.[123] issue diagnostic and fail.  I don't argue that the best thing to
do is just to have two bodies and allow inlining the body from inline
fn while use the separately defined non-inline body for the out of line
copy.  But before then I'd strongly prefer to just do what older GCCs have
done in the past, i.e. silently not inline it.  Otherwise, e.g. libraries
couldn't use almost at all always_inline extern inline functions, because
if some user decides to redefine that function (e.g. for interposition),
the compile will fail unless using some extremely ugly hacks (e.g.
#define __always_inline__ /**/
before including system headers or something similarly horrible).
But the fact that the implementation uses always_inline extern inline
(gnu_inline) functions is really an implementation detail.
glibc 2.7 now uses always_inline functions heavily and e.g. a bunch of
apps don't compile any longer, whenever they e.g. define their own
open for symbol interposition purposes.

Bootstrapped/regtested on x86_64-linux, ok for trunk/4.2/4.1?

2007-11-06  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/33763
	* gcc.dg/pr33763.c: New test.
	* g++.dg/opt/inline13.C: New test.

2007-11-06  Jan Hubicka  <jh@suse.cz>

	PR tree-optimization/33763
	* tree-inline.c (expand_call_inline): Silently ignore always_inline
	attribute for redefined extern inline functions.

--- gcc/tree-inline.c.jj	2007-11-06 09:29:04.000000000 +0100
+++ gcc/tree-inline.c	2007-11-06 16:19:12.000000000 +0100
@@ -2582,6 +2582,12 @@ expand_call_inline (basic_block bb, tree
   if (!cgraph_inline_p (cg_edge, &reason))
     {
       if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn))
+	/* For extern inline functions that get redefined we always
+	   silently ignored alway_inline flag. Better behaviour would
+	   be to be able to keep both bodies and use extern inline body
+	   for inlining, but we can't do that because frontends overwrite
+	   the body.  */
+	  && !cg_edge->callee->local.redefined_extern_inline
 	  /* Avoid warnings during early inline pass. */
 	  && (!flag_unit_at_a_time || cgraph_global_info_ready))
 	{
--- gcc/testsuite/gcc.dg/pr33763.c.jj	2007-11-06 16:19:12.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr33763.c	2007-11-06 16:19:12.000000000 +0100
@@ -0,0 +1,60 @@
+/* PR tree-optimization/33763 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef struct
+{
+  void *a;
+  void *b;
+} T;
+extern void *foo (const char *, const char *);
+extern void *bar (void *, const char *, T);
+extern int baz (const char *, int);
+
+extern inline __attribute__ ((always_inline, gnu_inline)) int
+baz (const char *x, int y)
+{
+  return 2;
+}
+
+int
+baz (const char *x, int y)
+{
+  return 1;
+}
+
+int xa, xb;
+
+static void *
+inl (const char *x, const char *y)
+{
+  T t = { &xa, &xb };
+  int *f = (int *) __builtin_malloc (sizeof (int));
+  const char *z;
+  int o = 0;
+  void *r = 0;
+
+  for (z = y; *z; z++)
+    {
+      if (*z == 'r')
+	o |= 1;
+      if (*z == 'w')
+	o |= 2;
+    }
+  if (o == 1)
+    *f = baz (x, 0);
+  if (o == 2)
+    *f = baz (x, 1);
+  if (o == 3)
+    *f = baz (x, 2);
+
+  if (o && *f > 0)
+    r = bar (f, "w", t);
+  return r;
+}
+
+void *
+foo (const char *x, const char *y)
+{
+  return inl (x, y);
+}
--- gcc/testsuite/g++.dg/opt/inline13.C.jj	2007-11-06 16:20:20.000000000 +0100
+++ gcc/testsuite/g++.dg/opt/inline13.C	2007-11-06 16:21:30.000000000 +0100
@@ -0,0 +1,60 @@
+// PR tree-optimization/33763
+// { dg-do compile }
+// { dg-options "-O2" }
+
+typedef struct
+{
+  void *a;
+  void *b;
+} T;
+extern void *foo (const char *, const char *);
+extern void *bar (void *, const char *, T);
+extern int baz (const char *, int);
+
+extern inline __attribute__ ((always_inline, gnu_inline)) int
+baz (const char *x, int y)
+{
+  return 2;
+}
+
+int
+baz (const char *x, int y)
+{
+  return 1;
+}
+
+int xa, xb;
+
+static void *
+inl (const char *x, const char *y)
+{
+  T t = { &xa, &xb };
+  int *f = (int *) __builtin_malloc (sizeof (int));
+  const char *z;
+  int o = 0;
+  void *r = 0;
+
+  for (z = y; *z; z++)
+    {
+      if (*z == 'r')
+	o |= 1;
+      if (*z == 'w')
+	o |= 2;
+    }
+  if (o == 1)
+    *f = baz (x, 0);
+  if (o == 2)
+    *f = baz (x, 1);
+  if (o == 3)
+    *f = baz (x, 2);
+
+  if (o && *f > 0)
+    r = bar (f, "w", t);
+  return r;
+}
+
+void *
+foo (const char *x, const char *y)
+{
+  return inl (x, y);
+}


	Jakub

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

* Re: [PATCH] Don't emit diagnostic about redefined extern inline always_inline  functions (PR tree-optimization/33763)
  2007-11-06 15:47 [PATCH] Don't emit diagnostic about redefined extern inline always_inline functions (PR tree-optimization/33763) Jakub Jelinek
@ 2007-11-12  1:47 ` Mark Mitchell
  0 siblings, 0 replies; 2+ messages in thread
From: Mark Mitchell @ 2007-11-12  1:47 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

Jakub Jelinek wrote:

> No GCC so far has been able to inline extern inline functions when they
> are redefined, because that means have two different bodies for a function,
> one for the out of line copy and one for inlining. 

> But we never actually documented what happens if you redefine extern
> always_inline inline function.  Older GCCs silently didn't inline it,
> 4.[123] issue diagnostic and fail.

I think 4.x is doing the right thing.  The always_inline attribute means
that the function should always be inlined, and the compiler isn't
inlining the function, so issuing the error makes sense.  The idea with
always_inline extern inline functions is that all calls are inlined; the
only time you get the out-of-line version of the function is if you take
its address.

-- 
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713

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

end of thread, other threads:[~2007-11-12  1:18 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-06 15:47 [PATCH] Don't emit diagnostic about redefined extern inline always_inline functions (PR tree-optimization/33763) Jakub Jelinek
2007-11-12  1:47 ` Mark Mitchell

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