x86: Skip ISA check for always_inline in system headers

For always_inline in system headers, we don't know if caller's ISAs are
compatible with callee's ISAs until much later.  Skip ISA check for
always_inline in system headers if caller has target attribute.

gcc/

	PR target/98209
	PR target/99744
	* config/i386/i386.c (ix86_can_inline_p): Don't check ISA for
	always_inline in system headers.

gcc/testsuite/

	PR target/98209
	PR target/99744
	* gcc.target/i386/pr98209.c: New test.
	* gcc.target/i386/pr99744-1.c: Likewise.
	* gcc.target/i386/pr99744-2.c: Likewise.
This commit is contained in:
H.J. Lu 2021-03-23 20:04:58 -07:00
parent d99111fd8e
commit 72982851d7
4 changed files with 58 additions and 8 deletions

View File

@ -578,21 +578,29 @@ ix86_can_inline_p (tree caller, tree callee)
&& lookup_attribute ("always_inline",
DECL_ATTRIBUTES (callee)));
/* NB: Skip ISA check for always_inline in system headers if caller
has target attribute. */
bool skip_isa_check = (always_inline
&& caller_tree != target_option_default_node
&& DECL_IN_SYSTEM_HEADER (callee));
cgraph_node *callee_node = cgraph_node::get (callee);
/* Callee's isa options should be a subset of the caller's, i.e. a SSE4
function can inline a SSE2 function but a SSE2 function can't inline
a SSE4 function. */
if (((caller_opts->x_ix86_isa_flags & callee_opts->x_ix86_isa_flags)
!= callee_opts->x_ix86_isa_flags)
|| ((caller_opts->x_ix86_isa_flags2 & callee_opts->x_ix86_isa_flags2)
!= callee_opts->x_ix86_isa_flags2))
if (!skip_isa_check
&& (((caller_opts->x_ix86_isa_flags & callee_opts->x_ix86_isa_flags)
!= callee_opts->x_ix86_isa_flags)
|| ((caller_opts->x_ix86_isa_flags2 & callee_opts->x_ix86_isa_flags2)
!= callee_opts->x_ix86_isa_flags2)))
ret = false;
/* See if we have the same non-isa options. */
else if ((!always_inline
&& caller_opts->x_target_flags != callee_opts->x_target_flags)
|| (caller_opts->x_target_flags & ~always_inline_safe_mask)
!= (callee_opts->x_target_flags & ~always_inline_safe_mask))
else if (!skip_isa_check
&& ((!always_inline
&& caller_opts->x_target_flags != callee_opts->x_target_flags)
|| ((caller_opts->x_target_flags & ~always_inline_safe_mask)
!= (callee_opts->x_target_flags & ~always_inline_safe_mask))))
ret = false;
/* See if arch, tune, etc. are the same. */

View File

@ -0,0 +1,13 @@
/* { dg-do run { target *-*-linux* } } */
/* { dg-options "-O2 -D_FORTIFY_SOURCE=2" } */
#include <stdio.h>
extern int main(int argc, char** argv)
__attribute__ ((__target__ ("no-sse,no-mmx")));
int main(int argc, char** argv)
{
printf ("hello!\n");
return 0;
}

View File

@ -0,0 +1,16 @@
/* { dg-do compile } */
/* { dg-options "-O0" } */
#include <x86intrin.h>
extern unsigned long long int curr_deadline;
extern void bar (void);
__attribute__ ((target("general-regs-only")))
void
foo (void)
{
if (__rdtsc () < curr_deadline)
return;
bar ();
}

View File

@ -0,0 +1,13 @@
/* { dg-do compile { target { ! ia32 } } } */
/* { dg-options "-O2" } */
#include <x86intrin.h>
extern __m128i x, y;
__attribute__ ((target("general-regs-only")))
void
foo (void)
{
x = _mm_move_epi64 (y); /* { dg-error "SSE register return with SSE disabled" } */
}