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. */
#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
--- /dev/null
+/* 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 .*" } } */
--- /dev/null
+/* 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);
+}
+
--- /dev/null
+/* 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 .*" } } */
--- /dev/null
+/* 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);
+}