Renamed attribute names to more understandable names.
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sun, 2 Jul 2006 16:24:26 +0000 (16:24 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Sun, 2 Jul 2006 16:24:26 +0000 (16:24 +0000)
Add floating point model to ir_graph.
Make fp optimization dependent on the fp model.

[r7983]

ir/ir/irgraph.c
ir/ir/irgraph.h
ir/ir/irgraph_t.h
ir/ir/iropt.c
ir/ir/iropt.h

index 71088ac..0b033a1 100644 (file)
@@ -17,8 +17,9 @@
 #ifdef HAVE_STRING_H
 # include <string.h>
 #endif
-
-#include <stddef.h>
+#ifdef HAVE_STDDEF_H
+# include <stddef.h>
+#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;
 }
index 145fb59..897fac8 100644 (file)
@@ -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
index 9b2dd1a..09966fd 100644 (file)
@@ -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
 /**
  * @file irgraph_t.h
  *
- * ir graph construction.
- *
- * @author Martin Trapp, Christian Schaefer
+ * IR graph construction.
  */
-
-
 #ifndef _IRGRAPH_T_H_
 #define _IRGRAPH_T_H_
 
 #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_ */
index d29e521..0cfee7b 100644 (file)
@@ -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 {
 
index 98a1d72..0a5098a 100644 (file)
 
 #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. */