Commit af666143 authored by Matthias Braun's avatar Matthias Braun
Browse files

cleanup special tarval and Unknown usage

This commit does:
- Remove tarval_reachable+tarval_unreachable, dataflow analysis rather
  use top/bottom instead of other special values.
- Rename tarval_undefined to tarval_unknown as it corresponds to the
  Unknown node (=a value which we don't know)
- Remove predefined tarval_top/tarval_bottom from tv.h and place the
  defines into combo.c
- Change compute_XXX constant folding functions to return tarval_unknown
  instead of tarval_bad if folding failed
- compute_Unknown in combo results in tarval_bottom == tarval_unknown
  this eliminates strange special cases in the Cond/Switch rules and the
  now unnecessary cprop_X list.
parent 67add5ec
......@@ -22,7 +22,7 @@
/** If the expression referenced can be evaluated statically
* computed_value returns a tarval representing the result.
* Else returns tarval_bad. */
* Else returns tarval_unknown. */
FIRM_API ir_tarval *computed_value(const ir_node *n);
/** Applies all optimizations to n that are expressible as a pattern
......
......@@ -271,46 +271,28 @@ FIRM_API int tarval_is_all_one(const ir_tarval *tv);
*/
FIRM_API int tarval_is_constant(const ir_tarval *tv);
/** The 'bad' tarval. */
FIRM_API ir_tarval *tarval_bad;
/** The 'bad' tarval. Representing "no value", do not confuse this with
* tarval_unknown. */
FIRM_API ir_tarval *const tarval_bad;
/** Returns the 'bad' tarval. */
FIRM_API ir_tarval *get_tarval_bad(void);
/** The 'undefined' tarval. */
FIRM_API ir_tarval *tarval_undefined;
/** Returns the 'undefined' tarval. */
FIRM_API ir_tarval *get_tarval_undefined(void);
/** The 'unknown' tarval. Representing an unknown (but legal) value, do
* not confuse this with tarval_bad. */
FIRM_API ir_tarval *const tarval_unknown;
/** Returns the 'unknown' tarval. */
FIRM_API ir_tarval *get_tarval_unknown(void);
/** The mode_b tarval 'false'. */
FIRM_API ir_tarval *tarval_b_false;
FIRM_API ir_tarval *const tarval_b_false;
/** Returns the mode_b tarval 'false'. */
FIRM_API ir_tarval *get_tarval_b_false(void);
/** The mode_b tarval 'true'. */
FIRM_API ir_tarval *tarval_b_true;
FIRM_API ir_tarval *const tarval_b_true;
/** Returns the mode_b tarval 'true'. */
FIRM_API ir_tarval *get_tarval_b_true(void);
/** The mode_X tarval 'unreachable'. */
FIRM_API ir_tarval *tarval_unreachable;
/** Returns the mode_X tarval 'unreachable'. */
FIRM_API ir_tarval *get_tarval_unreachable(void);
/** The mode_X tarval 'reachable'. */
FIRM_API ir_tarval *tarval_reachable;
/** Returns the mode_X tarval 'reachable'. */
FIRM_API ir_tarval *get_tarval_reachable(void);
/** The 'top' tarval. This is just another name for the 'undefined' tarval. */
#define tarval_top tarval_undefined
/** Returns the 'top' tarval. */
#define get_tarval_top() get_tarval_undefined()
/** The 'bottom' tarval. This is just another name for the 'bad' tarval. */
#define tarval_bottom tarval_bad
/** Returns the 'bottom' tarval. */
#define get_tarval_bottom() get_tarval_bad()
/** Returns the maximum value of a given mode. */
FIRM_API ir_tarval *get_tarval_max(ir_mode *mode);
......@@ -343,8 +325,8 @@ FIRM_API ir_tarval *get_tarval_minus_inf(ir_mode *mode);
/** Modes for handling integer overflows. */
typedef enum tarval_int_overflow_mode_t {
TV_OVERFLOW_BAD, /**< tarval module will return tarval_bad if a overflow occurs */
TV_OVERFLOW_WRAP, /**< tarval module will overflow will be ignored, wrap around occurs */
TV_OVERFLOW_BAD, /**< tarval module will return tarval_bad if an overflow occurs */
TV_OVERFLOW_WRAP, /**< overflow will be ignored, wrap around occurs */
TV_OVERFLOW_SATURATE /**< tarval module will saturate the overflow */
} tarval_int_overflow_mode_t;
......
......@@ -43,8 +43,8 @@ static vrp_attr *vrp_get_or_set_info(ir_vrp_info *info, const ir_node *node)
attr->range_type = VRP_UNDEFINED;
attr->bits_set = get_mode_null(mode);
attr->bits_not_set = get_mode_all_one(mode);
attr->range_bottom = get_tarval_top();
attr->range_top = get_tarval_top();
attr->range_bottom = tarval_bad;
attr->range_top = tarval_bad;
ir_nodemap_insert(&info->infos, node, attr);
}
......
......@@ -279,7 +279,7 @@ static ir_tarval *get_initializer_tarval(const ir_initializer_t *initializer)
return get_Const_tarval(node);
}
}
return get_tarval_undefined();
return get_tarval_unknown();
}
static bool initializer_is_string_const(const ir_initializer_t *initializer,
......
......@@ -307,7 +307,7 @@ end:
} else { /* non-float mode */
tv = tarval_convert_to(tv, ia32_mode_gp);
if (tv == get_tarval_bad() || tv == get_tarval_undefined() ||
if (tv == get_tarval_bad() || tv == get_tarval_unknown() ||
tv == NULL) {
panic("couldn't convert constant tarval (%+F)", node);
}
......
This diff is collapsed.
......@@ -560,7 +560,7 @@ static ir_tarval *get_initializer_value(ir_initializer_t *const init, ir_mode *c
break;
}
return get_tarval_undefined();
return get_tarval_unknown();
}
static bool initializer_val_is_null(ir_initializer_t *init)
......
This diff is collapsed.
......@@ -102,7 +102,9 @@ static int get_conv_costs(const ir_node *node, ir_mode *dest_mode)
return 0;
if (is_Const(node)) {
return conv_const_tv(node, dest_mode) == tarval_bad ? 1 : 0;
ir_tarval *conved = conv_const_tv(node, dest_mode);
return (conved != tarval_bad && conved != tarval_unknown)
? 0 : 1;
}
if (is_Conv(node) &&
......@@ -179,7 +181,7 @@ static ir_node *conv_transform(ir_node *node, ir_mode *dest_mode)
if (is_Const(node)) {
ir_tarval *tv = conv_const_tv(node, dest_mode);
if (tv == tarval_bad) {
if (tv == tarval_bad || tv == tarval_unknown) {
return place_conv(node, dest_mode);
} else {
return new_r_Const(irg, tv);
......
......@@ -393,7 +393,7 @@ static void transform_allocs(ir_graph *irg, walk_env_t *env)
} else if (is_Const(size)) {
ir_tarval *tv = get_Const_tarval(size);
if (tv != tarval_bad && tarval_is_long(tv) &&
if (tarval_is_long(tv) &&
get_type_state(atp) == layout_fixed &&
(unsigned)get_tarval_long(tv) == get_type_size_bytes(atp)) {
/* a already lowered type size */
......
......@@ -351,7 +351,7 @@ static int eval_cmp(jumpthreading_env_t *env, ir_node *cand)
assert(is_Confirm(cand));
ir_tarval *res = computed_value_Cmp_Confirm(env->cmp, cand, env->cnst,
env->relation);
if (res == tarval_bad)
if (res == tarval_unknown)
return -1;
return res == tarval_b_true;
}
......
......@@ -246,7 +246,7 @@ static ir_entity *find_constant_entity(ir_node *ptr)
ir_tarval *tv = computed_value(index);
/* check if the index is constant */
if (tv == tarval_bad)
if (tv == tarval_unknown)
return NULL;
ir_node *lower = get_array_lower_bound(tp, i);
......@@ -254,7 +254,7 @@ static ir_entity *find_constant_entity(ir_node *ptr)
ir_node *upper = get_array_upper_bound(tp, i);
ir_tarval *tupper = computed_value(upper);
if (tlower == tarval_bad || tupper == tarval_bad)
if (tlower == tarval_unknown || tupper == tarval_unknown)
return NULL;
if (tarval_cmp(tv, tlower) == ir_relation_less)
......
......@@ -82,11 +82,11 @@ static interval_t *get_interval_from_tv(interval_t *iv, ir_tarval *tv)
{
ir_mode *mode = get_tarval_mode(tv);
if (tv == tarval_bad) {
if (tv == tarval_unknown) {
if (mode_is_float(mode)) {
/* NaN could be included which we cannot handle */
iv->min = tarval_bad;
iv->max = tarval_bad;
iv->min = tarval_unknown;
iv->max = tarval_unknown;
iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
return NULL;
} else {
......@@ -100,8 +100,8 @@ static interval_t *get_interval_from_tv(interval_t *iv, ir_tarval *tv)
if (mode_is_float(mode) && tarval_is_nan(tv)) {
/* arg, we cannot handle NaN's. */
iv->min = tarval_bad;
iv->max = tarval_bad;
iv->min = tarval_unknown;
iv->max = tarval_unknown;
iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
return NULL;
}
......@@ -129,22 +129,22 @@ static interval_t *get_interval(interval_t *iv, ir_node *bound, ir_relation rela
ir_mode *mode = get_irn_mode(bound);
ir_tarval *tv = value_of(bound);
if (tv == tarval_bad) {
if (tv == tarval_unknown) {
/* There is nothing we could do here. For integer
* modes we could return [-oo, +oo], but there is
* nothing we could deduct from such an interval.
* So, speed things up and return unknown.
*/
iv->min = tarval_bad;
iv->max = tarval_bad;
iv->min = tarval_unknown;
iv->max = tarval_unknown;
iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
return NULL;
}
if (mode_is_float(mode) && tarval_is_nan(tv)) {
/* arg, we cannot handle NaN's. */
iv->min = tarval_bad;
iv->max = tarval_bad;
iv->min = tarval_unknown;
iv->max = tarval_unknown;
iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
return NULL;
......@@ -203,13 +203,13 @@ static interval_t *get_interval(interval_t *iv, ir_node *bound, ir_relation rela
* We do not handle UNORDERED, as a NaN
* could be included in the interval.
*/
iv->min = tarval_bad;
iv->max = tarval_bad;
iv->min = tarval_unknown;
iv->max = tarval_unknown;
iv->flags = MIN_EXCLUDED | MAX_EXCLUDED;
return NULL;
}
if (iv->min != tarval_bad && iv->max != tarval_bad)
if (iv->min != tarval_unknown && iv->max != tarval_unknown)
return iv;
return NULL;
}
......@@ -223,7 +223,7 @@ static interval_t *get_interval(interval_t *iv, ir_node *bound, ir_relation rela
*
* @return
* tarval_b_true or tarval_b_false it it can be evaluated,
* tarval_bad else
* tarval_unknown else
*/
static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, ir_relation relation)
{
......@@ -233,7 +233,7 @@ static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, i
/* if one interval contains NaNs, we cannot evaluate anything */
if (! l_iv || ! r_iv)
return tarval_bad;
return tarval_unknown;
/* we can only check ordered relations */
if (relation & ir_relation_unordered) {
......@@ -342,9 +342,9 @@ static ir_tarval *(compare_iv)(const interval_t *l_iv, const interval_t *r_iv, i
return tv_true;
default:
return tarval_bad;
return tarval_unknown;
}
return tarval_bad;
return tarval_unknown;
}
/**
......@@ -376,7 +376,7 @@ ir_tarval *computed_value_Cmp_Confirm(const ir_node *cmp, ir_node *left,
relation = get_inversed_relation(relation);
} else if (!is_Confirm(left))
return tarval_bad;
return tarval_unknown;
/* ok, here at least left is a Confirm, right might be */
ir_node *l_bound = get_Confirm_bound(left);
......@@ -462,7 +462,7 @@ ir_tarval *computed_value_Cmp_Confirm(const ir_node *cmp, ir_node *left,
get_interval(&r_iv, r_bound, r_relation),
relation);
if (tv != tarval_bad) {
if (tv != tarval_unknown) {
DBG_EVAL_CONFIRM(cmp);
return tv;
}
......@@ -503,14 +503,14 @@ ir_tarval *computed_value_Cmp_Confirm(const ir_node *cmp, ir_node *left,
/* now, only right == Const can help */
tv = value_of(right);
if (tv != tarval_bad) {
if (tv != tarval_unknown) {
tv = compare_iv(
get_interval(&l_iv, l_bound, l_relation),
get_interval_from_tv(&r_iv, tv),
relation);
}
if (tv != tarval_bad)
if (tv != tarval_unknown)
DBG_EVAL_CONFIRM(cmp);
return tv;
......@@ -573,8 +573,8 @@ static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir
{
tarval *tv = (compare_iv)(l_iv, r_iv, relation);
if (tv == tarval_bad)
return tv;
if (tv == tarval_unknown)
return tv;
ir_printf("In %e:\n", get_irg_entity(current_ir_graph));
print_iv_cmp(l_iv, r_iv, relation);
......
......@@ -1195,7 +1195,7 @@ flt2int_result_t fc_flt2int(const fp_value *a, sc_word *result,
case FC_NORMAL:
if (a->sign && !result_signed) {
/* FIXME: for now we cannot convert this */
return FLT2INT_UNKNOWN;
return FLT2INT_BAD;
}
unsigned tgt_bits = result_bits - result_signed;
......@@ -1233,7 +1233,7 @@ flt2int_result_t fc_flt2int(const fp_value *a, sc_word *result,
case FC_NAN:
break;
}
return FLT2INT_UNKNOWN;
return FLT2INT_BAD;
}
bool fc_is_exact(void)
......
......@@ -154,7 +154,7 @@ typedef enum flt2int_result_t {
FLT2INT_OK,
FLT2INT_POSITIVE_OVERFLOW,
FLT2INT_NEGATIVE_OVERFLOW,
FLT2INT_UNKNOWN
FLT2INT_BAD
} flt2int_result_t;
/**
......
......@@ -196,15 +196,15 @@ static ir_tarval *get_tarval_overflow(const void *value, size_t length,
return get_tarval(value, length, mode);
}
static ir_tarval reserved_tv[2];
static ir_tarval nonconst_tvs[4];
static ir_tarval tarval_b_false_obj;
static ir_tarval tarval_b_true_obj;
static ir_tarval tarval_bad_obj;
static ir_tarval tarval_unknown_obj;
ir_tarval *tarval_b_false = &reserved_tv[0];
ir_tarval *tarval_b_true = &reserved_tv[1];
ir_tarval *tarval_bad = &nonconst_tvs[0];
ir_tarval *tarval_undefined = &nonconst_tvs[1];
ir_tarval *tarval_reachable = &nonconst_tvs[2];
ir_tarval *tarval_unreachable = &nonconst_tvs[3];
ir_tarval *const tarval_b_false = &tarval_b_false_obj;
ir_tarval *const tarval_b_true = &tarval_b_true_obj;
ir_tarval *const tarval_bad = &tarval_bad_obj;
ir_tarval *const tarval_unknown = &tarval_unknown_obj;
/**
* get the float descriptor for given mode.
......@@ -470,9 +470,9 @@ ir_tarval *(get_tarval_bad)(void)
return _get_tarval_bad();
}
ir_tarval *(get_tarval_undefined)(void)
ir_tarval *(get_tarval_unknown)(void)
{
return _get_tarval_undefined();
return _get_tarval_unknown();
}
ir_tarval *(get_tarval_b_false)(void)
......@@ -485,16 +485,6 @@ ir_tarval *(get_tarval_b_true)(void)
return _get_tarval_b_true();
}
ir_tarval *(get_tarval_reachable)(void)
{
return _get_tarval_reachable();
}
ir_tarval *(get_tarval_unreachable)(void)
{
return _get_tarval_unreachable();
}
ir_tarval *get_tarval_max(ir_mode *mode)
{
switch (get_mode_sort(mode)) {
......@@ -629,8 +619,7 @@ ir_tarval *get_tarval_all_one(ir_mode *mode)
int tarval_is_constant(const ir_tarval *tv)
{
size_t const num_res = ARRAY_SIZE(nonconst_tvs);
return tv < &nonconst_tvs[0] || &nonconst_tvs[num_res] <= tv;
return tv != tarval_bad && tv != tarval_unknown;
}
ir_tarval *get_tarval_minus_one(ir_mode *mode)
......@@ -708,36 +697,35 @@ int tarval_is_negative(const ir_tarval *a)
panic("invalid mode sort");
}
int tarval_is_null(const ir_tarval *a)
int tarval_is_null(const ir_tarval *tv)
{
return a != tarval_bad && a == get_mode_null(get_tarval_mode(a));
return tv != tarval_unknown && tv != tarval_bad
&& tv == get_mode_null(get_tarval_mode(tv));
}
int tarval_is_one(const ir_tarval *a)
int tarval_is_one(const ir_tarval *tv)
{
return a != tarval_bad && a == get_mode_one(get_tarval_mode(a));
return tv != tarval_unknown && tv != tarval_bad
&& tv == get_mode_one(get_tarval_mode(tv));
}
int tarval_is_all_one(const ir_tarval *tv)
{
return tv != tarval_bad && tv == get_mode_all_one(get_tarval_mode(tv));
return tv != tarval_unknown && tv != tarval_bad
&& tv == get_mode_all_one(get_tarval_mode(tv));
}
int tarval_is_minus_one(const ir_tarval *a)
int tarval_is_minus_one(const ir_tarval *tv)
{
return a != tarval_bad && a == get_mode_minus_one(get_tarval_mode(a));
return tv != tarval_unknown && tv != tarval_bad
&& tv == get_mode_minus_one(get_tarval_mode(tv));
}
ir_relation tarval_cmp(const ir_tarval *a, const ir_tarval *b)
{
if (a == tarval_bad || b == tarval_bad) {
panic("Comparison with tarval_bad");
}
if (a == tarval_undefined || b == tarval_undefined)
return ir_relation_false;
if (a->mode != b->mode)
if (a == tarval_unknown || b == tarval_unknown)
return ir_relation_true;
if (a == tarval_bad || b == tarval_bad || a->mode != b->mode)
return ir_relation_false;
/* Here the two tarvals are unequal and of the same mode */
......@@ -797,7 +785,7 @@ ir_tarval *tarval_convert_to(ir_tarval *src, ir_mode *dst_mode)
break;
case FLT2INT_NEGATIVE_OVERFLOW:
return get_mode_min(dst_mode);
case FLT2INT_UNKNOWN:
case FLT2INT_BAD:
return tarval_bad;
case FLT2INT_OK:
return get_tarval(buffer, sc_value_length, dst_mode);
......@@ -1332,12 +1320,8 @@ int tarval_snprintf(char *buf, size_t len, ir_tarval *tv)
default:
if (tv == tarval_bad)
return snprintf(buf, len, "<TV_BAD>");
else if (tv == tarval_undefined)
return snprintf(buf, len, "<TV_UNDEFINED>");
else if (tv == tarval_reachable)
return snprintf(buf, len, "<TV_REACHABLE>");
else if (tv == tarval_unreachable)
return snprintf(buf, len, "<TV_UNREACHABLE>");
else if (tv == tarval_unknown)
return snprintf(buf, len, "<TV_UNKNOWN>");
else
return snprintf(buf, len, "<TV_??""?>");
}
......@@ -1382,12 +1366,8 @@ const char *ir_tarval_to_ascii(char *buf, size_t len, ir_tarval *tv)
case irms_auxiliary:
if (tv == tarval_bad)
return "bad";
else if (tv == tarval_undefined)
return "undefined";
else if (tv == tarval_reachable)
return "reachable";
else if (tv == tarval_unreachable)
return "unreachable";
else if (tv == tarval_unknown)
return "unknown";
break;
}
panic("invalid tarval");
......@@ -1415,12 +1395,8 @@ ir_tarval *ir_tarval_from_ascii(const char *buf, ir_mode *mode)
case irms_auxiliary:
if (strcmp(buf, "bad") == 0)
return tarval_bad;
else if (strcmp(buf, "undefined") == 0)
return tarval_undefined;
else if (strcmp(buf, "reachable") == 0)
return tarval_reachable;
else if (strcmp(buf, "unreachable") == 0)
return tarval_unreachable;
else if (strcmp(buf, "unknown") == 0)
return tarval_unknown;
break;
}
panic("invalid mode for tarval_from_ascii");
......@@ -1574,25 +1550,19 @@ void init_tarval_1(int support_quad_precision)
void init_tarval_2(void)
{
tarval_bad->kind = k_tarval;
tarval_bad->mode = mode_BAD;
tarval_undefined->kind = k_tarval;
tarval_undefined->mode = mode_ANY;
tarval_b_true->kind = k_tarval;
tarval_b_true->mode = mode_b;
tarval_b_true->value = "\1";
tarval_bad->kind = k_tarval;
tarval_bad->mode = mode_BAD;
tarval_b_false->kind = k_tarval;
tarval_b_false->mode = mode_b;
tarval_b_false->value = "\0";
tarval_unknown->kind = k_tarval;
tarval_unknown->mode = mode_ANY;
tarval_unreachable->kind = k_tarval;
tarval_unreachable->mode = mode_X;
tarval_b_true->kind = k_tarval;
tarval_b_true->mode = mode_b;
tarval_b_true->value = "\1";
tarval_reachable->kind = k_tarval;
tarval_reachable->mode = mode_X;
tarval_b_false->kind = k_tarval;
tarval_b_false->mode = mode_b;
tarval_b_false->value = "\0";
}
void finish_tarval(void)
......
......@@ -22,11 +22,9 @@
#define get_tarval_mode(tv) _get_tarval_mode(tv)
#define get_tarval_bad() _get_tarval_bad()
#define get_tarval_undefined() _get_tarval_undefined()
#define get_tarval_unknown() _get_tarval_unknown()
#define get_tarval_b_false() _get_tarval_b_false()
#define get_tarval_b_true() _get_tarval_b_true()
#define get_tarval_unreachable() _get_tarval_unreachable()
#define get_tarval_reachable() _get_tarval_reachable()
#define is_tarval(thing) _is_tarval(thing)
#define SC_BITS 4
......@@ -89,9 +87,9 @@ static inline ir_tarval *_get_tarval_bad(void)
return tarval_bad;
}
static inline ir_tarval *_get_tarval_undefined(void)
static inline ir_tarval *_get_tarval_unknown(void)
{
return tarval_undefined;
return tarval_unknown;
}
static inline ir_tarval *_get_tarval_b_false(void)
......@@ -104,16 +102,6 @@ static inline ir_tarval *_get_tarval_b_true(void)
return tarval_b_true;
}
static inline ir_tarval *_get_tarval_reachable(void)
{
return tarval_reachable;
}
static inline ir_tarval *_get_tarval_unreachable(void)
{
return tarval_unreachable;
}
static inline int _is_tarval(const void *thing)
{
return get_kind(thing) == k_tarval;
......
......@@ -183,7 +183,10 @@ class Bad:
Phis to be shortened too for example). So instead of removing block inputs
they are set to Bad, and the actual removal is left to the control flow
optimization phase. Block, Phi, Tuple with only Bad inputs however are
replaced by Bad right away."""
replaced by Bad right away.
In the future we may use the Bad node to model poison values that arise
from undefined behaviour like reading uninitialized local variables in C."""
flags = [ "start_block", "dump_noblock" ]
pinned = "yes"
knownBlock = True
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment