<commit_before>/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
** All rights reserved.
**
** Authors: <NAME>, <NAME>
**
** iropt --- optimizations intertwined with IR construction.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

# include "irnode_t.h"
# include "irgraph_t.h"
# include "iropt_t.h"
# include "ircons.h"
# include "irgmod.h"
# include "irvrfy.h"
# include "tv.h"
# include "tune.h"
# include "debinfo.h"

/* Make types visible to allow most efficient access */
# include "entity_t.h"

/* Trivial inlineable routine for copy propagation.
   Does follow Ids, needed to optimize inlined code. */
static inline ir_node *
follow_Id (ir_node *n)
{
  while (get_irn_op (n) == op_Id) n = get_Id_pred (n);
  return n;
}

static inline tarval *
value_of (ir_node *n)
{
  if ((n != NULL) && (get_irn_op(n) == op_Const))
    return get_Const_tarval(n);
  else
    return NULL;
}

/* if n can be computed, return the value, else NULL. Performs
   constant folding. GL: Only if n is arithmetic operator? */
tarval *
computed_value (ir_node *n)
{
  tarval *res;

  ir_node *a = NULL, *b = NULL;	 /* initialized to shut up gcc */
  tarval *ta = NULL, *tb = NULL; /* initialized to shut up gcc */

  res = NULL;

  /* get the operands we will work on for simple cases. */
  if (is_binop(n)) {
    a = get_binop_left(n);
    b = get_binop_right(n);
  } else if (is_unop(n)) {
    a = get_unop_op(n);
  }

  /* if the operands are constants, get the target value, else set it NULL.
     (a and b may be NULL if we treat a node that is no computation.) */
  ta = value_of (a);
  tb = value_of (b);

  /* Perform the constant evaluation / computation. */
  switch (get_irn_opcode(n)) {
  case iro_Const:
    res = get_Const_tarval(n);
  case iro_Add:
    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
	&& (get_irn_mode(a) != mode_p)) {
      res = tarval_add (ta, tb);
    }
    break;
  case iro_Sub:
    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
	&& (get_irn_mode(a) != mode_p)) {
      res = tarval_sub (ta, tb);
    } else if (a == b) {
      res = tarval_mode_null [get_irn_modecode (n)];
    }
    break;
  case iro_Minus:
      if (ta && mode_is_float(get_irn_mode(a)))
        res = tarval_neg (ta);
    break;
  case iro_Mul:
    if (ta && tb) /* tarval_mul tests for equivalent modes itself */ {
      res = tarval_mul (ta, tb);
    } else {
      /* a*0 = 0 or 0*b = 0:
	 calls computed_value recursive and returns the 0 with proper
         mode. */
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == 0)
	  || (tarval_classify ((v = computed_value (b))) == 0)) {
	res = v;
      }
    }
    break;
  case iro_Quot:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_quo(ta, tb);
    }
    break;
  case iro_Div:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_div(ta, tb);
    }
    break;
  case iro_Mod:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_mod(ta, tb);
    }
    break;
  case iro_Abs:
    if (ta)
      res = tarval_abs (ta);
    break;
  case iro_And:
    if (ta && tb) {
      res = tarval_and (ta, tb);
    } else {
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == 0)
	  || (tarval_classify ((v = computed_value (b))) == 0)) {
	res = v;
      }
    }
    break;
  case iro_Or:
    if (ta && tb) {
      res = tarval_or (ta, tb);
    } else {
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == -1)
	  || (tarval_classify ((v = computed_value (b))) == -1)) {
	res = v;
      }
    }
    break;
  case iro_Eor: if (ta && tb) { res = tarval_eor (ta, tb); } break;
  case iro_Not: if (ta)       { res = tarval_neg (ta); } break;
  case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break;
    /* tarval_shr is faulty !! */
  case iro_Shr: if (ta && tb) { res = tarval_shr (ta, tb); } break;
  case iro_Shrs:if (ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break;
  case iro_Rot: if (ta && tb) { /*res = tarval_rot (ta, tb)*/; } break;
  case iro_Conv:if (ta)       { res = tarval_convert_to (ta, get_irn_mode (n)); }
    break;
  case iro_Proj:  /* iro_Cmp */
    {
      ir_node *aa, *ab;

      a = get_Proj_pred(n);
      /* Optimize Cmp nodes.
	 This performs a first step of unreachable code elimination.
	 Proj can not be computed, but folding a Cmp above the Proj here is
	 not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
	 only 1 is used.
         There are several case where we can evaluate a Cmp node:
         1. The nodes compared are both the same.  If we compare for
            equal, this will return true, else it will return false.
            This step relies on cse.
         2. The predecessors of Cmp are target values.  We can evaluate
            the Cmp.
         3. The predecessors are Allocs or void* constants.  Allocs never
            return NULL, they raise an exception.   Therefore we can predict
            the Cmp result. */
      if (get_irn_op(a) == op_Cmp) {
        aa = get_Cmp_left(a);
        ab = get_Cmp_right(a);
	if (aa == ab) { /* 1.: */
          /* This is a tric with the bits used for encoding the Cmp
             Proj numbers, the following statement is not the same:
          res = tarval_from_long (mode_b, (get_Proj_proj(n) == Eq)):    */
	  res = tarval_from_long (mode_b, (get_Proj_proj(n) & irpn_Eq));
	} else {
	  tarval *taa = computed_value (aa);
	  tarval *tab = computed_value (ab);
	  if (taa && tab) { /* 2.: */
            /* strange checks... */
	    ir_pncmp flags = tarval_comp (taa, tab);
	    if (flags != irpn_False) {
              res = tarval_from_long (mode_b, get_Proj_proj(n) & flags);
	    }
	  } else {  /* check for 3.: */
            ir_node *aaa = skip_nop(skip_Proj(aa));
            ir_node *aba = skip_nop(skip_Proj(ab));
	    if (   (   (/* aa is ProjP and aaa is Alloc */
                           (get_irn_op(aa) == op_Proj)
    	                && (get_irn_mode(aa) == mode_p)
                        && (get_irn_op(aaa) == op_Alloc))
                    && (   (/* ab is constant void */
                               (get_irn_op(ab) == op_Const)
                            && (get_irn_mode(ab) == mode_p)
                            && (get_Const_tarval(ab) == tarval_p_void))
		        || (/* ab is other Alloc */
                               (get_irn_op(ab) == op_Proj)
    	                    && (get_irn_mode(ab) == mode_p)
                            && (get_irn_op(aba) == op_Alloc)
			    && (aaa != aba))))
		|| (/* aa is void and aba is Alloc */
                       (get_irn_op(aa) == op_Const)
                    && (get_irn_mode(aa) == mode_p)
                    && (get_Const_tarval(aa) == tarval_p_void)
                    && (get_irn_op(ab) == op_Proj)
    	            && (get_irn_mode(ab) == mode_p)
                    && (get_irn_op(aba) == op_Alloc)))
	      /* 3.: */
	      res = tarval_from_long (mode_b, get_Proj_proj(n) & irpn_Ne);
	  }
	}
      } else {
        /* printf(" # comp_val: Proj node, not optimized\n"); */
      }<commit_msg>added DivMod to constant evaluation.<commit_after>/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
** All rights reserved.
**
** Authors: <NAME>, <NAME>
**
** iropt --- optimizations intertwined with IR construction.
*/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

# include "irnode_t.h"
# include "irgraph_t.h"
# include "iropt_t.h"
# include "ircons.h"
# include "irgmod.h"
# include "irvrfy.h"
# include "tv.h"
# include "tune.h"
# include "debinfo.h"

/* Make types visible to allow most efficient access */
# include "entity_t.h"

/* Trivial inlineable routine for copy propagation.
   Does follow Ids, needed to optimize inlined code. */
static inline ir_node *
follow_Id (ir_node *n)
{
  while (get_irn_op (n) == op_Id) n = get_Id_pred (n);
  return n;
}

static inline tarval *
value_of (ir_node *n)
{
  if ((n != NULL) && (get_irn_op(n) == op_Const))
    return get_Const_tarval(n);
  else
    return NULL;
}

/* if n can be computed, return the value, else NULL. Performs
   constant folding. GL: Only if n is arithmetic operator? */
tarval *
computed_value (ir_node *n)
{
  tarval *res;

  ir_node *a = NULL, *b = NULL;	 /* initialized to shut up gcc */
  tarval *ta = NULL, *tb = NULL; /* initialized to shut up gcc */

  res = NULL;

  /* get the operands we will work on for simple cases. */
  if (is_binop(n)) {
    a = get_binop_left(n);
    b = get_binop_right(n);
  } else if (is_unop(n)) {
    a = get_unop_op(n);
  }

  /* if the operands are constants, get the target value, else set it NULL.
     (a and b may be NULL if we treat a node that is no computation.) */
  ta = value_of (a);
  tb = value_of (b);

  /* Perform the constant evaluation / computation. */
  switch (get_irn_opcode(n)) {
  case iro_Const:
    res = get_Const_tarval(n);
  case iro_Add:
    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
	&& (get_irn_mode(a) != mode_p)) {
      res = tarval_add (ta, tb);
    }
    break;
  case iro_Sub:
    if (ta && tb && (get_irn_mode(a) == get_irn_mode(b))
	&& (get_irn_mode(a) != mode_p)) {
      res = tarval_sub (ta, tb);
    } else if (a == b) {
      res = tarval_mode_null [get_irn_modecode (n)];
    }
    break;
  case iro_Minus:
      if (ta && mode_is_float(get_irn_mode(a)))
        res = tarval_neg (ta);
    break;
  case iro_Mul:
    if (ta && tb) /* tarval_mul tests for equivalent modes itself */ {
      res = tarval_mul (ta, tb);
    } else {
      /* a*0 = 0 or 0*b = 0:
	 calls computed_value recursive and returns the 0 with proper
         mode. */
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == 0)
	  || (tarval_classify ((v = computed_value (b))) == 0)) {
	res = v;
      }
    }
    break;
  case iro_Quot:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_quo(ta, tb);
    }
    break;
  case iro_Div:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_div(ta, tb);
    }
    break;
  case iro_Mod:
    /* This was missing in original implementation. Why? */
    if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
      if (tarval_classify(tb) == 0) {res = NULL; break;}
      res = tarval_mod(ta, tb);
    }
    break;
  /* for iro_DivMod see iro_Proj */
  case iro_Abs:
    if (ta)
      res = tarval_abs (ta);
    break;
  case iro_And:
    if (ta && tb) {
      res = tarval_and (ta, tb);
    } else {
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == 0)
	  || (tarval_classify ((v = computed_value (b))) == 0)) {
	res = v;
      }
    }
    break;
  case iro_Or:
    if (ta && tb) {
      res = tarval_or (ta, tb);
    } else {
      tarval *v;
      if (   (tarval_classify ((v = computed_value (a))) == -1)
	  || (tarval_classify ((v = computed_value (b))) == -1)) {
	res = v;
      }
    }
    break;
  case iro_Eor: if (ta && tb) { res = tarval_eor (ta, tb); } break;
  case iro_Not: if (ta)       { res = tarval_neg (ta); } break;
  case iro_Shl: if (ta && tb) { res = tarval_shl (ta, tb); } break;
    /* tarval_shr is faulty !! */
  case iro_Shr: if (ta && tb) { res = tarval_shr (ta, tb); } break;
  case iro_Shrs:if (ta && tb) { /*res = tarval_shrs (ta, tb)*/; } break;
  case iro_Rot: if (ta && tb) { /*res = tarval_rot (ta, tb)*/; } break;
  case iro_Conv:if (ta)       { res = tarval_convert_to (ta, get_irn_mode (n)); }
    break;
  case iro_Proj:  /* iro_Cmp */
    {
      ir_node *aa, *ab;

      a = get_Proj_pred(n);
      /* Optimize Cmp nodes.
	 This performs a first step of unreachable code elimination.
	 Proj can not be computed, but folding a Cmp above the Proj here is
	 not as wasteful as folding a Cmp into a Tuple of 16 Consts of which
	 only 1 is used.
         There are several case where we can evaluate a Cmp node:
         1. The nodes compared are both the same.  If we compare for
            equal, this will return true, else it will return false.
            This step relies on cse.
         2. The predecessors of Cmp are target values.  We can evaluate
            the Cmp.
         3. The predecessors are Allocs or void* constants.  Allocs never
            return NULL, they raise an exception.   Therefore we can predict
            the Cmp result. */
      if (get_irn_op(a) == op_Cmp) {
        aa = get_Cmp_left(a);
        ab = get_Cmp_right(a);
	if (aa == ab) { /* 1.: */
          /* This is a tric with the bits used for encoding the Cmp
             Proj numbers, the following statement is not the same:
          res = tarval_from_long (mode_b, (get_Proj_proj(n) == Eq)):    */
	  res = tarval_from_long (mode_b, (get_Proj_proj(n) & irpn_Eq));
	} else {
	  tarval *taa = computed_value (aa);
	  tarval *tab = computed_value (ab);
	  if (taa && tab) { /* 2.: */
            /* strange checks... */
	    ir_pncmp flags = tarval_comp (taa, tab);
	    if (flags != irpn_False) {
              res = tarval_from_long (mode_b, get_Proj_proj(n) & flags);
	    }
	  } else {  /* check for 3.: */
            ir_node *aaa = skip_nop(skip_Proj(aa));
            ir_node *aba = skip_nop(skip_Proj(ab));
	    if (   (   (/* aa is ProjP and aaa is Alloc */
                           (get_irn_op(aa) == op_Proj)
    	                && (get_irn_mode(aa) == mode_p)
                        && (get_irn_op(aaa) == op_Alloc))
                    && (   (/* ab is constant void */
                               (get_irn_op(ab) == op_Const)
                            && (get_irn_mode(ab) == mode_p)
                            && (get_Const_tarval(ab) == tarval_p_void))
		        || (/* ab is other Alloc */
                               (get_irn_op(ab) == op_Proj)
    	                    && (get_irn_mode(ab) == mode_p)
                            && (get_irn_op(aba) == op_Alloc)
			    && (aaa != aba))))
		|| (/* aa is void and aba is Alloc */
                       (get_irn_op(aa) == op_Const)
                    && (get_irn_mode(aa) == mode_p)
                    && (get_Const_tarval(aa) == tarval_p_void)
                    && (get_irn_op(ab) == op_Proj)
    	            && (get_irn_mode(ab) == mode_p)
                    && (get_irn_op(aba) == op_Alloc)))
	      /* 3.: */
	      res = tarval_from_long (mode_b, get_Proj_proj(n) & irpn_Ne);
	  }
	}
      } else if (get_irn_op(a) == op_DivMod) {
        ta = value_of(get_DivMod_left(a));
        tb = value_of(get_DivMod_right(a));
	if (ta && tb  && (get_irn_mode(a) == get_irn_mode(b))) {
	  if (tarval_classify(tb) == 0) {res = NULL; break;}
	  if (get_Proj_proj(n)== 0) /* Div */
	    res = tarval_div(ta, tb);
	  else /* Mod */
	    res = tarval_mod(ta, tb);
	}
      } else {
        /* printf(" # comp_val: Proj node, not optimized\n"); */
      }
{'fraction_non_alphanumeric': 0.1420303050009755, 'fraction_numerical': 0.00429212460167783, 'mean_word_length': 2.1648487343074705, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6384706', 'n_tokens_mistral': 5864, 'n_tokens_neox': 5652, 'n_words': 1599}