[committed] Nios2: Add TARGET_CAN_INLINE_P hook

Message ID e265a14d-b9e4-f815-1049-cbfcf9dd2b92@codesourcery.com
State Committed
Headers
Series [committed] Nios2: Add TARGET_CAN_INLINE_P hook |

Commit Message

Sandra Loosemore Nov. 10, 2021, 2:14 a.m. UTC
  I've checked in the attached patch, which fixes 30+ FAILs across the gcc 
and g++ testsuites on nios2-elf target.  The only target options we have 
to worry about in this backend are the nios2 custom instructions, and 
the hashing in the default hook function seemed to be confused by all 
the extra state being stored in the options structure.  I've made it 
properly check that the custom instructions enabled in the callee must 
be a subset of those in the caller, with the same encoding in both cases.

-Sandra
  

Patch

commit df69d7ae8f9903df8a553e236c54df61633d8af2
Author: Sandra Loosemore <sandra@codesourcery.com>
Date:   Mon Nov 8 19:10:58 2021 -0800

    Nios2:  Add TARGET_CAN_INLINE_P hook.
    
    2021-11-09  Sandra Loosemore  <sandra@codesourcery.com>
    
    	gcc/
    	* config/nios2/nios2.c (nios2_can_inline_p): New.
    	(TARGET_CAN_INLINE_P): Define.
    
    	gcc/testsuite/
    	* gcc.target/nios2/custom-fp-inline-1.c: New.
    	* gcc.target/nios2/custom-fp-inline-2.c: New.
    	* gcc.target/nios2/custom-fp-inline-3.c: New.
    	* gcc.target/nios2/custom-fp-inline-4.c: New.

diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 7a613e4..f77f7e6 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -4162,6 +4162,40 @@  nios2_option_restore (struct gcc_options *opts ATTRIBUTE_UNUSED,
 	  sizeof (custom_code_index));
 }
 
+static bool
+nios2_can_inline_p (tree caller, tree callee)
+{
+  tree callee_opts = DECL_FUNCTION_SPECIFIC_TARGET (callee);
+  tree caller_opts = DECL_FUNCTION_SPECIFIC_TARGET (caller);
+  struct cl_target_option *callee_ptr, *caller_ptr;
+  unsigned int i;
+
+  if (! callee_opts)
+    callee_opts = target_option_default_node;
+  if (! caller_opts)
+    caller_opts = target_option_default_node;
+
+  /* If both caller and callee have attributes, assume that if the
+     pointer is different, the two functions have different target
+     options since build_target_option_node uses a hash table for the
+     options.  */
+  if (callee_opts == caller_opts)
+    return true;
+
+  /* The only target options we recognize via function attributes are
+     those related to custom instructions.  If we failed the above test,
+     check that any custom instructions enabled in the callee are also
+     enabled with the same value in the caller.  */
+  callee_ptr = TREE_TARGET_OPTION (callee_opts);
+  caller_ptr = TREE_TARGET_OPTION (caller_opts);
+  for (i = 0; i < ARRAY_SIZE (nios2_fpu_insn); i++)
+    if (callee_ptr->saved_fpu_custom_code[i] != -1
+	&& (callee_ptr->saved_fpu_custom_code[i]
+	    != caller_ptr->saved_fpu_custom_code[i]))
+      return false;
+  return true;
+}
+
 /* Inner function to process the attribute((target(...))), take an argument and
    set the current options from the argument.  If we have a list, recursively
    go over the list.  */
@@ -5554,6 +5588,9 @@  nios2_adjust_reg_alloc_order (void)
 #undef TARGET_OPTION_RESTORE
 #define TARGET_OPTION_RESTORE nios2_option_restore
 
+#undef TARGET_CAN_INLINE_P
+#define TARGET_CAN_INLINE_P nios2_can_inline_p
+
 #undef TARGET_SET_CURRENT_FUNCTION
 #define TARGET_SET_CURRENT_FUNCTION nios2_set_current_function
 
diff --git a/gcc/testsuite/gcc.target/nios2/custom-fp-inline-1.c b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-1.c
new file mode 100644
index 0000000..43715e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-1.c
@@ -0,0 +1,33 @@ 
+/* Test that you can inline a function with custom insn attributes into
+   one with the same attributes.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -ffinite-math-only" } */
+
+/* -O1 in the options is significant.  Without it FP operations may not be
+   optimized to custom instructions.  */
+
+#include <math.h>
+
+static inline
+__attribute__ ((always_inline, target ("custom-fmaxs=246,custom-fmins=247")))
+void
+custom_fp1 (float operand_a, float operand_b, float *result)
+
+{
+  result[0] = fmaxf (operand_a, operand_b);
+  result[1] = fminf (operand_a, operand_b);
+}
+
+extern void
+custom_fp (float operand_a, float operand_b, float *result)
+  __attribute__ ((target ("custom-fmaxs=246,custom-fmins=247")));
+
+void
+custom_fp (float operand_a, float operand_b, float *result)
+{
+  custom_fp1 (operand_a, operand_b, result);
+}
+
+/* { dg-final { scan-assembler "custom\\t246, .* # fmaxs .*" } } */
+/* { dg-final { scan-assembler "custom\\t247, .* # fmins .*" } } */
diff --git a/gcc/testsuite/gcc.target/nios2/custom-fp-inline-2.c b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-2.c
new file mode 100644
index 0000000..3e35241
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-2.c
@@ -0,0 +1,29 @@ 
+/* Test that you cannot inline a function with custom insn attributes into
+   one without attributes.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -ffinite-math-only" } */
+
+/* -O1 in the options is significant.  Without it FP operations may not be
+   optimized to custom instructions.  */
+
+#include <math.h>
+
+static inline
+__attribute__ ((always_inline, target ("custom-fmaxs=246,custom-fmins=247")))
+void
+custom_fp1 (float operand_a, float operand_b, float *result)  /* { dg-error "target specific option mismatch" } */
+{
+  result[0] = fmaxf (operand_a, operand_b);
+  result[1] = fminf (operand_a, operand_b);
+}
+
+extern void
+custom_fp (float operand_a, float operand_b, float *result);
+
+void
+custom_fp (float operand_a, float operand_b, float *result)
+{
+  custom_fp1 (operand_a, operand_b, result);
+}
+
diff --git a/gcc/testsuite/gcc.target/nios2/custom-fp-inline-3.c b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-3.c
new file mode 100644
index 0000000..86b1064
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-3.c
@@ -0,0 +1,33 @@ 
+/* Test that you can inline a function without custom insn attributes into
+   one that does have custom insn attributes.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -ffinite-math-only" } */
+
+/* -O1 in the options is significant.  Without it FP operations may not be
+   optimized to custom instructions.  */
+
+#include <math.h>
+
+static inline 
+__attribute__ ((always_inline))
+void
+custom_fp1 (float operand_a, float operand_b, float *result)
+
+{
+  result[0] = fmaxf (operand_a, operand_b);
+  result[1] = fminf (operand_a, operand_b);
+}
+
+extern void
+custom_fp (float operand_a, float operand_b, float *result)
+  __attribute__ ((target ("custom-fmaxs=246,custom-fmins=247")));
+
+void
+custom_fp (float operand_a, float operand_b, float *result)
+{
+  custom_fp1 (operand_a, operand_b, result);
+}
+
+/* { dg-final { scan-assembler "custom\\t246, .* # fmaxs .*" } } */
+/* { dg-final { scan-assembler "custom\\t247, .* # fmins .*" } } */
diff --git a/gcc/testsuite/gcc.target/nios2/custom-fp-inline-4.c b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-4.c
new file mode 100644
index 0000000..5e2c1bc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/custom-fp-inline-4.c
@@ -0,0 +1,29 @@ 
+/* Test that you cannot inline a function with custom insn attributes into
+   one with incompatible attributes.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O1 -ffinite-math-only" } */
+
+/* -O1 in the options is significant.  Without it FP operations may not be
+   optimized to custom instructions.  */
+
+#include <math.h>
+
+static inline
+__attribute__ ((always_inline, target ("custom-fmaxs=246,custom-fmins=247")))
+void
+custom_fp1 (float operand_a, float operand_b, float *result)  /* { dg-error "target specific option mismatch" } */
+{
+  result[0] = fmaxf (operand_a, operand_b);
+  result[1] = fminf (operand_a, operand_b);
+}
+
+extern void
+custom_fp (float operand_a, float operand_b, float *result)
+  __attribute__ ((target ("custom-fmaxs=200,custom-fmins=201")));
+
+void
+custom_fp (float operand_a, float operand_b, float *result)
+{
+  custom_fp1 (operand_a, operand_b, result);
+}