Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
fb0f4a3a
Commit
fb0f4a3a
authored
Feb 16, 2014
by
Matthias Braun
Browse files
merge value_not_zero() into value_not_null(), cleanup and move it to iropt.c
parent
b539d120
Changes
3
Hide whitespace changes
Inline
Side-by-side
include/libfirm/iroptimize.h
View file @
fb0f4a3a
...
...
@@ -555,30 +555,12 @@ FIRM_API void fixpoint_vrp(ir_graph*);
FIRM_API
void
occult_consts
(
ir_graph
*
);
/**
* Checks if the value of a node is != 0.
*
* This is a often needed case, so we handle here Confirm
* nodes too.
* Returns true if the value @p n is known not be zero/null.
*
* @param n a node representing the value
* @param confirm if n is confirmed to be != 0, returns
* the the Confirm-node, else NULL
*/
FIRM_API
int
value_not_zero
(
const
ir_node
*
n
,
const
ir_node
**
confirm
);
/**
* Checks if the value of a node cannot represent a NULL pointer.
*
* - If option sel_based_null_check_elim is enabled, all
* Sel nodes can be skipped.
* - A Address is NEVER a NULL pointer
* - A Const != NULL is NEVER a NULL pointer
* - Confirms are evaluated
*
* @param n a node representing the value
* @param confirm if n is confirmed to be != NULL, returns
* the the Confirm-node, else NULL
*/
FIRM_API
int
value_not_null
(
const
ir_node
*
n
,
const
ir_node
**
confirm
);
/**
...
...
ir/ir/iropt.c
View file @
fb0f4a3a
...
...
@@ -112,6 +112,96 @@ void set_value_of_func(value_of_func func)
value_of_ptr
=
default_value_of
;
}
int
value_not_null
(
const
ir_node
*
n
,
const
ir_node
**
confirm
)
{
*
confirm
=
NULL
;
/* walk confirm sequence and look for matching confirms */
for
(;;)
{
/* -x != 0 => x != 0 */
if
(
is_Minus
(
n
))
{
n
=
get_Minus_op
(
n
);
continue
;
}
/* we can ignore Sels: either the base pointer points to null or
* if it doesn't then members addresses cannot be at NULL or we have
* undefined behaviour because we are obviously not pointing to an
* object. */
if
(
is_Sel
(
n
))
{
n
=
get_Sel_ptr
(
n
);
continue
;
}
if
(
!
is_Confirm
(
n
))
break
;
ir_node
*
bound
=
get_Confirm_bound
(
n
);
if
(
!
is_Const
(
bound
))
{
n
=
get_Confirm_value
(
n
);
continue
;
}
ir_tarval
*
tv
=
get_Const_tarval
(
bound
);
ir_mode
*
mode
=
get_irn_mode
(
n
);
ir_tarval
*
null
=
get_mode_null
(
mode
);
ir_relation
relation
=
tarval_cmp
(
tv
,
null
);
switch
(
get_Confirm_relation
(
n
))
{
case
ir_relation_equal
:
/* n == C && C != 0 ==> n != 0 */
if
(
relation
!=
ir_relation_equal
)
goto
confirmed
;
break
;
case
ir_relation_less_greater
:
/* n != C /\ C == 0 ==> n != 0 */
if
(
relation
==
ir_relation_equal
)
goto
confirmed
;
break
;
case
ir_relation_less
:
/* n < C /\ C <= 0 ==> n != 0 */
if
(
relation
==
ir_relation_less
||
relation
==
ir_relation_equal
)
goto
confirmed
;
break
;
case
ir_relation_less_equal
:
/* n <= C /\ C < 0 ==> n != 0 */
if
(
relation
==
ir_relation_less
)
goto
confirmed
;
break
;
case
ir_relation_greater_equal
:
/* n >= C /\ C > 0 ==> n != 0 */
if
(
relation
==
ir_relation_greater
)
goto
confirmed
;
break
;
case
ir_relation_greater
:
/* n > C /\ C >= 0 ==> n != 0 */
if
(
relation
==
ir_relation_greater
||
relation
==
ir_relation_equal
)
{
confirmed:
*
confirm
=
n
;
return
true
;
}
break
;
default:
break
;
}
n
=
get_Confirm_value
(
n
);
}
if
(
is_Const
(
n
))
{
ir_tarval
*
tv
=
get_Const_tarval
(
n
);
return
!
tarval_is_null
(
tv
);
}
/* global entities are never NULL */
if
(
is_Address
(
n
))
return
true
;
/* the frame pointer is never NULL */
if
(
is_Proj
(
n
)
&&
is_Start
(
get_Proj_pred
(
n
))
&&
get_Proj_proj
(
n
)
==
pn_Start_P_frame_base
)
return
true
;
/* alloc never returns NULL (but throws an exception in the error case) */
if
(
is_Alloc
(
n
))
return
true
;
/* for all we know the value may be null */
return
false
;
}
/**
* Return the value of a Constant.
*/
...
...
@@ -624,7 +714,7 @@ static ir_tarval *do_computed_value_Div(const ir_node *div)
/* cannot optimize 0 / b = 0 because of NaN */
if
(
!
mode_is_float
(
mode
))
{
if
(
tarval_is_null
(
ta
)
&&
value_not_
zero
(
b
,
&
dummy
))
if
(
tarval_is_null
(
ta
)
&&
value_not_
null
(
b
,
&
dummy
))
return
ta
;
/* 0 / b == 0 if b != 0 */
}
ir_tarval
*
tb
=
value_of
(
b
);
...
...
@@ -3011,7 +3101,7 @@ static ir_node *transform_node_Div(ir_node *n)
}
const
ir_node
*
dummy
;
if
(
a
==
b
&&
value_not_
zero
(
a
,
&
dummy
))
{
if
(
a
==
b
&&
value_not_
null
(
a
,
&
dummy
))
{
ir_graph
*
irg
=
get_irn_irg
(
n
);
/* BEWARE: we can optimize a/a to 1 only if this cannot cause a exception */
value
=
new_r_Const
(
irg
,
get_mode_one
(
mode
));
...
...
@@ -3124,7 +3214,7 @@ static ir_node *transform_node_Mod(ir_node *n)
ir_node
*
b
=
get_Mod_right
(
n
);
const
ir_node
*
dummy
;
if
(
a
==
b
&&
value_not_
zero
(
a
,
&
dummy
))
{
if
(
a
==
b
&&
value_not_
null
(
a
,
&
dummy
))
{
/* BEWARE: we can optimize a%a to 0 only if this cannot cause a exception */
value
=
create_zero_const
(
irg
,
mode
);
DBG_OPT_CSTEVAL
(
n
,
value
);
...
...
@@ -3686,7 +3776,7 @@ static ir_node *transform_node_Proj_Div(ir_node *proj)
const
ir_node
*
b
=
get_Div_right
(
div
);
const
ir_node
*
confirm
;
if
(
value_not_
zero
(
b
,
&
confirm
))
{
if
(
value_not_
null
(
b
,
&
confirm
))
{
/* div(x, y) && y != 0 */
if
(
confirm
==
NULL
)
{
/* we are sure we have a Const != 0 */
...
...
@@ -3737,7 +3827,7 @@ static ir_node *transform_node_Proj_Mod(ir_node *proj)
ir_node
*
b
=
get_Mod_right
(
mod
);
const
ir_node
*
confirm
;
if
(
value_not_
zero
(
b
,
&
confirm
))
{
if
(
value_not_
null
(
b
,
&
confirm
))
{
/* mod(x, y) && y != 0 */
if
(
confirm
==
NULL
)
{
...
...
@@ -6165,7 +6255,7 @@ static ir_node *transform_node_Load(ir_node *n)
}
const
ir_node
*
confirm
;
if
(
value_not_
zero
(
ptr
,
&
confirm
)
&&
confirm
==
NULL
)
{
if
(
value_not_
null
(
ptr
,
&
confirm
)
&&
confirm
==
NULL
)
{
set_irn_pinned
(
n
,
op_pin_state_floats
);
}
...
...
@@ -6211,7 +6301,7 @@ static ir_node *transform_node_Store(ir_node *n)
ir_node
*
ptr
=
get_Store_ptr
(
n
);
const
ir_node
*
confirm
;
if
(
value_not_
zero
(
ptr
,
&
confirm
)
&&
confirm
==
NULL
)
{
if
(
value_not_
null
(
ptr
,
&
confirm
)
&&
confirm
==
NULL
)
{
set_irn_pinned
(
n
,
op_pin_state_floats
);
}
return
n
;
...
...
ir/opt/opt_confirms.c
View file @
fb0f4a3a
...
...
@@ -72,140 +72,6 @@ static tarval *compare_iv_dbg(const interval_t *l_iv, const interval_t *r_iv, ir
#endif
/* DEBUG_CONFIRM */
/*
* 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
(
const
ir_node
*
n
,
const
ir_node
**
confirm
)
{
#define RET_ON(x) if (x) { *confirm = n; return 1; } break
ir_tarval
*
tv
;
ir_mode
*
mode
=
get_irn_mode
(
n
);
ir_relation
relation
;
*
confirm
=
NULL
;
/* there might be several Confirms one after other that form an interval */
for
(;;)
{
if
(
is_Minus
(
n
))
{
/* we can safely skip Minus when checking for != 0 */
n
=
get_Minus_op
(
n
);
continue
;
}
if
(
!
is_Confirm
(
n
))
break
;
/*
* Note: A Confirm is never after a Const. So,
* we simply can check the bound for being 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
)
{
n
=
get_Confirm_value
(
n
);
continue
;
}
relation
=
tarval_cmp
(
tv
,
get_mode_null
(
mode
));
/*
* Beware: C might by a NaN. It is not clear, what we should do
* than. Of course a NaN is != 0, but we might use this function
* to remove up Exceptions, and NaN's might generate Exception.
* So, we do NOT handle NaNs here for safety.
*
* Note that only the C != 0 case need additional checking.
*/
switch
(
get_Confirm_relation
(
n
))
{
case
ir_relation_equal
:
/* n == C /\ C != 0 ==> n != 0 */
RET_ON
(
relation
!=
ir_relation_equal
&&
relation
!=
ir_relation_unordered
);
case
ir_relation_less_greater
:
/* n != C /\ C == 0 ==> n != 0 */
RET_ON
(
relation
==
ir_relation_equal
);
case
ir_relation_less
:
/* n < C /\ C <= 0 ==> n != 0 */
RET_ON
(
relation
==
ir_relation_less
||
relation
==
ir_relation_equal
);
case
ir_relation_less_equal
:
/* n <= C /\ C < 0 ==> n != 0 */
RET_ON
(
relation
==
ir_relation_less
);
case
ir_relation_greater_equal
:
/* n >= C /\ C > 0 ==> n != 0 */
RET_ON
(
relation
==
ir_relation_greater
);
case
ir_relation_greater
:
/* n > C /\ C >= 0 ==> n != 0 */
RET_ON
(
relation
==
ir_relation_greater
||
relation
==
ir_relation_equal
);
default:
break
;
}
n
=
get_Confirm_value
(
n
);
}
/* global entities are never NULL */
if
(
is_Address
(
n
))
return
true
;
tv
=
value_of
(
n
);
if
(
tv
==
tarval_bad
)
return
false
;
relation
=
tarval_cmp
(
tv
,
get_mode_null
(
mode
));
/* again, need check for NaN */
return
(
relation
!=
ir_relation_equal
)
&&
(
relation
!=
ir_relation_unordered
);
#undef RET_ON
}
/*
* Check, if the value of a node cannot represent a NULL pointer.
*
* - Sels are skipped
* - An Address is NEVER a NULL pointer
* - Confirms are evaluated
*/
int
value_not_null
(
const
ir_node
*
n
,
const
ir_node
**
confirm
)
{
ir_tarval
*
tv
;
*
confirm
=
NULL
;
tv
=
value_of
(
n
);
if
(
tarval_is_constant
(
tv
)
&&
!
tarval_is_null
(
tv
))
return
1
;
assert
(
mode_is_reference
(
get_irn_mode
(
n
)));
/* skip all Sel nodes */
while
(
is_Sel
(
n
))
{
n
=
get_Sel_ptr
(
n
);
}
while
(
1
)
{
if
(
is_Proj
(
n
))
{
n
=
get_Proj_pred
(
n
);
continue
;
}
break
;
}
if
(
is_Address
(
n
))
{
/* global references are never NULL */
return
1
;
}
else
if
(
n
==
get_irg_frame
(
get_irn_irg
(
n
)))
{
/* local references are never NULL */
return
1
;
}
else
if
(
is_Alloc
(
n
))
{
/* alloc never returns NULL (it throws an exception instead) */
return
1
;
}
else
{
/* check for more Confirms */
for
(;
is_Confirm
(
n
);
n
=
get_Confirm_value
(
n
))
{
if
(
get_Confirm_relation
(
n
)
==
ir_relation_less_greater
)
{
ir_node
*
bound
=
get_Confirm_bound
(
n
);
ir_tarval
*
tv
=
value_of
(
bound
);
if
(
tarval_is_null
(
tv
))
{
*
confirm
=
n
;
return
1
;
}
}
}
}
return
0
;
}
/**
* construct an interval from a value
*
...
...
@@ -659,7 +525,7 @@ check_null_case:
tv
=
relation
==
ir_relation_equal
?
tarval_b_false
:
tarval_b_true
;
}
}
else
{
if
(
value_not_
zero
(
left
,
&
dummy
))
{
if
(
value_not_
null
(
left
,
&
dummy
))
{
tv
=
relation
==
ir_relation_equal
?
tarval_b_false
:
tarval_b_true
;
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment