<commit_before>/*
 * Project:     libFIRM
 * File name:   ir/opt/opt_confirms.c
 * Purpose:     Optimizations regarding Confirm nodes
 * Author:      <NAME>
 * Modified by:
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2005 Universitt Karlsruhe
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "tv_t.h"
#include "iropt_t.h"
#include "opt_confirms.h"

enum range_tags {
  MIN_INCLUDED = 0x00,  /**< [min, ... */
  MAX_INCLUDED = 0x00,  /**< ..., max] */
  MIN_EXCLUDED = 0x01,  /**< (min, ... */
  MAX_EXCLUDED = 0x02   /**< ..., max) */
};

/**
 * An interval. We could use
 * intervals that ALWAYS include its borders, even for
 * floating point, as the precision is limited.
 * However, as our tarval module did not support
 * such kind of operation, we use border flags allowing
 * all intervals.
 */
typedef struct _interval_t {
  tarval        *min;   /**< lowest border */
  tarval        *max;   /**< highest border */
  unsigned char flags;  /**< border flags */
} interval_t;

/**
 * Check, if the value of a node is != 0.
 *
 * This is a often needed case, so we handle here Confirm
 * nodes too.
 */
int value_not_zero(ir_node *n)
{
#define RET_ON(x)  if (x) return 1; break

  tarval *tv;
  ir_mode *mode;
  pn_Cmp pnc;

  while (get_irn_op(n) == op_Confirm) {
    /*
     * Note: A Confirm is never after a Const. So,
     * we simply can check the bound for beeing a Const
     * without the fear that is might be hidden by a further Confirm.
     */
    tv = value_of(get_Confirm_bound(n));
    if (tv == tarval_bad)
      return 0;

    mode = get_tarval_mode(tv);
    pnc  = tarval_cmp(tv, get_mode_null(mode));

    switch (get_Confirm_cmp(n)) {
    case pn_Cmp_Eq: /* n == C /\ C != 0 ==> n != 0, should never happen, but simple */
      RET_ON(pnc != pn_Cmp_Eq);
    case pn_Cmp_Lg: /* n != C /\ C == 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Eq);
    case pn_Cmp_Lt: /* n <  C /\ C <= 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq);
    case pn_Cmp_Le: /* n <= C /\ C <  0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Lt);
    case pn_Cmp_Ge: /* n >= C /\ C >  0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Gt);
    case pn_Cmp_Gt: /* n >  C /\ C >= 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Gt || pnc == pn_Cmp_Eq);
    default:
      break;
	}

    /* there might be several Confirms one after other that form an interval */
    n = get_Confirm_value(n);
  }
  tv = value_of(n);

  return (tv != tarval_bad) && (classify_tarval(tv) != TV_CLASSIFY_NULL);

#undef RET_ON
}

/*
 * Check, if the value of a node can be confirmed >= 0 or <= 0,
 * If the mode of the value did not honor signed zeros, else
 * check for >= 0 or < 0.
 */
value_classify classify_value_sign(ir_node *n)
{
  tarval *tv, *c;
  ir_mode *mode;
  pn_Cmp cmp, ncmp;

  if (get_irn_op(n) != op_Confirm)
    return VALUE_UNKNOWN;

  tv  = value_of(get_Confirm_bound(n));
  if (tv == tarval_bad)
    return VALUE_UNKNOWN;

  mode = get_irn_mode(n);

  /*
   * We can handle only >=, >, <, <= cases.
   * We could handle == too, but this will be optimized into
   * a constant either.
   *
   * Note that for integer modes we have a slightly better
   * optimization possibilities, so we handle this
   * different.
   */
  cmp = get_Confirm_cmp(n);

  switch (cmp) {
  case pn_Cmp_Lt:
    /*
     * must be x < c <= 1 to be useful if integer mode and -0 = 0
     *         x < c <= 0 to be useful else
     */
  case pn_Cmp_Le:
    /*
     * must be x <= c < 1 to be useful if integer mode and -0 = 0
     *         x <= c < 0 to be useful else
     */
    c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ?
      get_mode_one(mode) : get_mode_null(mode);

    ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
    if (cmp != ncmp)
      return VALUE_UNKNOWN;

    /* yep, negative */
    return VALUE_NEGATIVE;

  case pn_Cmp_Ge:
    /*
     * must be x >= c > -1 to be useful if integer mode
     *         x >= c >= 0 to be useful else
     */
  case pn_Cmp_Gt:
    /*
     * must be x > c >= -1 to be useful if integer mode
     *         x > c >= 0 to be useful else
     */
    if (mode_is_int(mode)) {
      c = get_mode_minus_one(mode);

      ncmp = tarval_cmp(tv, c) ^ pn_Cmp_Eq;
      if (cmp != ncmp)
        return VALUE_UNKNOWN;
    }
    else {
      c = get_mode_minus_one(mode);

      ncmp = tarval_cmp(tv, c);

      if (ncmp != pn_Cmp_Eq && ncmp != pn_Cmp_Gt)
        return VALUE_UNKNOWN;
    }

    /* yep, positive */
    return VALUE_POSITIVE;

  default:
    return VALUE_UNKNOWN;
  }
}

/**
 * construct an interval from a value
 */
static interval_t *get_interval_from_tv(interval_t *iv, tarval *tv)
{
  ir_mode *mode = get_tarval_mode(tv);

  if (tv == tarval_bad) {
    /* [-oo, +oo] */
    iv->min   = get_mode_min(mode);
    iv->max   = get_mode_max(mode);
    iv->flags = MIN_INCLUDED | MAX_INCLUDED;<commit_msg>fixed classify_value() function<commit_after>/*
 * Project:     libFIRM
 * File name:   ir/opt/opt_confirms.c
 * Purpose:     Optimizations regarding Confirm nodes
 * Author:      <NAME>
 * Modified by:
 * Created:
 * CVS-ID:      $Id$
 * Copyright:   (c) 1998-2005 <NAME>
 * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include "tv_t.h"
#include "iropt_t.h"
#include "opt_confirms.h"

enum range_tags {
  MIN_INCLUDED = 0x00,  /**< [min, ... */
  MAX_INCLUDED = 0x00,  /**< ..., max] */
  MIN_EXCLUDED = 0x01,  /**< (min, ... */
  MAX_EXCLUDED = 0x02   /**< ..., max) */
};

/**
 * An interval. We could use
 * intervals that ALWAYS include its borders, even for
 * floating point, as the precision is limited.
 * However, as our tarval module did not support
 * such kind of operation, we use border flags allowing
 * all intervals.
 */
typedef struct _interval_t {
  tarval        *min;   /**< lowest border */
  tarval        *max;   /**< highest border */
  unsigned char flags;  /**< border flags */
} interval_t;

/**
 * Check, if the value of a node is != 0.
 *
 * This is a often needed case, so we handle here Confirm
 * nodes too.
 */
int value_not_zero(ir_node *n)
{
#define RET_ON(x)  if (x) return 1; break

  tarval *tv;
  ir_mode *mode;
  pn_Cmp pnc;

  while (get_irn_op(n) == op_Confirm) {
    /*
     * Note: A Confirm is never after a Const. So,
     * we simply can check the bound for beeing a Const
     * without the fear that is might be hidden by a further Confirm.
     */
    tv = value_of(get_Confirm_bound(n));
    if (tv == tarval_bad)
      return 0;

    mode = get_tarval_mode(tv);
    pnc  = tarval_cmp(tv, get_mode_null(mode));

    switch (get_Confirm_cmp(n)) {
    case pn_Cmp_Eq: /* n == C /\ C != 0 ==> n != 0, should never happen, but simple */
      RET_ON(pnc != pn_Cmp_Eq);
    case pn_Cmp_Lg: /* n != C /\ C == 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Eq);
    case pn_Cmp_Lt: /* n <  C /\ C <= 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Lt || pnc == pn_Cmp_Eq);
    case pn_Cmp_Le: /* n <= C /\ C <  0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Lt);
    case pn_Cmp_Ge: /* n >= C /\ C >  0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Gt);
    case pn_Cmp_Gt: /* n >  C /\ C >= 0 ==> n != 0 */
      RET_ON(pnc == pn_Cmp_Gt || pnc == pn_Cmp_Eq);
    default:
      break;
	}

    /* there might be several Confirms one after other that form an interval */
    n = get_Confirm_value(n);
  }
  tv = value_of(n);

  return (tv != tarval_bad) && (classify_tarval(tv) != TV_CLASSIFY_NULL);

#undef RET_ON
}

/*
 * Check, if the value of a node can be confirmed >= 0 or <= 0,
 * If the mode of the value did not honor signed zeros, else
 * check for >= 0 or < 0.
 */
value_classify classify_value_sign(ir_node *n)
{
  tarval *tv, *c;
  ir_mode *mode;
  pn_Cmp cmp, ncmp;

  if (get_irn_op(n) != op_Confirm)
    return VALUE_UNKNOWN;

  tv  = value_of(get_Confirm_bound(n));
  if (tv == tarval_bad)
    return VALUE_UNKNOWN;

  mode = get_irn_mode(n);

  /*
   * We can handle only >=, >, <, <= cases.
   * We could handle == too, but this will be optimized into
   * a constant either.
   *
   * Note that for integer modes we have a slightly better
   * optimization possibilities, so we handle this
   * different.
   */
  cmp = get_Confirm_cmp(n);

  switch (cmp) {
  case pn_Cmp_Lt:
    /*
     * must be x < c <= 1 to be useful if integer mode and -0 = 0
     *         x < c <= 0 to be useful else
     */
  case pn_Cmp_Le:
    /*
     * must be x <= c < 1 to be useful if integer mode and -0 = 0
     *         x <= c < 0 to be useful else
     */
    c = mode_is_int(mode) && mode_honor_signed_zeros(mode) ?
      get_mode_one(mode) : get_mode_null(mode);

    ncmp = tarval_cmp(tv, c);
    if (ncmp == pn_Cmp_Eq)
      ncmp = pn_Cmp_Le;

    if (cmp != (ncmp ^ pn_Cmp_Eq))
      return VALUE_UNKNOWN;

    /* yep, negative */
    return VALUE_NEGATIVE;

  case pn_Cmp_Ge:
    /*
     * must be x >= c > -1 to be useful if integer mode
     *         x >= c >= 0 to be useful else
     */
  case pn_Cmp_Gt:
    /*
     * must be x > c >= -1 to be useful if integer mode
     *         x > c >= 0 to be useful else
     */
    if (mode_is_int(mode)) {
      c = get_mode_minus_one(mode);

      ncmp = tarval_cmp(tv, c);
      if (ncmp == pn_Cmp_Eq)
        ncmp = pn_Cmp_Ge;

      if (cmp != (ncmp ^ pn_Cmp_Eq))
        return VALUE_UNKNOWN;
    }
    else {
      c = get_mode_minus_one(mode);

      ncmp = tarval_cmp(tv, c);

      if (ncmp != pn_Cmp_Eq && ncmp != pn_Cmp_Gt)
        return VALUE_UNKNOWN;
    }

    /* yep, positive */
    return VALUE_POSITIVE;

  default:
    return VALUE_UNKNOWN;
  }
}

/**
 * construct an interval from a value
 */
static interval_t *get_interval_from_tv(interval_t *iv, tarval *tv)
{
  ir_mode *mode = get_tarval_mode(tv);

  if (tv == tarval_bad) {
    /* [-oo, +oo] */
    iv->min   = get_mode_min(mode);
    iv->max   = get_mode_max(mode);
    iv->flags = MIN_INCLUDED | MAX_INCLUDED;
{'fraction_non_alphanumeric': 0.1356, 'fraction_numerical': 0.0102, 'mean_word_length': 2.3515415549597853, 'pattern_counts': {'":': 0, '<': 52, '<?xml version=': 0, '>': 56, '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': '6573395', 'n_tokens_mistral': 3966, 'n_tokens_neox': 3815, 'n_words': 1114}