[PATCH][RFC] Prevent implicit FPU usage

Momchil Velikov velco@fadata.bg
Thu Jan 5 22:10:00 GMT 2006


Momchil Velikov wrote:
> Momchil Velikov wrote:
> 
>>  The following pathch prevents implicit usage of FP registers.
>   Here's the updated version of the patch, following comments received
> on the previous one.

The next update, after the next round of comments ...

2006-01-05  Momchil Velikov  <velco@fadata.bg>

	* common.opt (-fimplicit-fp): New option.

	* tree.h (DECL_USES_FP): New macro.
	(struct tree_function_decl): Add ``uses_fp_flag''.

	* print-tree.c (print_node): Print the value of ``uses_fp_flag''.

	* c-decl.c (grokdeclarator): Check for floating point usage.

	* c-parser.c (c_parser_cast_expression):  Likewise.
	(c_parser_postfix_expression): Likewise.

	* hard-reg-set.h (floating_point_regs): New variable.

	* regclass.c (floating_point_regs): Define it.
	(init_reg_sets_1): Clear ``floating_point_regs''.

	* global.c (prune_preferences): Conditionally exclude floating
	point registers.
	(find_reg): Likewise.

	* local-alloc.c (find_free_reg): Likewise.

	* reload1.c (order_regs_for_reload): Likewise.

	* tree-inline.c (expand_call_inline): Propagate the floating point
	usage flag from the inlined subroutine.

	* config/sh/sh.h (CONDITIONAL_REGISTER_USAGE): Initialize
	``floating_point_regs''.
	(OVERRIDE_OPTIONS): Warn if -fno-implicit-fp is used without
	-mhitachi.


Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 109236)
+++ gcc/tree.h	(working copy)
@@ -2699,6 +2699,11 @@
 #define DECL_NO_LIMIT_STACK(NODE) \
   (FUNCTION_DECL_CHECK (NODE)->function_decl.no_limit_stack)

+/* Used in FUNCTION_DECLs to indicate that the function uses
+   floating-point values.  */
+#define DECL_USES_FP(NODE) \
+  (FUNCTION_DECL_CHECK (NODE)->function_decl.uses_fp_flag)
+
 /* In a FUNCTION_DECL with a nonzero DECL_CONTEXT, indicates that a
    static chain is not needed.  */
 #define DECL_NO_STATIC_CHAIN(NODE) \
@@ -2762,6 +2767,7 @@
   unsigned no_instrument_function_entry_exit : 1;
   unsigned no_limit_stack : 1;
   ENUM_BITFIELD(built_in_class) built_in_class : 2;
+  unsigned uses_fp_flag : 1;

   struct function *f;
 };
Index: gcc/global.c
===================================================================
--- gcc/global.c	(revision 109236)
+++ gcc/global.c	(working copy)
@@ -38,6 +38,7 @@
 #include "toplev.h"
 #include "tree-pass.h"
 #include "timevar.h"
+#include "tree.h"

 /* This pass of the compiler performs global register allocation.
    It assigns hard register numbers to all the pseudo registers
@@ -969,6 +970,9 @@
       else
 	IOR_HARD_REG_SET (temp,	call_used_reg_set);

+      if (! flag_implicit_fp && ! DECL_USES_FP (cfun->decl))
+	IOR_HARD_REG_SET (temp, floating_point_regs);
+
       IOR_COMPL_HARD_REG_SET
 	(temp,
 	 reg_class_contents[(int) reg_preferred_class (allocno[num].reg)]);
@@ -1050,6 +1054,9 @@
   else
     COPY_HARD_REG_SET (used1, call_used_reg_set);

+  if (! flag_implicit_fp && ! DECL_USES_FP (cfun->decl))
+    IOR_HARD_REG_SET (used1, floating_point_regs);
+
   /* Some registers should not be allocated in global-alloc.  */
   IOR_HARD_REG_SET (used1, no_global_alloc_regs);
   if (losers)
Index: gcc/hard-reg-set.h
===================================================================
--- gcc/hard-reg-set.h	(revision 109236)
+++ gcc/hard-reg-set.h	(working copy)
@@ -446,6 +446,12 @@

 extern HARD_REG_SET regs_invalidated_by_call;

+/* Contains 1 for registers, which should be considered fixed if no
+   implicit floating point operations are to be generated and the
+   current function does not contain floating point operations.  */
+
+extern HARD_REG_SET floating_point_regs;
+
 #ifdef REG_ALLOC_ORDER
 /* Table of register numbers in the order in which to try to use them.  */

Index: gcc/c-decl.c
===================================================================
--- gcc/c-decl.c	(revision 109236)
+++ gcc/c-decl.c	(working copy)
@@ -4647,6 +4647,23 @@
 	   needed, and let dwarf2 know that the function is inlinable.  */
 	else if (flag_inline_trees == 2 && initialized)
 	  DECL_INLINE (decl) = 1;
+
+	/* Check for floating point usage.  */
+	if (FLOAT_TYPE_P (TREE_TYPE (decl)))
+	  DECL_USES_FP (decl) = 1;
+	else
+	  {
+	    tree params = TYPE_ARG_TYPES (TREE_TYPE (decl));
+	    while (params)
+	      {
+		if (FLOAT_TYPE_P (TREE_VALUE (params)))
+		  {
+		    DECL_USES_FP (decl) = 1;
+		    break;
+		  }
+		params = TREE_CHAIN (params);
+	      }
+	  }
       }
     else
       {
@@ -4713,6 +4730,10 @@
 		 at runtime.  Don't bother to allow this to compile.  */
 	      error ("thread-local storage not supported for this target");
 	  }
+
+	/* Check for floating point usage.  */
+	if (current_function_decl && FLOAT_TYPE_P (TREE_TYPE (decl)))
+	  DECL_USES_FP (current_function_decl) = 1;
       }

     /* Record `register' declaration for warnings on &
Index: gcc/local-alloc.c
===================================================================
--- gcc/local-alloc.c	(revision 109236)
+++ gcc/local-alloc.c	(working copy)
@@ -80,6 +80,7 @@
 #include "ggc.h"
 #include "timevar.h"
 #include "tree-pass.h"
+#include "tree.h"
 

 /* Next quantity number available for allocation.  */

@@ -2236,6 +2237,9 @@
   else
     COPY_HARD_REG_SET (used, call_used_reg_set);

+  if (! flag_implicit_fp && ! DECL_USES_FP (cfun->decl))
+    IOR_HARD_REG_SET (used, floating_point_regs);
+
   if (accept_call_clobbered)
     IOR_HARD_REG_SET (used, losing_caller_save_reg_set);

Index: gcc/print-tree.c
===================================================================
--- gcc/print-tree.c	(revision 109236)
+++ gcc/print-tree.c	(working copy)
@@ -349,6 +349,8 @@
 	fputs (" built-in", file);
       if (TREE_CODE (node) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (node))
 	fputs (" no-static-chain", file);
+      if (TREE_CODE (node) == FUNCTION_DECL && DECL_USES_FP (node))
+	fputs (" uses-fp", file);

       if (TREE_CODE (node) == FIELD_DECL && DECL_PACKED (node))
 	fputs (" packed", file);
Index: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 109236)
+++ gcc/common.opt	(working copy)
@@ -483,6 +483,10 @@
 Common Report Var(flag_inhibit_size_directive)
 Do not generate .size directives

+fimplicit-fp
+Common Report Var(flag_implicit_fp) Init(1)
+Implicitly use the floating-point registers.
+
 ; Nonzero means that functions declared `inline' will be treated
 ; as `static'.  Prevents generation of zillions of copies of unused
 ; static inline functions; instead, `inlines' are written out
Index: gcc/regclass.c
===================================================================
--- gcc/regclass.c	(revision 109236)
+++ gcc/regclass.c	(working copy)
@@ -143,6 +143,12 @@

 HARD_REG_SET regs_invalidated_by_call;

+/* Contains 1 for registers, which should be considered fixed if no
+   implicit floating point operations are to be generated and the
+   current function does not contain floating point operations.  */
+
+HARD_REG_SET floating_point_regs;
+
 /* Table of register numbers in the order in which to try to use them.  */
 #ifdef REG_ALLOC_ORDER
 int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
@@ -422,6 +428,7 @@
   CLEAR_HARD_REG_SET (call_used_reg_set);
   CLEAR_HARD_REG_SET (call_fixed_reg_set);
   CLEAR_HARD_REG_SET (regs_invalidated_by_call);
+  CLEAR_HARD_REG_SET (floating_point_regs);

   memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);

Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c	(revision 109236)
+++ gcc/tree-inline.c	(working copy)
@@ -2168,6 +2168,9 @@
 					       cfun->unexpanded_var_list);
     }

+  /* Propagate floating point usage flag.  */
+  DECL_USES_FP (cfun->decl) = DECL_USES_FP (id->callee_cfun->decl);
+
   /* Clean up.  */
   splay_tree_delete (id->decl_map);
   id->decl_map = st;
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 109236)
+++ gcc/c-parser.c	(working copy)
@@ -4510,6 +4510,8 @@
       expr = default_function_array_conversion (expr);
       ret.value = c_cast_expr (type_name, expr.value);
       ret.original_code = ERROR_MARK;
+      if (current_function_decl && FLOAT_TYPE_P (TREE_TYPE (ret.value)))
+	DECL_USES_FP (current_function_decl) = 1;
       return ret;
     }
   else
@@ -4814,6 +4816,8 @@
       expr.value = c_parser_peek_token (parser)->value;
       expr.original_code = ERROR_MARK;
       c_parser_consume_token (parser);
+      if (current_function_decl && FLOAT_TYPE_P (TREE_TYPE (expr.value)))
+	DECL_USES_FP (current_function_decl) = 1;
       break;
     case CPP_STRING:
     case CPP_WSTRING:
@@ -4844,6 +4848,8 @@
 					 (c_parser_peek_token (parser)->type
 					  == CPP_OPEN_PAREN), loc);
 	expr.original_code = ERROR_MARK;
+	if (current_function_decl && FLOAT_TYPE_P (TREE_TYPE (expr.value)))
+	  DECL_USES_FP (current_function_decl) = 1;
       }
       break;
     case CPP_OPEN_PAREN:
Index: gcc/config/sh/sh.h
===================================================================
--- gcc/config/sh/sh.h	(revision 109236)
+++ gcc/config/sh/sh.h	(working copy)
@@ -128,9 +128,14 @@
       call_really_used_regs[MACH_REG] = 0;				\
       call_really_used_regs[MACL_REG] = 0;				\
     }									\
+  SET_HARD_REG_BIT (floating_point_regs, FPUL_REG);			\
   for (regno = FIRST_FP_REG + (TARGET_LITTLE_ENDIAN != 0);		\
        regno <= LAST_FP_REG; regno += 2)				\
-    SET_HARD_REG_BIT (reg_class_contents[DF_HI_REGS], regno);		\
+    {									\
+      SET_HARD_REG_BIT (floating_point_regs, regno);			\
+      SET_HARD_REG_BIT (floating_point_regs, regno + 1);		\
+      SET_HARD_REG_BIT (reg_class_contents[DF_HI_REGS], regno);		\
+    }									\
   if (TARGET_SHMEDIA)							\
     {									\
       for (regno = FIRST_TARGET_REG; regno <= LAST_TARGET_REG; regno ++)\
@@ -701,6 +706,11 @@
       if (align_functions < min_align)					\
 	align_functions = min_align;					\
     }									\
+  /* Variable argument functions may access floating point registers	\
+     unless we are using the Renesas ABI.  */				\
+  if (!TARGET_HITACHI && !flag_implicit_fp)				\
+    warning (0, "selected ABI may cause unexpected use of floating point" \
+	     " (use -mhitachi)");                                       \
 } while (0)
 

 /* Target machine storage layout.  */
Index: gcc/reload1.c
===================================================================
--- gcc/reload1.c	(revision 109236)
+++ gcc/reload1.c	(working copy)
@@ -1617,6 +1617,9 @@

   COPY_HARD_REG_SET (bad_spill_regs, fixed_reg_set);

+  if (! flag_implicit_fp && ! DECL_USES_FP (cfun->decl))
+    IOR_HARD_REG_SET (bad_spill_regs, floating_point_regs);
+
   memset (spill_cost, 0, sizeof spill_cost);
   memset (spill_add_cost, 0, sizeof spill_add_cost);





More information about the Gcc-patches mailing list