Segher Boessenkool <seg...@kernel.crashing.org> writes:
> So what should we do about this?  There are arguments for *both*
> behaviours, and apparently with LTO we do not know which flags are
> explicit?

Actually, from my testing, it seems the rs6000_isa_flags_explicit
flags are set correctly in LTO!



On 10/15/19 7:45 AM, Jiufu Guo wrote:
> The difference between 'with LTO' and 'without LTO' is:
> Wit LTO, if a function does not have target attribute in source code,
> then using option attribute from command line(e.g. -mcpu=xxx) as
> isa_flags; and if features (e.g. -mno-vsx, -mvsx) are specified on
> command line, isa_flags_explicit is also set.
> If a function has target attribute in source code explicitly,
> then isa_flags_explicit is set to reflect feature is specified
> explicitly besides explicit features from command line; and isa_flags is
> set as the effective features.
> 
> Without LTO, if a function does not have target attribute in source code,
> then it's isa_flags_explicit and isa_flags are as NULL (target_options
> == NULL). 
> If a function has target attribute in source code, it is same as 'with
> LTO'. 

After reading this a few times and compiling a few unit tests cases in
gdb/cc1/lto1, I agree with your explanation above and with your addition
to my patch.  However, how about a slight modification to your change
with some updated comments?  Updated patch below.

This also incorporates Segher and Andreas's changes to my test case.
I have not looked at your extra test cases, so I have not added them
to this patch, but I like the idea of adding test cases that exercise
this code in LTO context.

I am going on vacation tomorrow, so Jiufu, can you take over ownership
of this combined patch, along with your extra test cases?  I have not
bootstrapped or regtested this, so that still needs doing.  If you're
busy, I can pick this up when I return to work on Monday.

Peter


gcc/
        PR target/70010
        * config/rs6000/rs6000.c (rs6000_can_inline_p): Prohibit inlining if
        the callee explicitly disables some isa_flags the caller is using.

gcc.testsuite/
        PR target/70010
        * gcc.target/powerpc/pr70010.c: New test.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 276975)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -23964,25 +23964,31 @@ rs6000_can_inline_p (tree caller, tree c
   tree caller_tree = DECL_FUNCTION_SPECIFIC_TARGET (caller);
   tree callee_tree = DECL_FUNCTION_SPECIFIC_TARGET (callee);
 
-  /* If callee has no option attributes, then it is ok to inline.  */
+  /* If the callee has no option attributes, then it is ok to inline.  */
   if (!callee_tree)
     ret = true;
 
-  /* If caller has no option attributes, but callee does then it is not ok to
-     inline.  */
-  else if (!caller_tree)
-    ret = false;
-
   else
     {
-      struct cl_target_option *caller_opts = TREE_TARGET_OPTION (caller_tree);
+      HOST_WIDE_INT caller_isa;
       struct cl_target_option *callee_opts = TREE_TARGET_OPTION (callee_tree);
+      HOST_WIDE_INT callee_isa = callee_opts->x_rs6000_isa_flags;
+      HOST_WIDE_INT explicit_isa = callee_opts->x_rs6000_isa_flags_explicit;
+
+      /* If the caller has option attributes, then use them.
+        Otherwise, use the command line options.  */
+      if (caller_tree)
+       caller_isa = TREE_TARGET_OPTION (caller_tree)->x_rs6000_isa_flags;
+      else
+       caller_isa = rs6000_isa_flags;
 
-      /* Callee's options should a subset of the caller's, i.e. a vsx function
-        can inline an altivec function but a non-vsx function can't inline a
-        vsx function.  */
-      if ((caller_opts->x_rs6000_isa_flags & callee_opts->x_rs6000_isa_flags)
-         == callee_opts->x_rs6000_isa_flags)
+      /* The callee's options must be a subset of the caller's options, i.e.
+        a vsx function may inline an altivec function, but a non-vsx function
+        must not inline a vsx function.  However, for those options that the
+        callee has explicitly set, then we must enforce that the callee's
+        and caller's options match exactly; see PR70010.  */
+      if (((caller_isa & callee_isa) == callee_isa)
+         && (caller_isa & explicit_isa) == (callee_isa & explicit_isa))
        ret = true;
     }
 
Index: gcc/testsuite/gcc.target/powerpc/pr70010.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr70010.c  (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr70010.c  (working copy)
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -finline-functions" } */
+/* { dg-final { scan-assembler {\mbl vadd_no_vsx\M} } } */
+
+typedef int vec_t __attribute__((vector_size(16)));
+
+static vec_t
+__attribute__((__target__("no-vsx")))
+vadd_no_vsx (vec_t a, vec_t b)
+{
+  return a + b;
+}
+
+vec_t
+__attribute__((__target__("vsx")))
+call_vadd_no_vsx (vec_t x, vec_t y, vec_t z)
+{
+  return vadd_no_vsx (x, y) - z;
+}

Reply via email to