[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