From 31a9483b87d008eebe6d47e3ef640e9080ccee5a Mon Sep 17 00:00:00 2001 From: Michael Beck Date: Sun, 2 Jul 2006 16:24:26 +0000 Subject: [PATCH] Renamed attribute names to more understandable names. Add floating point model to ir_graph. Make fp optimization dependent on the fp model. [r7983] --- ir/ir/irgraph.c | 30 ++++++++++------- ir/ir/irgraph.h | 13 ++++++-- ir/ir/irgraph_t.h | 41 +++++++++++++----------- ir/ir/iropt.c | 82 +++++++++++++++++++++++++++++++++++------------ ir/ir/iropt.h | 47 +++++++++++++++++++++++++++ 5 files changed, 161 insertions(+), 52 deletions(-) diff --git a/ir/ir/irgraph.c b/ir/ir/irgraph.c index 71088acc2..0b033a1c5 100644 --- a/ir/ir/irgraph.c +++ b/ir/ir/irgraph.c @@ -17,8 +17,9 @@ #ifdef HAVE_STRING_H # include #endif - -#include +#ifdef HAVE_STDDEF_H +# include +#endif #include "xmalloc.h" #include "ircons.h" @@ -201,6 +202,7 @@ new_r_ir_graph (entity *ent, int n_loc) res->execfreq_state = exec_freq_none; res->class_cast_state = ir_class_casts_transitive; res->extblk_state = ir_extblk_info_none; + res->fp_model = fp_model_precise; /*-- Type information for the procedure of the graph --*/ res->ent = ent; @@ -267,7 +269,7 @@ new_ir_graph(entity *ent, int n_loc) return res; } -/* Make a rudimentary ir graph for the constant code. +/* Make a rudimentary IR graph for the constant code. Must look like a correct irg, spare everything else. */ ir_graph *new_const_code_irg(void) { ir_graph *res; @@ -299,6 +301,7 @@ ir_graph *new_const_code_irg(void) { res->phase_state = phase_building; res->irg_pinned_state = op_pin_state_pinned; res->extblk_state = ir_extblk_info_none; + res->fp_model = fp_model_precise; res->value_table = new_identities (); /* value table for global value numbering for optimizing use in @@ -818,6 +821,15 @@ void _inc_irg_block_visited(irg); } +/* Return the floating point model of this graph. */ +unsigned (get_irg_fp_model)(const ir_graph *irg) { + return _get_irg_fp_model(irg); +} + +/* Sets the floating point model for this graph. */ +void set_irg_fp_model(ir_graph *irg, unsigned model) { + irg->fp_model = model; +} /** * walker Start->End: places Proj nodes into the same block @@ -826,8 +838,7 @@ void * @param n the node * @param env ignored */ -static void normalize_proj_walker(ir_node *n, void *env) -{ +static void normalize_proj_walker(ir_node *n, void *env){ if (is_Proj(n)) { ir_node *pred = get_Proj_pred(n); ir_node *block = get_nodes_block(pred); @@ -837,15 +848,13 @@ static void normalize_proj_walker(ir_node *n, void *env) } /* move Proj nodes into the same block as its predecessors */ -void normalize_proj_nodes(ir_graph *irg) -{ +void normalize_proj_nodes(ir_graph *irg) { irg_walk_graph(irg, NULL, normalize_proj_walker, NULL); set_irg_outs_inconsistent(irg); } /* set a description for local value n */ -void set_irg_loc_description(ir_graph *irg, int n, void *description) -{ +void set_irg_loc_description(ir_graph *irg, int n, void *description) { assert(0 <= n && n < irg->n_loc); if (! irg->loc_descriptions) @@ -855,8 +864,7 @@ void set_irg_loc_description(ir_graph *irg, int n, void *description) } /* get the description for local value n */ -void *get_irg_loc_description(ir_graph *irg, int n) -{ +void *get_irg_loc_description(ir_graph *irg, int n) { assert(0 <= n && n < irg->n_loc); return irg->loc_descriptions ? irg->loc_descriptions[n] : NULL; } diff --git a/ir/ir/irgraph.h b/ir/ir/irgraph.h index 145fb599b..897fac804 100644 --- a/ir/ir/irgraph.h +++ b/ir/ir/irgraph.h @@ -24,6 +24,7 @@ #include "firm_types.h" #include "irop.h" +#include "iropt.h" #include "irextbb.h" #include "type.h" @@ -283,7 +284,7 @@ long get_irg_graph_nr(ir_graph *irg); * The graph is in phase_building during construction of the irgraph. * The construction is finished by a call to finalize_cons(). * - * Finalize_cons() sets the state to phase_high. All stadard Firm nodes are + * Finalize_cons() sets the state to phase_high. All standard Firm nodes are * allowed. * * To get the irgraph into phase_low all Sel nodes must be removed and @@ -292,13 +293,13 @@ long get_irg_graph_nr(ir_graph *irg); * memory allocated by Alloc must be explicit. @@@ More conditions? * * phase_backend is set if architecture specific machine nodes are inserted - * (and probally most standard Firm are removed). + * (and probably most standard Firm are removed). */ typedef enum { phase_building, phase_high, phase_low, - phase_backend + phase_backend } irg_phase_state; /** returns the phase_state of an IR graph. */ @@ -494,6 +495,12 @@ unsigned get_irg_estimated_node_cnt(const ir_graph *irg); /** Returns the last irn index for this graph. */ unsigned get_irg_last_idx(const ir_graph *irg); +/** Returns the floating point model of this graph. */ +unsigned get_irg_fp_model(const ir_graph *irg); + +/** Sets a floating point model for this graph. */ +void set_irg_fp_model(ir_graph *irg, unsigned model); + /** * Access custom graph data. * The data must have been registered with diff --git a/ir/ir/irgraph_t.h b/ir/ir/irgraph_t.h index 9b2dd1aa3..09966fd3e 100644 --- a/ir/ir/irgraph_t.h +++ b/ir/ir/irgraph_t.h @@ -3,7 +3,7 @@ * File name: ir/ir/irgraph.c * Purpose: Entry point to the representation of procedure code -- internal header. * Author: Martin Trapp, Christian Schaefer - * Modified by: Goetz Lindenmaier + * Modified by: Goetz Lindenmaier, Michael Beck * Created: * CVS-ID: $Id$ * Copyright: (c) 1998-2003 Universität Karlsruhe @@ -13,12 +13,8 @@ /** * @file irgraph_t.h * - * ir graph construction. - * - * @author Martin Trapp, Christian Schaefer + * IR graph construction. */ - - #ifndef _IRGRAPH_T_H_ #define _IRGRAPH_T_H_ @@ -41,14 +37,15 @@ #include "pset.h" #include "set.h" +/** Prefix that is added to every frame type. */ #define FRAME_TP_SUFFIX "frame_tp" /** * Edge info to put into an irg. */ typedef struct _irg_edge_info_t { - set *edges; - unsigned activated : 1; + set *edges; /**< a set containing all edges of a graph. */ + unsigned activated : 1; /**< set if edges are activated for the graph. */ } irg_edge_info_t; /** @@ -97,17 +94,18 @@ struct ir_graph { unsigned additional_properties; /**< additional graph properties. */ /* -- Fields indicating different states of irgraph -- */ - irg_phase_state phase_state; /**< compiler phase */ - op_pin_state irg_pinned_state; /**< Flag for status of nodes */ + irg_phase_state phase_state; /**< Compiler phase. */ + op_pin_state irg_pinned_state; /**< Flag for status of nodes. */ irg_outs_state outs_state; /**< Out edges. */ - irg_dom_state dom_state; /**< Dominator state information */ - irg_dom_state pdom_state; /**< Post Dominator state information */ - ir_typeinfo_state typeinfo_state; /**< Validity of type information */ - irg_callee_info_state callee_info_state; /**< Validity of callee information */ - irg_loopinfo_state loopinfo_state; /**< state of loop information */ - exec_freq_state execfreq_state; /**< state of execution frequency information */ - ir_class_cast_state class_cast_state; /**< kind of cast operations in code. */ - irg_extblk_info_state extblk_state; /**< state of extended basic block info */ + irg_dom_state dom_state; /**< Dominator state information. */ + irg_dom_state pdom_state; /**< Post Dominator state information. */ + ir_typeinfo_state typeinfo_state; /**< Validity of type information. */ + irg_callee_info_state callee_info_state; /**< Validity of callee information. */ + irg_loopinfo_state loopinfo_state; /**< State of loop information. */ + exec_freq_state execfreq_state; /**< State of execution frequency information. */ + ir_class_cast_state class_cast_state; /**< Kind of cast operations in code. */ + irg_extblk_info_state extblk_state; /**< State of extended basic block info. */ + unsigned fp_model; /**< floating point model of the graph. */ /* -- Fields for construction -- */ #if USE_EXPLICIT_PHI_IN_STACK @@ -547,6 +545,12 @@ _get_irg_estimated_node_cnt(const ir_graph *irg) { return irg->estimated_node_count; } +/* Return the floating point model of this graph. */ +static INLINE unsigned +_get_irg_fp_model(const ir_graph *irg) { + return irg->fp_model; +} + /** * Allocates a new idx in the irg for the node and adds the irn to the idx -> irn map. * @param irg The graph. @@ -654,5 +658,6 @@ get_idx_irn(ir_graph *irg, unsigned idx) { #define inc_irg_block_visited(irg) _inc_irg_block_visited(irg) #define dec_irg_block_visited(irg) _dec_irg_block_visited(irg) #define get_irg_estimated_node_cnt(irg) _get_irg_estimated_node_cnt(irg) +#define get_irg_fp_model(irg) _get_irg_fp_model(irg) # endif /* _IRGRAPH_T_H_ */ diff --git a/ir/ir/iropt.c b/ir/ir/iropt.c index d29e52139..0cfee7b80 100644 --- a/ir/ir/iropt.c +++ b/ir/ir/iropt.c @@ -897,6 +897,11 @@ static ir_node *equivalent_node_Add(ir_node *n) { ir_node *oldn = n; ir_node *left, *right; + ir_mode *mode = get_irn_mode(n); + + /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */ + if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)) + return n; n = equivalent_node_neutral_zero(n); if (n != oldn) @@ -910,7 +915,7 @@ static ir_node *equivalent_node_Add(ir_node *n) /* (a - x) + x */ n = get_Sub_left(left); - if (get_irn_mode(oldn) == get_irn_mode(n)) { + if (mode == get_irn_mode(n)) { DBG_OPT_ALGSIM1(oldn, left, right, n, FS_OPT_ADD_SUB); return n; } @@ -921,7 +926,7 @@ static ir_node *equivalent_node_Add(ir_node *n) /* x + (a - x) */ n = get_Sub_left(right); - if (get_irn_mode(oldn) == get_irn_mode(n)) { + if (mode == get_irn_mode(n)) { DBG_OPT_ALGSIM1(oldn, left, right, n, FS_OPT_ADD_SUB); return n; } @@ -967,40 +972,43 @@ static ir_node *equivalent_node_left_zero(ir_node *n) static ir_node *equivalent_node_Sub(ir_node *n) { ir_node *oldn = n; + ir_node *a, *b; + ir_mode *mode = get_irn_mode(n); - ir_node *a = get_Sub_left(n); - ir_node *b = get_Sub_right(n); + /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */ + if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)) + return n; + + a = get_Sub_left(n); + b = get_Sub_right(n); /* Beware: modes might be different */ if (classify_tarval(value_of(b)) == TV_CLASSIFY_NULL) { - if (get_irn_mode(n) == get_irn_mode(a)) { + if (mode == get_irn_mode(a)) { n = a; DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_NEUTRAL_0); } } else if (get_irn_op(a) == op_Add) { - ir_mode *mode = get_irn_mode(n); - if (mode_wrap_around(mode)) { ir_node *left = get_Add_left(a); ir_node *right = get_Add_right(a); if (left == b) { - if (get_irn_mode(n) == get_irn_mode(right)) { + if (mode == get_irn_mode(right)) { n = right; DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_ADD_SUB); } } else if (right == b) { - if (get_irn_mode(n) == get_irn_mode(left)) { + if (mode == get_irn_mode(left)) { n = left; DBG_OPT_ALGSIM1(oldn, a, b, n, FS_OPT_ADD_SUB); } } } } - return n; } @@ -1039,7 +1047,6 @@ static ir_node *equivalent_node_idempotent_unop(ir_node *n) static ir_node *equivalent_node_Mul(ir_node *n) { ir_node *oldn = n; - ir_node *a = get_Mul_left(n); ir_node *b = get_Mul_right(n); @@ -1074,6 +1081,25 @@ static ir_node *equivalent_node_Div(ir_node *n) return n; } +/** + * Optimize a / 1.0 = a. + */ +static ir_node *equivalent_node_Quot(ir_node *n) { + ir_node *a = get_Div_left(n); + ir_node *b = get_Div_right(n); + + /* Div is not commutative. */ + if (classify_tarval(value_of(b)) == TV_CLASSIFY_ONE) { /* Quot(x, 1) == x */ + /* Turn Quot into a tuple (mem, bad, a) */ + ir_node *mem = get_Quot_mem(n); + turn_into_tuple(n, pn_Quot_max); + set_Tuple_pred(n, pn_Quot_M, mem); + set_Tuple_pred(n, pn_Quot_X_except, new_Bad()); /* no exception */ + set_Tuple_pred(n, pn_Quot_res, a); + } + return n; +} + /** * Optimize a / 1 = a. */ @@ -1157,6 +1183,9 @@ static ir_node *equivalent_node_Conv(ir_node *n) ir_mode *a_mode = get_irn_mode(a); if (n_mode == a_mode) { /* No Conv necessary */ + /* leave strict floating point Conv's */ + if (get_Conv_strict(n)) + return n; n = a; DBG_OPT_ALGSIM0(oldn, n, FS_OPT_CONV); } else if (get_irn_op(a) == op_Conv) { /* Conv(Conv(b)) */ @@ -1627,6 +1656,7 @@ static ir_op_ops *firm_set_default_equivalent_node(opcode code, ir_op_ops *ops) CASE(Minus); CASE(Mul); CASE(Div); + CASE(Quot); CASE(DivMod); CASE(And); CASE(Conv); @@ -1902,6 +1932,11 @@ static ir_node *transform_node_Add(ir_node *n) HANDLE_BINOP_PHI(tarval_add, a,b,c); mode = get_irn_mode(n); + + /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */ + if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)) + return n; + if (mode_is_num(mode)) { if (a == b) { ir_node *block = get_irn_n(n, -1); @@ -2024,6 +2059,11 @@ static ir_node *transform_node_Sub(ir_node *n) HANDLE_BINOP_PHI(tarval_sub, a,b,c); mode = get_irn_mode(n); + + /* for FP these optimizations are only allowed if fp_strict_algebraic is disabled */ + if (mode_is_float(mode) && (get_irg_fp_model(current_ir_graph) & fp_strict_algebraic)) + return n; + if (mode_is_num(mode) && (classify_Const(a) == CNST_NULL)) { n = new_rd_Minus( get_irn_dbg_info(n), @@ -3461,8 +3501,7 @@ static int node_cmp_attr_Const(ir_node *a, ir_node *b) } /** Compares the attributes of two Proj nodes. */ -static int node_cmp_attr_Proj(ir_node *a, ir_node *b) -{ +static int node_cmp_attr_Proj(ir_node *a, ir_node *b) { return get_irn_proj_attr (a) != get_irn_proj_attr (b); } @@ -3495,8 +3534,7 @@ static int node_cmp_attr_SymConst(ir_node *a, ir_node *b) } /** Compares the attributes of two Call nodes. */ -static int node_cmp_attr_Call(ir_node *a, ir_node *b) -{ +static int node_cmp_attr_Call(ir_node *a, ir_node *b) { return (get_irn_call_attr(a) != get_irn_call_attr(b)); } @@ -3511,14 +3549,17 @@ static int node_cmp_attr_Sel(ir_node *a, ir_node *b) } /** Compares the attributes of two Phi nodes. */ -static int node_cmp_attr_Phi(ir_node *a, ir_node *b) -{ +static int node_cmp_attr_Phi(ir_node *a, ir_node *b) { return get_irn_phi_attr (a) != get_irn_phi_attr (b); } +/** Compares the attributes of two Conv nodes. */ +static int node_cmp_attr_Conv(ir_node *a, ir_node *b) { + return get_Conv_strict(a) != get_Conv_strict(b); +} + /** Compares the attributes of two Cast nodes. */ -static int node_cmp_attr_Cast(ir_node *a, ir_node *b) -{ +static int node_cmp_attr_Cast(ir_node *a, ir_node *b) { return get_Cast_type(a) != get_Cast_type(b); } @@ -3573,6 +3614,7 @@ static ir_op_ops *firm_set_default_node_cmp_attr(opcode code, ir_op_ops *ops) CASE(Call); CASE(Sel); CASE(Phi); + CASE(Conv); CASE(Cast); CASE(Load); CASE(Store); @@ -3642,7 +3684,7 @@ unsigned ir_node_hash(ir_node *node) h = 9*h + HASH_PTR(get_irn_mode(node)); } else if (node->op == op_SymConst) { /* special value for const, as they only differ in their symbol. */ - h = HASH_PTR(node->attr.i.sym.type_p); + h = HASH_PTR(node->attr.symc.sym.type_p); h = 9*h + HASH_PTR(get_irn_mode(node)); } else { diff --git a/ir/ir/iropt.h b/ir/ir/iropt.h index 98a1d72bc..0a5098a2a 100644 --- a/ir/ir/iropt.h +++ b/ir/ir/iropt.h @@ -22,6 +22,53 @@ #include "firm_types.h" +/** + * The Floating point model. + * + * Several basic properties are defined: + * - fp_explicit_rounding + * - fp_strict_algebraic + * - fp_contradictions + * - fp_strict_eval_order + * - fp_exceptions + * - fp_environment_access + * + * From those basic properties three general models are defined, + * compatible to the VC8 compiler: + * - fp_model_precise: + * Default mode. Associative and distributive law forbidden unless a transformation + * is guaranteed to produce the same result. + * No FPU environment access. No FP exception semantics. + * - fp_model_strict: + * Slowest mode. Additionally to fp_model_precise allows correct handling of + * FP exceptions and FPU environment access. + * - fp_model_fast: + * Fastest mode. Associative and distributive law allowed at the expense + * of floating point accuracy and correctness. Explicite rounding is disabled. + */ +typedef enum _fp_model_t { + fp_explicit_rounding = 1, /**< Explicite rounding at assignments, typecasts, return + and function calls. Conv nodes may NOT be removed, even + if they look useless. */ + fp_strict_algebraic = 2, /**< Strict adherence to non-associative and non-distributive + algebra unless the same result is guaranteed. */ + fp_contradictions = 4, /**< FP contradictions are enabled. Only for backend. */ + fp_strict_eval_order = 8, /**< FP instructions must be strict evaluated in given order. */ + fp_exceptions = 16, /**< FP exceptions are supported. No reordering that changes + the exception flow are allowed. Backends must generate + synchronized exception code. */ + fp_environment_access = 32, /**< FPU environment can be accessed. Even Constant folding + cannot be done. */ + + /** Precise floating point model. Default. */ + fp_model_precise = fp_explicit_rounding|fp_strict_algebraic|fp_contradictions, + /** Strict floating point model. */ + fp_model_strict = fp_explicit_rounding|fp_strict_algebraic|fp_strict_eval_order| + fp_exceptions|fp_environment_access, + /** Fast floating point model. */ + fp_model_fast = fp_contradictions, +} fp_model_t; + /** If the expression referenced can be evaluated statically * computed_value returns a tarval representing the result. * Else returns tarval_bad. */ -- 2.20.1