compute_loop_info moved into an own file
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 22 Dec 2005 11:50:18 +0000 (11:50 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 22 Dec 2005 11:50:18 +0000 (11:50 +0000)
[r7114]

ir/ana/Makefile.in
ir/ana/compute_loop_info.c [new file with mode: 0644]
ir/ana/compute_loop_info.h [new file with mode: 0644]

index cbb1fe4..ff52154 100644 (file)
@@ -27,7 +27,8 @@ SOURCES += Makefile.in \
                irloop_t.h irbackedge.c irbackedge_t.h irscc.c ircfscc.c        \
                irtypeinfo.c irsimpletype.c interval_analysis.c                 \
                callgraph.c field_temperature.c execution_frequency.c phiclass.c \
-               irextbb.c irextbb_t.h irconsconfirm.c analyze_irg_args.c
+               irextbb.c irextbb_t.h irconsconfirm.c analyze_irg_args.c \
+               compute_loop_info.c compute_loop_info.h
 
 include $(topdir)/MakeRules
 
diff --git a/ir/ana/compute_loop_info.c b/ir/ana/compute_loop_info.c
new file mode 100644 (file)
index 0000000..b2b73e8
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Project:     libFIRM
+ * File name:   ir/opt/construct_loop.c
+ * Purpose:     Construct some loop infromation.
+ * Author:      Beyhan Veliev
+ * Created:
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 1998-2005 Universität Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+# include "compute_loop_info.h"
+# include "strength_red.h"
+# include "tv.h"
+# include "irgwalk.h"
+# include "irloop_t.h"
+# include "irgopt.h"
+# include "irflag.h"
+# include "irouts.h"
+# include "tv.h"
+
+#undef TRUE
+#define TRUE 1   /**< For loops, that are count loop. */
+
+static char _x;
+static void *NODE_VISITED = &_x;
+
+/* Walk over the successors of the loop iteration varialbe and
+ *   decided if the loop a count loop is.
+ *
+ * @param *node          A ir node.
+ * @param *loop_head     The head of the loop that be checked.
+ */
+static int is_count_loop(ir_node *node, ir_node *loop_head)
+{
+  int i,  res = 1;
+  set_irn_link(node, NODE_VISITED);
+  for (i = get_irn_n_outs(node) - 1; i >= 0; --i) {
+    ir_node *succ = get_irn_out(node, i);
+    /* The start position is reached.*/
+    if(get_irn_link(succ) == NODE_VISITED)
+      return 1;
+    /* The iteration varible musn't be chanched aside the iteration and the loop mussn't have
+       a break.*/
+    if ((is_loop_invariant(succ, loop_head) && get_irn_op(node) == op_Proj) ||
+        (get_irn_op(succ) == op_Phi && !is_loop_invariant(succ, loop_head)))
+      return 0;
+      else
+       if(get_irn_link(succ) != NODE_VISITED)
+         res = is_count_loop(succ, loop_head);
+  }
+  return res;
+}
+/**
+ * Compute the end value, that be reached from the interation.
+ *
+ * @param *loop_start       The loop's start value.
+ * @param *loop_end         The loop's end, that "cmp" node have as parameter.
+ * @param *loop_step        The value, with that inductan variable is (in|de)cremented.
+ * @param *is_endlessloop   A integer to set of 1, if the loop is endlees in mathematic mean.
+ * @param *is_untroddenloop A integer to set of 1, if the loop is dead, that mean the loop can't be trodden.
+ * @param *info             A struct, that contain loop information.
+ */
+static void compute_loop_end(tarval *loop_start, tarval *loop_end, tarval *loop_step,
+                                   int *is_endlessloop, int *is_untroddenloop, induct_var_info *info)
+{
+  ir_node *cmp_out;
+  int cmp_typ;
+  tarval *tarval_one, *diff;
+  tarval_one = get_tarval_one(get_tarval_mode(loop_step));
+
+  cmp_out   = get_irn_out(info->cmp, 0);
+  cmp_typ   = get_Proj_proj(cmp_out);
+  if((tarval_is_negative(loop_start) && tarval_is_negative(loop_end)) ||
+     (!tarval_is_negative(loop_start) && !tarval_is_negative(loop_end)) ||
+     (tarval_is_null(loop_start) || tarval_is_null(loop_end)))
+    diff = tarval_abs(tarval_sub(loop_end, loop_start));
+  else
+    diff = tarval_add(tarval_abs(loop_end),tarval_abs(loop_start));
+  diff = tarval_mod(diff, loop_step);
+
+  if(get_irn_op(info->op) == op_Add && !tarval_is_negative(loop_step)){
+    /* iterator < loop_end*/
+    if(cmp_typ == pn_Cmp_Lt){
+      /* A loop that can't be entered as  for(i = 10; i < 5; i++) */
+      if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq ||
+         tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt){
+       *is_untroddenloop = 1;
+       return;
+      }
+      if(diff == get_tarval_null(get_tarval_mode(loop_start)))
+       diff = loop_step;
+      info->l_itervar_phi->loop_iter_end = tarval_sub(loop_end, diff);
+    }else
+      if(cmp_typ == pn_Cmp_Lg){
+       /* A loop that can't be entered as  for(i = 5; i != 5; i++) */
+       if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq){
+         *is_untroddenloop = 1;
+         return;
+       }
+       if(tarval_cmp(loop_start, tarval_sub(get_mode_max(get_tarval_mode(loop_step)), loop_step)) == pn_Cmp_Gt){
+           info->l_itervar_phi->flags |= loop_downto_loop;
+           loop_step = tarval_sub(loop_start, tarval_add(loop_step, loop_start));
+           info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, loop_step);
+       }else
+         info->l_itervar_phi->loop_iter_end = tarval_sub(loop_end, loop_step);
+      }else
+         /* iterator <= loop_end*/
+       if(cmp_typ == pn_Cmp_Le){
+         /* A loop that can't be entered as  for(i = 10; i <= 5; i++) */
+         if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt){
+             *is_untroddenloop = 1;
+             return;
+         }
+         /* A endless loop as  for(i = 10; i <= 0xFFFFFFFF; i++) */
+         if (tarval_cmp(loop_end, get_mode_max(get_tarval_mode(loop_start))) == pn_Cmp_Eq){
+             info->l_itervar_phi->flags |= loop_is_endless;
+             return;
+         }
+         if (tarval_cmp(loop_end, tarval_sub(get_mode_max(get_tarval_mode(loop_start)), tarval_one)) == pn_Cmp_Eq)
+           if(tarval_cmp(loop_step, tarval_one) == pn_Cmp_Gt)
+             info->l_itervar_phi->flags |= loop_end_false;
+         info->l_itervar_phi->loop_iter_end = tarval_sub(loop_end, diff);
+       }else{
+         /* iterator > loop_end*/
+         if(cmp_typ == pn_Cmp_Gt){
+           /* A endless loop in mathematic mean that iterate until 0xFFFFFFFF as  for(i = 10; i > 5; i++) */
+           if(tarval_cmp(loop_start, tarval_sub(get_mode_max(get_tarval_mode(loop_step)), loop_step)) == pn_Cmp_Gt){
+             if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt ){
+               info->l_itervar_phi->flags |= loop_downto_loop;
+               loop_step = tarval_sub(loop_start, tarval_add(loop_step, loop_start));
+               diff = tarval_sub(loop_start, loop_end);
+               diff = tarval_mod(diff, loop_step);
+               if(diff == get_tarval_null(get_tarval_mode(loop_start)))
+                 diff = loop_step;
+               info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, diff);
+             }else
+               /* A loop that can't be entered as  for(i = 4; i > 5; i++) */
+               *is_untroddenloop = 1;
+           }else
+             if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt )
+               *is_endlessloop = 1;
+             else
+               /* A loop that can't be entered as  for(i = 4; i > 5; i++) */
+               *is_untroddenloop = 1;
+           /* iterator >= loop_end*/
+         }else{
+           /* Test if the cmp is after the incrementation and add to loop start one.*/
+           if(get_irn_link(info->cmp_const) != NULL)
+             loop_start = tarval_add(loop_start, loop_step);
+           /* A endless loop in mathematic mean that iterate until 0xFFFFFFFF as  for(i = 10; i > 5; i++) */
+           if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq ||
+              tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt)
+             *is_endlessloop = 1;
+           else
+             /* A loop that can't be entered as  for(i = 4; i >= 5; i++) */
+             *is_untroddenloop = 1;
+           }
+       }
+  }else
+    /* The loop iterate downto.*/
+    if(get_irn_op(info->op) == op_Add && tarval_is_negative(loop_step)){
+      info->l_itervar_phi->flags |= loop_downto_loop;
+      /* iterator > loop_end*/
+      if(cmp_typ == pn_Cmp_Gt){
+       /* A loop that can't be entered as  for(i = 4; i > 5; i = i+(-1)) */
+       if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq ||
+           tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt ){
+         *is_untroddenloop = 1;
+         return;
+       }
+       if(diff == get_tarval_null(get_tarval_mode(loop_start)))
+         diff = tarval_abs(loop_step);
+       info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, diff);
+       }else
+         if(cmp_typ == pn_Cmp_Lg){
+           /* A loop that can't be entered as  for(i = 5; i != 5; i--) */
+           if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq)
+             *is_untroddenloop = 1;
+
+           info->l_itervar_phi->loop_iter_end = tarval_sub(loop_end, loop_step);
+         }else
+           /* iterator >= loop_end*/
+           if(cmp_typ == pn_Cmp_Ge){
+             /* Test if the cmp is after the incrementation and add to loop start the loop step.*/
+             if(get_irn_link(info->cmp_const) != NULL)
+               loop_start = tarval_add(loop_start, loop_step);
+             /* A loop that can't be entered as  for(i = 4; i >= 5; i--) */
+             if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt){
+               *is_untroddenloop = 1;
+               return;
+             }
+             /* A endless loop as  for(i = 10; i >=(int)0x0; i--) */
+             if (tarval_cmp(loop_end, get_mode_min(get_tarval_mode(loop_start))) == pn_Cmp_Eq){
+               info->l_itervar_phi->flags |= loop_is_endless;
+               return;
+             }
+             if (tarval_cmp(loop_end, tarval_add(get_mode_min(get_tarval_mode(loop_start)), tarval_one)) == pn_Cmp_Eq)
+               if(tarval_cmp(tarval_abs(loop_step), tarval_one) == pn_Cmp_Gt)
+                 info->l_itervar_phi->flags |= loop_end_false;
+             info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, diff);;
+           } else
+             /* iterator < loop_end*/
+             if(cmp_typ == pn_Cmp_Lt){
+               /* A loop that can't be entered as  for(i = 6; i < 5; i--) */
+               if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt ||
+                  tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq)
+                 *is_untroddenloop = 1;
+               else
+                 /* A endless loop in mathematic mean that iterate until 0xFFFFFFFF as  for(i = 4; i < 5; i--) */
+                 *is_endlessloop = 1;
+             }else{
+               /* A loop that can't be entered as  for(i = 6; i <= 5; i = i+(-1)) */
+               if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Gt)
+                 *is_untroddenloop = 1;
+               else
+                 /* A endless loop in mathematic mean that iterate until 0xFFFFFFFF as  for(i = 4; i < 5; i--) */
+                 *is_endlessloop = 1;
+             }
+    }else
+      if(get_irn_op(info->op) == op_Sub && !tarval_is_negative(loop_step)){
+       info->l_itervar_phi->flags |= loop_downto_loop;
+       if(cmp_typ == pn_Cmp_Lg){
+         /* A loop that can't be entered as  for(i = 5; i != 5; i++) */
+         if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq)
+           *is_untroddenloop = 1;
+
+         info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, loop_step);
+       }else
+         if(cmp_typ == pn_Cmp_Gt){
+           /*A loop that can't be entered as  for(i = 10; i < 5; i++)*/
+           if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq ||
+               tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt){
+             *is_untroddenloop = 1;
+             return;
+           }
+           if(diff == get_tarval_null(get_tarval_mode(loop_start)))
+             diff = loop_step;
+           info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, diff);
+         }else
+           /* iterator <= loop_end*/
+           if(cmp_typ == pn_Cmp_Ge){
+             /* A loop that can't be entered as  for(i = 10; i <= 5; i++) */
+             if (tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt){
+               *is_untroddenloop = 1;
+               return;
+             }
+             /* A endless loop as  for((unsigned)i = 10; i >= 0x0; i--) */
+             if (tarval_cmp(loop_end, get_mode_min(get_tarval_mode(loop_start))) == pn_Cmp_Eq){
+               info->l_itervar_phi->flags |= loop_is_endless;
+               return;
+             }
+             if (tarval_cmp(loop_end, tarval_add(get_mode_min(get_tarval_mode(loop_start)), tarval_one)) == pn_Cmp_Eq)
+               if(tarval_cmp(loop_step, tarval_one) == pn_Cmp_Gt)
+                 info->l_itervar_phi->flags |= loop_end_false;
+             info->l_itervar_phi->loop_iter_end = tarval_add(loop_end, diff);
+           }else{
+             /* iterator < loop_end*/
+             if(cmp_typ == pn_Cmp_Lt){
+               /* A endless loop in mathematic mean that iterate until 0x0 as  for(i = 5; i <= 10; i--) */
+           if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt )
+             *is_endlessloop = 1;
+           else
+             /* A loop that can't be entered as  for(i = 4; i > 5; i++) */
+             *is_untroddenloop = 1;
+           /* iterator >= loop_end*/
+             }else{
+               /* Test if the cmp is after the (in|de)crementation and sub to loop start one.*/
+             if(get_irn_link(info->cmp_const) != NULL)
+               loop_start = tarval_sub(loop_start, loop_step);
+             /* A endless loop in mathematic mean that iterate until 0x0 as  for(i = 5; i <= 10; i--) */
+             if(tarval_cmp(loop_start, loop_end) == pn_Cmp_Eq ||
+                tarval_cmp(loop_start, loop_end) == pn_Cmp_Lt)
+               *is_endlessloop = 1;
+             else
+               /* A loop that can't be entered as  for(i = 4; i >= 5; i++) */
+               *is_untroddenloop = 1;
+             }
+         }
+      }
+}
+int is_do_loop(induct_var_info *info)
+{
+  ir_node *cmp_pred_0, *cmp_pred_1;
+  cmp_pred_0 = get_irn_n(info->cmp, 0);
+  cmp_pred_1 = get_irn_n(info->cmp, 1);
+  if(get_irn_op(cmp_pred_0) == op_Phi ||
+     get_irn_op(cmp_pred_1) == op_Phi)
+    return 0;
+  else
+    return 1;
+}
+
+
+/**
+ * set the loop end if the loop couldn't be computed from the function "compute_loop_end",
+ * the loop is endless in mathematic mean or the loop is dead.
+ * @param is_endlessloop   A integer, that is set to 1, if the loop is endlees in mathematic mean.
+ * @param is_untroddenloop A integer, that is  set to 1, if the loop is dead, that mean the loop can't be trodden.
+ * @param *info             A struct, that contain loop information.
+ */
+static void set_loop_end(int is_endlessloop, int is_untroddenloop, induct_var_info *info)
+{
+
+    if(is_endlessloop){
+      if(info->l_itervar_phi->flags & loop_downto_loop)
+       info->l_itervar_phi->loop_iter_end = get_mode_min(get_tarval_mode(get_Const_tarval(info->cmp_const)));
+      else
+       info->l_itervar_phi->loop_iter_end = get_mode_max(get_tarval_mode(get_Const_tarval(info->cmp_const)));
+    }else
+      if(is_untroddenloop || info->l_itervar_phi->loop_iter_end == NULL)
+       info->l_itervar_phi->loop_iter_end  = get_Const_tarval(info->cmp_const);
+}
+/**
+ * Walker: checks every phi node for a induction variable and
+ * compute some loop information.
+ *
+ * @param n        An IR node.
+ * @param env      Free environment pointer.
+ */
+static void set_loop_info(ir_node *n, void *env)
+{
+  tarval *loop_end;
+  induct_var_info info;
+  int is_endlessloop = 0 , is_untroddenloop = 0;
+  /* The IR node must be a induction variable. */
+  if (get_irn_op(n) != op_Phi)
+    return;
+
+  info.itervar_phi = n;
+
+  /* Just induction variables are tested. */
+  if (!is_induction_variable(&info))
+    return;
+  /* If the loop haven't a "cmp" node to break the iteration,
+   * then this loop can't be a count loop.*/
+  if (info.cmp == NULL) {
+    return;
+  } else {
+    set_irn_link(info.cmp, NODE_VISITED);
+    if(!is_count_loop(info.itervar_phi, get_loop_node(info.l_itervar_phi, 0)))
+      return;
+  }
+
+  /* The loop start, end and iteration step muss be constants. */
+  if (get_irn_op(info.increment) != op_Const   ||
+      get_irn_op(info.init) != op_Const        ||
+      get_irn_op(info.cmp_const) != op_Const) {
+    return;
+  }
+  if(is_do_loop(&info))
+     info.l_itervar_phi->flags |= do_loop;
+
+  info.l_itervar_phi->loop_iter_start= get_Const_tarval(info.init);
+  loop_end  = get_Const_tarval(info.cmp_const);
+  info.l_itervar_phi->loop_iter_increment = get_Const_tarval(info.increment);
+  info.l_itervar_phi->loop_iter_variable  = info.itervar_phi;
+
+  compute_loop_end(info.l_itervar_phi->loop_iter_start, loop_end,  info.l_itervar_phi->loop_iter_increment,
+                         &is_endlessloop, &is_untroddenloop, &info);
+  if(is_endlessloop)
+    info.l_itervar_phi->flags |= loop_wrap_around;
+
+  if(is_untroddenloop){
+    if(info.l_itervar_phi->flags & do_loop)
+      info.l_itervar_phi->flags |= once;
+    else
+      info.l_itervar_phi->flags |= loop_is_dead;
+  }
+  /* The loop ist a count loop and the information is computed.*/
+  info.l_itervar_phi->flags              |= loop_is_count_loop;
+
+  set_loop_end(is_endlessloop, is_untroddenloop, &info);
+
+}
+
+/* Compute additional loop information
+ *
+ * @param *irg  The current ir graph.
+ */
+void compute_loop_info(ir_graph *irg)
+{
+  /* Call algorithm that computes the out edges */
+  compute_irg_outs(irg);
+  /* Call algorithm that computes the loop information */
+  construct_cf_backedges(irg);
+
+  /* -- Search expressions that can be optimized -- */
+  irg_walk_graph(irg, NULL, set_loop_info, NULL);
+}
diff --git a/ir/ana/compute_loop_info.h b/ir/ana/compute_loop_info.h
new file mode 100644 (file)
index 0000000..f8cfcf1
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Project:     libFIRM
+ * File name:   ir/ana/compute_loop_info.h
+ * Purpose:     Construct some loop infromation.
+ * Author:      Beyhan Veliev
+ * Created:
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 1998-2005 Universität Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
+#ifndef _COMPUTE_LOOP_INFO_
+#define _COMPUTE_LOOP_INFO_
+
+#include "irgraph.h"
+
+void compute_loop_info(ir_graph *irg);
+
+#endif  /* _COMPUTE_LOOP_INFO_ */