public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Non-inlined functions and mixed architectures
@ 2020-07-23  6:37 Allan Sandfeld Jensen
  2020-07-27  8:33 ` Florian Weimer
  0 siblings, 1 reply; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-07-23  6:37 UTC (permalink / raw)
  To: gcc

A problem that I keep running into is functions defined headers, but used in 
sources files that are compiled with different CPU feature flags (for runtime 
CPU feature selection).

We know to make sure the functions are inlinable and their address never 
taken, but of course in debug builds they are still not inlined. Every so 
often the functions get compiled using some of the optional CPU instructions, 
and if the linker selects the optimized versions those instructions can then 
leak through to instances compiled with different CPU flags where the 
instructions aren't supposed to be used. This happens even in unoptimized 
debug builds as the extended instruction selections doesn't count as an 
optimization.

So far the main workaround for gcc has been to mark the functions as 
always_inline.

I have been wondering if you couldn't use the same technique you used for fix 
similar problems for mixed archs for LTO builds and tag shared functions with 
their archs so they don't get merged by linker?

I know the whole thing could technially be seen as an ODR violation, but it 
would still be great if it was something GCC could just handle it out of the 
box.

Alternatively an compile time option to mark non-inline inline functions as 
weak or not generated at all would when compiling certain files would also 
work. 

Best regards
'Allan



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

* Re: Non-inlined functions and mixed architectures
  2020-07-23  6:37 Non-inlined functions and mixed architectures Allan Sandfeld Jensen
@ 2020-07-27  8:33 ` Florian Weimer
  2020-07-27  8:42   ` Allan Sandfeld Jensen
  0 siblings, 1 reply; 10+ messages in thread
From: Florian Weimer @ 2020-07-27  8:33 UTC (permalink / raw)
  To: Allan Sandfeld Jensen; +Cc: gcc

* Allan Sandfeld Jensen:

> A problem that I keep running into is functions defined headers, but used in 
> sources files that are compiled with different CPU feature flags (for runtime 
> CPU feature selection).
>
> We know to make sure the functions are inlinable and their address never 
> taken, but of course in debug builds they are still not inlined. Every so 
> often the functions get compiled using some of the optional CPU instructions, 
> and if the linker selects the optimized versions those instructions can then 
> leak through to instances compiled with different CPU flags where the 
> instructions aren't supposed to be used. This happens even in unoptimized 
> debug builds as the extended instruction selections doesn't count as an 
> optimization.

You need to provide source code examples.  This isn't supposed to happen
if you declare the functions as static inline.  If a function is emitted
for any reason, it will be local this particular object file.

Plain inline (for C++) works differently and will attempt to share
implementations.

Thanks,
Florian


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

* Re: Non-inlined functions and mixed architectures
  2020-07-27  8:33 ` Florian Weimer
@ 2020-07-27  8:42   ` Allan Sandfeld Jensen
  2020-07-27  8:54     ` Florian Weimer
  0 siblings, 1 reply; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-07-27  8:42 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc

On Montag, 27. Juli 2020 10:33:35 CEST Florian Weimer wrote:
> * Allan Sandfeld Jensen:
> > A problem that I keep running into is functions defined headers, but used
> > in sources files that are compiled with different CPU feature flags (for
> > runtime CPU feature selection).
> > 
> > We know to make sure the functions are inlinable and their address never
> > taken, but of course in debug builds they are still not inlined. Every so
> > often the functions get compiled using some of the optional CPU
> > instructions, and if the linker selects the optimized versions those
> > instructions can then leak through to instances compiled with different
> > CPU flags where the instructions aren't supposed to be used. This happens
> > even in unoptimized debug builds as the extended instruction selections
> > doesn't count as an optimization.
> 
> You need to provide source code examples.  This isn't supposed to happen
> if you declare the functions as static inline.  If a function is emitted
> for any reason, it will be local this particular object file.
> 
> Plain inline (for C++) works differently and will attempt to share
> implementations.
> 
static inline? Hadn't thought of that in a shared header file.

Is harder to do with inline methods in C++ classes though.

A recent example I hit into was methods using a qfloat16 class that 
specializes for F16C when available, see https://codereview.qt-project.org/c/
qt/qtbase/+/307772. Which I guess ought to be split into different classes 
with different constructors, so they don't violate ODR rules to be really safe 
across compilers.

But I guess a case like https://codereview.qt-project.org/c/qt/qtbase/+/308163 
could be solved with static inline instead.

Best regards
Allan



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

* Re: Non-inlined functions and mixed architectures
  2020-07-27  8:42   ` Allan Sandfeld Jensen
@ 2020-07-27  8:54     ` Florian Weimer
  2020-08-04  7:25       ` Allan Sandfeld Jensen
  0 siblings, 1 reply; 10+ messages in thread
From: Florian Weimer @ 2020-07-27  8:54 UTC (permalink / raw)
  To: Allan Sandfeld Jensen; +Cc: gcc

* Allan Sandfeld Jensen:

> On Montag, 27. Juli 2020 10:33:35 CEST Florian Weimer wrote:
>> * Allan Sandfeld Jensen:
>> > A problem that I keep running into is functions defined headers, but used
>> > in sources files that are compiled with different CPU feature flags (for
>> > runtime CPU feature selection).
>> > 
>> > We know to make sure the functions are inlinable and their address never
>> > taken, but of course in debug builds they are still not inlined. Every so
>> > often the functions get compiled using some of the optional CPU
>> > instructions, and if the linker selects the optimized versions those
>> > instructions can then leak through to instances compiled with different
>> > CPU flags where the instructions aren't supposed to be used. This happens
>> > even in unoptimized debug builds as the extended instruction selections
>> > doesn't count as an optimization.
>> 
>> You need to provide source code examples.  This isn't supposed to happen
>> if you declare the functions as static inline.  If a function is emitted
>> for any reason, it will be local this particular object file.
>> 
>> Plain inline (for C++) works differently and will attempt to share
>> implementations.
>> 

> static inline? Hadn't thought of that in a shared header file.
>
> Is harder to do with inline methods in C++ classes though.

Ahh, and anonymous namespaces (the equivalent for that for member
functions) do not work in such cases because the representation of the
class still needs to be shared across API boundaries.  With an anonymous
namspace, that would be undefined.

Thanks,
Florian


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

* Re: Non-inlined functions and mixed architectures
  2020-07-27  8:54     ` Florian Weimer
@ 2020-08-04  7:25       ` Allan Sandfeld Jensen
  2020-08-04 17:44         ` Florian Weimer
  0 siblings, 1 reply; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-08-04  7:25 UTC (permalink / raw)
  To: gcc, Florian Weimer

On Montag, 27. Juli 2020 10:54:02 CEST Florian Weimer wrote:
> * Allan Sandfeld Jensen:
> > On Montag, 27. Juli 2020 10:33:35 CEST Florian Weimer wrote:
> >> * Allan Sandfeld Jensen:
> >> > A problem that I keep running into is functions defined headers, but
> >> > used
> >> > in sources files that are compiled with different CPU feature flags
> >> > (for
> >> > runtime CPU feature selection).
> >> > 
> >> > We know to make sure the functions are inlinable and their address
> >> > never
> >> > taken, but of course in debug builds they are still not inlined. Every
> >> > so
> >> > often the functions get compiled using some of the optional CPU
> >> > instructions, and if the linker selects the optimized versions those
> >> > instructions can then leak through to instances compiled with different
> >> > CPU flags where the instructions aren't supposed to be used. This
> >> > happens
> >> > even in unoptimized debug builds as the extended instruction selections
> >> > doesn't count as an optimization.
> >> 
> >> You need to provide source code examples.  This isn't supposed to happen
> >> if you declare the functions as static inline.  If a function is emitted
> >> for any reason, it will be local this particular object file.
> >> 
> >> Plain inline (for C++) works differently and will attempt to share
> >> implementations.
> > 
> > static inline? Hadn't thought of that in a shared header file.
> > 
> > Is harder to do with inline methods in C++ classes though.
> 
> Ahh, and anonymous namespaces (the equivalent for that for member
> functions) do not work in such cases because the representation of the
> class still needs to be shared across API boundaries.  With an anonymous
> namspace, that would be undefined.
> 
So, would it be possible to have a gcc extension or future C++ attribute that 
worked like static on global functions but could be used on member functions 
(both static and otherwise)?

Perhaps make it universal so it did the same no matter where it was used 
instead of being contextual like 'static'.

Best regards
'Allan



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

* Re: Non-inlined functions and mixed architectures
  2020-08-04  7:25       ` Allan Sandfeld Jensen
@ 2020-08-04 17:44         ` Florian Weimer
  2020-08-04 18:49           ` Allan Sandfeld Jensen
  2020-08-10  7:29           ` RFC: -fno-share-inlines Allan Sandfeld Jensen
  0 siblings, 2 replies; 10+ messages in thread
From: Florian Weimer @ 2020-08-04 17:44 UTC (permalink / raw)
  To: Allan Sandfeld Jensen; +Cc: gcc

* Allan Sandfeld Jensen:

> On Montag, 27. Juli 2020 10:54:02 CEST Florian Weimer wrote:
>> * Allan Sandfeld Jensen:
>> > On Montag, 27. Juli 2020 10:33:35 CEST Florian Weimer wrote:
>> >> * Allan Sandfeld Jensen:
>> >> > A problem that I keep running into is functions defined headers, but
>> >> > used
>> >> > in sources files that are compiled with different CPU feature flags
>> >> > (for
>> >> > runtime CPU feature selection).
>> >> > 
>> >> > We know to make sure the functions are inlinable and their address
>> >> > never
>> >> > taken, but of course in debug builds they are still not inlined. Every
>> >> > so
>> >> > often the functions get compiled using some of the optional CPU
>> >> > instructions, and if the linker selects the optimized versions those
>> >> > instructions can then leak through to instances compiled with different
>> >> > CPU flags where the instructions aren't supposed to be used. This
>> >> > happens
>> >> > even in unoptimized debug builds as the extended instruction selections
>> >> > doesn't count as an optimization.
>> >> 
>> >> You need to provide source code examples.  This isn't supposed to happen
>> >> if you declare the functions as static inline.  If a function is emitted
>> >> for any reason, it will be local this particular object file.
>> >> 
>> >> Plain inline (for C++) works differently and will attempt to share
>> >> implementations.
>> > 
>> > static inline? Hadn't thought of that in a shared header file.
>> > 
>> > Is harder to do with inline methods in C++ classes though.
>> 
>> Ahh, and anonymous namespaces (the equivalent for that for member
>> functions) do not work in such cases because the representation of the
>> class still needs to be shared across API boundaries.  With an anonymous
>> namspace, that would be undefined.
>> 
> So, would it be possible to have a gcc extension or future C++ attribute that 
> worked like static on global functions but could be used on member functions 
> (both static and otherwise)?
>
> Perhaps make it universal so it did the same no matter where it was used 
> instead of being contextual like 'static'.

One caveat is that things get somewhat interesting if such a function
returns an object of static or thread storage duration.  In your
application, you probably want to globalize such objects because they
are all equivalent.  But there might be other cases where this is
different.

vtables are tricky as well, but you probably avoid them in your
scenario.

Thanks,
Florian


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

* Re: Non-inlined functions and mixed architectures
  2020-08-04 17:44         ` Florian Weimer
@ 2020-08-04 18:49           ` Allan Sandfeld Jensen
  2020-08-10  7:29           ` RFC: -fno-share-inlines Allan Sandfeld Jensen
  1 sibling, 0 replies; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-08-04 18:49 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc

On Dienstag, 4. August 2020 19:44:57 CEST Florian Weimer wrote:
> * Allan Sandfeld Jensen:
> > On Montag, 27. Juli 2020 10:54:02 CEST Florian Weimer wrote:
> >> * Allan Sandfeld Jensen:
> >> > On Montag, 27. Juli 2020 10:33:35 CEST Florian Weimer wrote:
> >> >> * Allan Sandfeld Jensen:
> >> >> > A problem that I keep running into is functions defined headers, but
> >> >> > used
> >> >> > in sources files that are compiled with different CPU feature flags
> >> >> > (for
> >> >> > runtime CPU feature selection).
> >> >> > 
> >> >> > We know to make sure the functions are inlinable and their address
> >> >> > never
> >> >> > taken, but of course in debug builds they are still not inlined.
> >> >> > Every
> >> >> > so
> >> >> > often the functions get compiled using some of the optional CPU
> >> >> > instructions, and if the linker selects the optimized versions those
> >> >> > instructions can then leak through to instances compiled with
> >> >> > different
> >> >> > CPU flags where the instructions aren't supposed to be used. This
> >> >> > happens
> >> >> > even in unoptimized debug builds as the extended instruction
> >> >> > selections
> >> >> > doesn't count as an optimization.
> >> >> 
> >> >> You need to provide source code examples.  This isn't supposed to
> >> >> happen
> >> >> if you declare the functions as static inline.  If a function is
> >> >> emitted
> >> >> for any reason, it will be local this particular object file.
> >> >> 
> >> >> Plain inline (for C++) works differently and will attempt to share
> >> >> implementations.
> >> > 
> >> > static inline? Hadn't thought of that in a shared header file.
> >> > 
> >> > Is harder to do with inline methods in C++ classes though.
> >> 
> >> Ahh, and anonymous namespaces (the equivalent for that for member
> >> functions) do not work in such cases because the representation of the
> >> class still needs to be shared across API boundaries.  With an anonymous
> >> namspace, that would be undefined.
> > 
> > So, would it be possible to have a gcc extension or future C++ attribute
> > that worked like static on global functions but could be used on member
> > functions (both static and otherwise)?
> > 
> > Perhaps make it universal so it did the same no matter where it was used
> > instead of being contextual like 'static'.
> 
> One caveat is that things get somewhat interesting if such a function
> returns an object of static or thread storage duration.  In your
> application, you probably want to globalize such objects because they
> are all equivalent.  But there might be other cases where this is
> different.
> 
> vtables are tricky as well, but you probably avoid them in your
> scenario.
> 
Right vtables would be a different story completely. I guess it would only 
make sense for non-virtual inline declared methods, which means a universal 
attribute doesn't make sense.

Application controlled runtime CPU switching with C++ interfaces will remain 
an unreliable hack.

Thanks
Allan






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

* RFC: -fno-share-inlines
  2020-08-04 17:44         ` Florian Weimer
  2020-08-04 18:49           ` Allan Sandfeld Jensen
@ 2020-08-10  7:29           ` Allan Sandfeld Jensen
  2020-08-24  6:52             ` Richard Biener
  1 sibling, 1 reply; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-08-10  7:29 UTC (permalink / raw)
  To: Florian Weimer; +Cc: gcc

[-- Attachment #1: Type: text/plain, Size: 734 bytes --]

Following the previous discussion, this is a proposal for a patch that adds 
the flag -fno-share-inlines that can be used when compiling singular source 
files with a different set of flags than the rest of the project.

It basically turns off comdat for inline functions, as if you compiled without 
support for 'weak' symbols. Turning them all into "static" functions, even if 
that wouldn't normally be possible for that type of function. Not sure if it 
breaks anything, which is why I am not sending it to the patch list.

I also considered alternatively to turn the comdat generation off later during 
assembler production to ensure all processing and optimization of comdat 
functions would occur as normal.

Best regards
Allan

[-- Attachment #2: no-share-inlines.diff --]
[-- Type: text/x-patch, Size: 1582 bytes --]

diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 2b1aca16eb4..78e1f592126 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -1803,6 +1803,10 @@ frtti
 C++ ObjC++ Optimization Var(flag_rtti) Init(1)
 Generate run time type descriptor information.

+fshare-inlines
+C C++ ObjC ObjC++ Var(flag_share_inlines) Init(1)
+Emit non-inlined inlined declared functions to be shared between object files.
+
 fshort-enums
 C ObjC C++ ObjC++ LTO Optimization Var(flag_short_enums)
 Use the narrowest integer type possible for enumeration types.
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 33c83773d33..8de796d16fc 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1957,10 +1957,9 @@ adjust_var_decl_tls_model (tree decl)
 void
 comdat_linkage (tree decl)
 {
-  if (flag_weak)
-    make_decl_one_only (decl, cxx_comdat_group (decl));
-  else if (TREE_CODE (decl) == FUNCTION_DECL
-	   || (VAR_P (decl) && DECL_ARTIFICIAL (decl)))
+  if ((!flag_share_inlines || !flag_weak)
+      && (TREE_CODE (decl) == FUNCTION_DECL
+	  || (VAR_P (decl) && DECL_ARTIFICIAL (decl))))
     /* We can just emit function and compiler-generated variables
        statically; having multiple copies is (for the most part) only
        a waste of space.
@@ -1978,6 +1977,8 @@ comdat_linkage (tree decl)
        should perform a string comparison, rather than an address
        comparison.  */
     TREE_PUBLIC (decl) = 0;
+  else if (flag_weak)
+    make_decl_one_only (decl, cxx_comdat_group (decl));
   else
     {
       /* Static data member template instantiations, however, cannot

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

* Re: RFC: -fno-share-inlines
  2020-08-10  7:29           ` RFC: -fno-share-inlines Allan Sandfeld Jensen
@ 2020-08-24  6:52             ` Richard Biener
  2020-08-24  7:29               ` Allan Sandfeld Jensen
  0 siblings, 1 reply; 10+ messages in thread
From: Richard Biener @ 2020-08-24  6:52 UTC (permalink / raw)
  To: Allan Sandfeld Jensen; +Cc: Florian Weimer, GCC Development

On Mon, Aug 10, 2020 at 9:36 AM Allan Sandfeld Jensen
<linux@carewolf.com> wrote:
>
> Following the previous discussion, this is a proposal for a patch that adds
> the flag -fno-share-inlines that can be used when compiling singular source
> files with a different set of flags than the rest of the project.
>
> It basically turns off comdat for inline functions, as if you compiled without
> support for 'weak' symbols. Turning them all into "static" functions, even if
> that wouldn't normally be possible for that type of function. Not sure if it
> breaks anything, which is why I am not sending it to the patch list.
>
> I also considered alternatively to turn the comdat generation off later during
> assembler production to ensure all processing and optimization of comdat
> functions would occur as normal.

We already have -fvisibility-inlines-hidden so maybe call it
-fvisibility-inlines-static?
Does this option also imply 'static' vtables?

Richard.

> Best regards
> Allan

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

* Re: RFC: -fno-share-inlines
  2020-08-24  6:52             ` Richard Biener
@ 2020-08-24  7:29               ` Allan Sandfeld Jensen
  0 siblings, 0 replies; 10+ messages in thread
From: Allan Sandfeld Jensen @ 2020-08-24  7:29 UTC (permalink / raw)
  To: Richard Biener; +Cc: Florian Weimer, GCC Development

On Montag, 24. August 2020 08:52:04 CEST Richard Biener wrote:
> On Mon, Aug 10, 2020 at 9:36 AM Allan Sandfeld Jensen
> 
> <linux@carewolf.com> wrote:
> > Following the previous discussion, this is a proposal for a patch that
> > adds
> > the flag -fno-share-inlines that can be used when compiling singular
> > source
> > files with a different set of flags than the rest of the project.
> > 
> > It basically turns off comdat for inline functions, as if you compiled
> > without support for 'weak' symbols. Turning them all into "static"
> > functions, even if that wouldn't normally be possible for that type of
> > function. Not sure if it breaks anything, which is why I am not sending
> > it to the patch list.
> > 
> > I also considered alternatively to turn the comdat generation off later
> > during assembler production to ensure all processing and optimization of
> > comdat functions would occur as normal.
> 
> We already have -fvisibility-inlines-hidden so maybe call it
> -fvisibility-inlines-static?
That could make sense.

> Does this option also imply 'static' vtables?
> 
I don't think so. It affects functions declarations. It probably also affect 
virtual functions, but as far as I know the place changed only affects the 
functions not the virtual table. So there could still be a duplicated virtual 
table with the wrong methods, that then depends on linking if it will be used 
globally. I am not sure I dare change that, having different virtual tables 
for the same class depending on where it is allocated sounds like a way to 
break some things.

I wouldn't use virtual tables anyway when dealing with mixed architectures.

Best regards
Allan



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

end of thread, other threads:[~2020-08-24  7:29 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-23  6:37 Non-inlined functions and mixed architectures Allan Sandfeld Jensen
2020-07-27  8:33 ` Florian Weimer
2020-07-27  8:42   ` Allan Sandfeld Jensen
2020-07-27  8:54     ` Florian Weimer
2020-08-04  7:25       ` Allan Sandfeld Jensen
2020-08-04 17:44         ` Florian Weimer
2020-08-04 18:49           ` Allan Sandfeld Jensen
2020-08-10  7:29           ` RFC: -fno-share-inlines Allan Sandfeld Jensen
2020-08-24  6:52             ` Richard Biener
2020-08-24  7:29               ` Allan Sandfeld Jensen

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