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
cbad497b
Commit
cbad497b
authored
Aug 22, 2012
by
Matthias Braun
Browse files
add more Conv(Conv) localopt rules
parent
ef3e7db6
Changes
5
Hide whitespace changes
Inline
Side-by-side
include/libfirm/irmode.h
View file @
cbad497b
...
...
@@ -330,20 +330,25 @@ FIRM_API int mode_is_datab (const ir_mode *mode);
FIRM_API
int
mode_is_dataM
(
const
ir_mode
*
mode
);
/**
* Returns true if sm can be converted to lm without
loss
*
according to firm definition
.
* Returns true if
a value of mode @p
sm can be converted to
mode @p
lm without
*
loss
.
*
* Note that mode_Iu is NOT smaller than mode_Is here.
* That is the interpretation of the numbers does not changes, so you a signed
* integer mode is never smaller than an unsigned integer mode since the
* unsigned mode can't represent negative numbers in a way that they are
* interpreted as negative numbers.
*
* @see values_in_mode()
*/
FIRM_API
int
smaller_mode
(
const
ir_mode
*
sm
,
const
ir_mode
*
lm
);
/**
* Returns true if
a value of mode sm can be converted into
mode
l
m
*
and backwards without loss
.
* Returns true if
no information is lost when converting a value of
mode
@p s
m
*
into mode @p lm (and back to mode @p sm)
.
*
* Note that mode_Iu values CAN be converted in mode_Is and back.
* So the interpretation of the values may change in the intermediate mode @p sm
* (for example when converting negative signed integer numbers into unsigned
* integers) but after a conversion back they are exactly the same value.
*
* @see smaller_mode()
*/
...
...
ir/ir/irmode.c
View file @
cbad497b
...
...
@@ -506,28 +506,34 @@ int smaller_mode(const ir_mode *sm, const ir_mode *lm)
int
values_in_mode
(
const
ir_mode
*
sm
,
const
ir_mode
*
lm
)
{
ir_mode_arithmetic
arith
;
assert
(
sm
);
assert
(
lm
);
if
(
sm
==
lm
)
return
1
;
if
(
sm
==
lm
)
return
true
;
if
(
sm
==
mode_b
)
return
mode_is_int
(
lm
);
arith
=
get_mode_arithmetic
(
sm
);
if
(
arith
!=
get_mode_arithmetic
(
lm
))
return
0
;
switch
(
arith
)
{
case
irma_twos_complement
:
case
irma_ieee754
:
return
mode_is_int
(
lm
)
||
mode_is_float
(
lm
);
ir_mode_arithmetic
larith
=
get_mode_arithmetic
(
lm
);
ir_mode_arithmetic
sarith
=
get_mode_arithmetic
(
sm
);
switch
(
larith
)
{
case
irma_x86_extended_float
:
case
irma_ieee754
:
if
(
sarith
==
irma_ieee754
||
sarith
==
irma_x86_extended_float
)
{
return
get_mode_size_bits
(
sm
)
<=
get_mode_size_bits
(
lm
);
default:
return
0
;
}
else
if
(
sarith
==
irma_twos_complement
)
{
unsigned
int_mantissa
=
get_mode_size_bits
(
sm
)
-
(
mode_is_signed
(
sm
)
?
1
:
0
);
unsigned
float_mantissa
=
get_mode_mantissa_size
(
lm
)
+
1
;
return
int_mantissa
<=
float_mantissa
;
}
break
;
case
irma_twos_complement
:
if
(
sarith
==
irma_twos_complement
)
{
return
get_mode_size_bits
(
sm
)
<=
get_mode_size_bits
(
lm
);
}
break
;
case
irma_none
:
break
;
}
return
false
;
}
ir_mode
*
get_reference_mode_signed_eq
(
ir_mode
*
mode
)
...
...
ir/ir/iropt.c
View file @
cbad497b
...
...
@@ -50,6 +50,7 @@
#include "firm_types.h"
#include "bitfiddle.h"
#include "be.h"
#include "error.h"
#include "entity_t.h"
...
...
@@ -1109,34 +1110,10 @@ static ir_node *equivalent_node_Conv(ir_node *n)
ir_node
*
b
=
get_Conv_op
(
a
);
ir_mode
*
b_mode
=
get_irn_mode
(
b
);
if
(
n_mode
==
b_mode
)
{
if
(
n_mode
==
mode_b
)
{
n
=
b
;
/* Convb(Conv*(xxxb(...))) == xxxb(...) */
DBG_OPT_ALGSIM1
(
oldn
,
a
,
b
,
n
,
FS_OPT_CONV
);
return
n
;
}
else
if
(
get_mode_arithmetic
(
n_mode
)
==
get_mode_arithmetic
(
a_mode
))
{
if
(
values_in_mode
(
b_mode
,
a_mode
))
{
n
=
b
;
/* ConvS(ConvL(xxxS(...))) == xxxS(...) */
DBG_OPT_ALGSIM1
(
oldn
,
a
,
b
,
n
,
FS_OPT_CONV
);
return
n
;
}
}
if
(
mode_is_int
(
n_mode
)
&&
get_mode_arithmetic
(
a_mode
)
==
irma_ieee754
)
{
/* ConvI(ConvF(I)) -> I, iff float mantissa >= int mode */
unsigned
int_mantissa
=
get_mode_size_bits
(
n_mode
)
-
(
mode_is_signed
(
n_mode
)
?
1
:
0
);
unsigned
float_mantissa
=
get_mode_mantissa_size
(
a_mode
);
if
(
float_mantissa
>=
int_mantissa
)
{
n
=
b
;
DBG_OPT_ALGSIM1
(
oldn
,
a
,
b
,
n
,
FS_OPT_CONV
);
return
n
;
}
}
if
(
is_Conv
(
b
)
&&
smaller_mode
(
b_mode
,
a_mode
))
{
n
=
b
;
/* ConvA(ConvB(ConvA(...))) == ConvA(...) */
DBG_OPT_ALGSIM1
(
oldn
,
a
,
b
,
n
,
FS_OPT_CONV
);
return
n
;
}
if
(
n_mode
==
b_mode
&&
values_in_mode
(
b_mode
,
a_mode
))
{
n
=
b
;
DBG_OPT_ALGSIM1
(
oldn
,
a
,
b
,
n
,
FS_OPT_CONV
);
return
n
;
}
}
return
n
;
...
...
@@ -5487,6 +5464,77 @@ static ir_node *transform_node_Rotl(ir_node *n)
return
n
;
}
/**
* returns mode size for may_leave_out_middle_mode
*/
static
unsigned
get_significand_size
(
ir_mode
*
mode
)
{
const
ir_mode_arithmetic
arithmetic
=
get_mode_arithmetic
(
mode
);
switch
(
arithmetic
)
{
case
irma_ieee754
:
case
irma_x86_extended_float
:
return
get_mode_mantissa_size
(
mode
)
+
1
;
case
irma_twos_complement
:
return
get_mode_size_bits
(
mode
);
case
irma_none
:
panic
(
"Conv node with irma_none mode?"
);
}
panic
(
"unexpected mode_arithmetic in get_significand_size"
);
}
/**
* Returns true if a conversion from mode @p m0 to @p m1 has the same effect
* as converting from @p m0 to @p m1 and then to @p m2.
* Classifying the 3 modes as the big(b), middle(m) and small(s) mode this
* gives the following truth table:
* s -> b -> m : true
* s -> m -> b : !signed(s) || signed(m)
* m -> b -> s : true
* m -> s -> b : false
* b -> s -> m : false
* b -> m -> s : true
*
* s -> b -> b : true
* s -> s -> b : false
*
* additional float constraints:
* F -> F -> F: fine
* F -> I -> I: signedness of Is must match
* I -> F -> I: signedness of Is must match
* I -> I -> F: signedness of Is must match
* F -> I -> F: bad
* I -> F -> F: fine
* F -> F -> I: fine
* at least 1 float involved: signedness must match
*/
bool
may_leave_out_middle_conv
(
ir_mode
*
m0
,
ir_mode
*
m1
,
ir_mode
*
m2
)
{
int
n_floats
=
mode_is_float
(
m0
)
+
mode_is_float
(
m1
)
+
mode_is_float
(
m2
);
if
(
n_floats
==
1
)
{
#if 0
int n_signed = mode_is_signed(m0) + mode_is_signed(m1)
+ mode_is_signed(m2);
/* we assume that float modes are always signed */
if ((n_signed & 1) != 1)
return false;
#else
/* because overflow gives strange results we don't touch this case */
return
false
;
#endif
}
else
if
(
n_floats
==
2
&&
!
mode_is_float
(
m1
))
{
return
false
;
}
unsigned
size0
=
get_significand_size
(
m0
);
unsigned
size1
=
get_significand_size
(
m1
);
unsigned
size2
=
get_significand_size
(
m2
);
if
(
size1
<
size2
&&
size0
>=
size1
)
return
false
;
if
(
size1
>=
size2
)
return
true
;
return
!
mode_is_signed
(
m0
)
||
mode_is_signed
(
m1
);
}
/**
* Transform a Conv.
*/
...
...
@@ -5496,6 +5544,17 @@ static ir_node *transform_node_Conv(ir_node *n)
ir_mode
*
mode
=
get_irn_mode
(
n
);
ir_node
*
a
=
get_Conv_op
(
n
);
if
(
is_Conv
(
a
))
{
ir_mode
*
a_mode
=
get_irn_mode
(
a
);
ir_node
*
b
=
get_Conv_op
(
a
);
ir_mode
*
b_mode
=
get_irn_mode
(
b
);
if
(
may_leave_out_middle_conv
(
b_mode
,
a_mode
,
mode
))
{
dbg_info
*
dbgi
=
get_irn_dbg_info
(
n
);
ir_node
*
block
=
get_nodes_block
(
n
);
return
new_rd_Conv
(
dbgi
,
block
,
b
,
mode
);
}
}
if
(
mode
!=
mode_b
&&
is_const_Phi
(
a
))
{
/* Do NOT optimize mode_b Conv's, this leads to remaining
* Phib nodes later, because the conv_b_lower operation
...
...
ir/ir/iropt_t.h
View file @
cbad497b
...
...
@@ -138,6 +138,11 @@ ir_node *ir_get_abs_op(const ir_node *sel, ir_node *mux_false,
bool
ir_is_optimizable_mux
(
const
ir_node
*
sel
,
const
ir_node
*
mux_false
,
const
ir_node
*
mux_true
);
/**
* Returns true if Conv_m0(Conv_m1( x_m2)) is equivalent to Conv_m0(x_m2)
*/
bool
may_leave_out_middle_conv
(
ir_mode
*
m0
,
ir_mode
*
m1
,
ir_mode
*
m2
);
void
ir_register_opt_node_ops
(
void
);
#endif
ir/opt/convopt.c
View file @
cbad497b
...
...
@@ -109,7 +109,6 @@ static int get_conv_costs(const ir_node *node, ir_mode *dest_mode)
return
0
;
if
(
is_Const
(
node
))
{
/* TODO tarval module is incomplete and can't convert floats to ints */
return
conv_const_tv
(
node
,
dest_mode
)
==
tarval_bad
?
1
:
0
;
}
...
...
@@ -155,10 +154,14 @@ static int get_conv_costs(const ir_node *node, ir_mode *dest_mode)
ir_node
*
pred
=
get_Conv_op
(
node
);
ir_mode
*
pred_mode
=
get_irn_mode
(
pred
);
if
(
!
values_in_mode
(
dest_mode
,
pred_mode
))
{
if
(
smaller_mode
(
pred_mode
,
dest_mode
))
{
return
get_conv_costs
(
get_Conv_op
(
node
),
dest_mode
)
-
1
;
}
if
(
may_leave_out_middle_conv
(
pred_mode
,
mode
,
dest_mode
))
{
return
0
;
}
else
{
return
1
;
}
return
get_conv_costs
(
get_Conv_op
(
node
),
dest_mode
)
-
1
;
}
if
(
!
is_optimizable_node
(
node
,
dest_mode
))
{
...
...
@@ -197,7 +200,6 @@ static ir_node *conv_transform(ir_node *node, ir_mode *dest_mode)
return
node
;
if
(
is_Const
(
node
))
{
/* TODO tarval module is incomplete and can't convert floats to ints */
ir_tarval
*
tv
=
conv_const_tv
(
node
,
dest_mode
);
if
(
tv
==
tarval_bad
)
{
return
place_conv
(
node
,
dest_mode
);
...
...
@@ -224,10 +226,10 @@ static ir_node *conv_transform(ir_node *node, ir_mode *dest_mode)
ir_node
*
pred
=
get_Conv_op
(
node
);
ir_mode
*
pred_mode
=
get_irn_mode
(
pred
);
if
(
!
values_in
_mode
(
dest
_mode
,
pred
_mode
))
{
return
place_conv
(
node
,
dest_mode
);
if
(
smaller
_mode
(
pred
_mode
,
dest
_mode
))
{
return
conv_transform
(
get_Conv_op
(
node
)
,
dest_mode
);
}
return
conv_transform
(
get_Conv_op
(
node
)
,
dest_mode
);
return
place_conv
(
node
,
dest_mode
);
}
if
(
!
is_optimizable_node
(
node
,
dest_mode
))
{
...
...
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