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
d1f02410
Commit
d1f02410
authored
May 30, 2011
by
Matthias Braun
Browse files
move integer abs optimisation from backend to the middleend
parent
630162b2
Changes
7
Hide whitespace changes
Inline
Side-by-side
ir/be/betranshlp.c
View file @
d1f02410
...
...
@@ -433,62 +433,3 @@ void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
edges_deactivate
(
irg
);
edges_activate
(
irg
);
}
int
be_mux_is_abs
(
ir_node
*
sel
,
ir_node
*
mux_true
,
ir_node
*
mux_false
)
{
ir_node
*
cmp_left
;
ir_node
*
cmp_right
;
ir_mode
*
mode
;
ir_relation
relation
;
if
(
!
is_Cmp
(
sel
))
return
0
;
/**
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
* transformations.
*/
mode
=
get_irn_mode
(
mux_true
);
if
(
mode_honor_signed_zeros
(
mode
))
return
0
;
/* must be <, <=, >=, > */
relation
=
get_Cmp_relation
(
sel
);
if
((
relation
&
ir_relation_less_greater
)
==
0
)
return
0
;
if
(
!
ir_is_negated_value
(
mux_true
,
mux_false
))
return
0
;
/* must be x cmp 0 */
cmp_right
=
get_Cmp_right
(
sel
);
if
(
!
is_Const
(
cmp_right
)
||
!
is_Const_null
(
cmp_right
))
return
0
;
cmp_left
=
get_Cmp_left
(
sel
);
if
(
cmp_left
==
mux_false
)
{
if
(
relation
&
ir_relation_less
)
{
return
1
;
}
else
{
assert
(
relation
&
ir_relation_greater
);
return
-
1
;
}
}
else
if
(
cmp_left
==
mux_true
)
{
if
(
relation
&
ir_relation_less
)
{
return
-
1
;
}
else
{
assert
(
relation
&
ir_relation_greater
);
return
1
;
}
}
return
0
;
}
ir_node
*
be_get_abs_op
(
ir_node
*
sel
)
{
ir_node
*
cmp_left
=
get_Cmp_left
(
sel
);
return
cmp_left
;
}
ir/be/betranshlp.h
View file @
d1f02410
...
...
@@ -85,12 +85,4 @@ void be_enqueue_preds(ir_node *node);
*/
void
be_transform_graph
(
ir_graph
*
irg
,
arch_pretrans_nodes
*
func
);
/**
* If Mux(sel, t, f) represents an Abs return 1, if it represents -Abs return
* -1, otherwise 0
*/
int
be_mux_is_abs
(
ir_node
*
sel
,
ir_node
*
mux_true
,
ir_node
*
mux_false
);
ir_node
*
be_get_abs_op
(
ir_node
*
sel
);
#endif
ir/be/ia32/bearch_ia32.c
View file @
d1f02410
...
...
@@ -1952,7 +1952,7 @@ static int ia32_is_mux_allowed(ir_node *sel, ir_node *mux_false,
if
(
get_mode_size_bits
(
mode
)
>
32
)
return
false
;
/* we can handle Abs for all modes and compares (except 64bit) */
if
(
be
_mux_is_abs
(
sel
,
mux_true
,
mux_false
)
!=
0
)
if
(
ir
_mux_is_abs
(
sel
,
mux_true
,
mux_false
)
!=
0
)
return
true
;
/* we can't handle MuxF yet */
if
(
mode_is_float
(
mode
))
...
...
ir/be/ia32/ia32_transform.c
View file @
d1f02410
...
...
@@ -1998,30 +1998,6 @@ static ir_node *create_abs(dbg_info *dbgi, ir_node *block, ir_node *op,
SET_IA32_ORIG_NODE
(
new_node
,
node
);
}
}
}
else
{
ir_node
*
xorn
;
ir_node
*
sign_extension
;
if
(
get_mode_size_bits
(
mode
)
==
32
)
{
new_op
=
be_transform_node
(
op
);
}
else
{
new_op
=
create_I2I_Conv
(
mode
,
mode_Is
,
dbgi
,
block
,
op
,
node
);
}
sign_extension
=
create_sex_32_64
(
dbgi
,
new_block
,
new_op
,
node
);
xorn
=
new_bd_ia32_Xor
(
dbgi
,
new_block
,
noreg_GP
,
noreg_GP
,
nomem
,
new_op
,
sign_extension
);
SET_IA32_ORIG_NODE
(
xorn
,
node
);
if
(
negate
)
{
new_node
=
new_bd_ia32_Sub
(
dbgi
,
new_block
,
noreg_GP
,
noreg_GP
,
nomem
,
sign_extension
,
xorn
);
}
else
{
new_node
=
new_bd_ia32_Sub
(
dbgi
,
new_block
,
noreg_GP
,
noreg_GP
,
nomem
,
xorn
,
sign_extension
);
}
SET_IA32_ORIG_NODE
(
new_node
,
node
);
}
return
new_node
;
...
...
@@ -3475,9 +3451,15 @@ static ir_node *gen_Mux(ir_node *node)
assert
(
get_irn_mode
(
sel
)
==
mode_b
);
is_abs
=
be
_mux_is_abs
(
sel
,
mux_true
,
mux_false
);
is_abs
=
ir
_mux_is_abs
(
sel
,
mux_true
,
mux_false
);
if
(
is_abs
!=
0
)
{
return
create_abs
(
dbgi
,
block
,
be_get_abs_op
(
sel
),
is_abs
<
0
,
node
);
if
(
ia32_mode_needs_gp_reg
(
mode
))
{
ir_fprintf
(
stderr
,
"Optimisation warning: Integer abs %+F not transformed
\n
"
,
node
);
}
else
{
ir_node
*
op
=
ir_get_abs_op
(
sel
,
mux_true
,
mux_false
);
return
create_abs
(
dbgi
,
block
,
op
,
is_abs
<
0
,
node
);
}
}
/* Note: a Mux node uses a Load two times IFF it's used in the compare AND in the result */
...
...
ir/be/sparc/sparc_transform.c
View file @
d1f02410
...
...
@@ -784,27 +784,6 @@ static ir_node *gen_Div(ir_node *node)
return
res
;
}
#if 0
static ir_node *gen_Abs(ir_node *node)
{
ir_mode *const mode = get_irn_mode(node);
if (mode_is_float(mode)) {
return gen_helper_unfpop(node, mode, new_bd_sparc_fabs_s,
new_bd_sparc_fabs_d, new_bd_sparc_fabs_q);
} else {
ir_node *const block = be_transform_node(get_nodes_block(node));
dbg_info *const dbgi = get_irn_dbg_info(node);
ir_node *const op = get_Abs_op(node);
ir_node *const new_op = be_transform_node(op);
ir_node *const sra = new_bd_sparc_Sra_imm(dbgi, block, new_op, NULL, 31);
ir_node *const xor = new_bd_sparc_Xor_reg(dbgi, block, new_op, sra);
ir_node *const sub = new_bd_sparc_Sub_reg(dbgi, block, xor, sra);
return sub;
}
}
#endif
/**
* Transforms a Not node.
*
...
...
ir/ir/iropt.c
View file @
d1f02410
...
...
@@ -5306,20 +5306,119 @@ int ir_is_negated_value(const ir_node *a, const ir_node *b)
return
false
;
}
static
const
ir_node
*
skip_upconv
(
const
ir_node
*
node
)
{
while
(
is_Conv
(
node
))
{
ir_mode
*
mode
=
get_irn_mode
(
node
);
const
ir_node
*
op
=
get_Conv_op
(
node
);
ir_mode
*
op_mode
=
get_irn_mode
(
op
);
if
(
!
smaller_mode
(
op_mode
,
mode
))
break
;
node
=
op
;
}
return
node
;
}
int
ir_mux_is_abs
(
const
ir_node
*
sel
,
const
ir_node
*
mux_true
,
const
ir_node
*
mux_false
)
{
ir_node
*
cmp_left
;
ir_node
*
cmp_right
;
ir_mode
*
mode
;
ir_relation
relation
;
if
(
!
is_Cmp
(
sel
))
return
0
;
/**
* Note further that these optimization work even for floating point
* with NaN's because -NaN == NaN.
* However, if +0 and -0 is handled differently, we cannot use the Abs/-Abs
* transformations.
*/
mode
=
get_irn_mode
(
mux_true
);
if
(
mode_honor_signed_zeros
(
mode
))
return
0
;
/* must be <, <=, >=, > */
relation
=
get_Cmp_relation
(
sel
);
if
((
relation
&
ir_relation_less_greater
)
==
0
)
return
0
;
if
(
!
ir_is_negated_value
(
mux_true
,
mux_false
))
return
0
;
mux_true
=
skip_upconv
(
mux_true
);
mux_false
=
skip_upconv
(
mux_false
);
/* must be x cmp 0 */
cmp_right
=
get_Cmp_right
(
sel
);
if
(
!
is_Const
(
cmp_right
)
||
!
is_Const_null
(
cmp_right
))
return
0
;
cmp_left
=
get_Cmp_left
(
sel
);
if
(
cmp_left
==
mux_false
)
{
if
(
relation
&
ir_relation_less
)
{
return
1
;
}
else
{
assert
(
relation
&
ir_relation_greater
);
return
-
1
;
}
}
else
if
(
cmp_left
==
mux_true
)
{
if
(
relation
&
ir_relation_less
)
{
return
-
1
;
}
else
{
assert
(
relation
&
ir_relation_greater
);
return
1
;
}
}
return
0
;
}
ir_node
*
ir_get_abs_op
(
const
ir_node
*
sel
,
ir_node
*
mux_true
,
ir_node
*
mux_false
)
{
ir_node
*
cmp_left
=
get_Cmp_left
(
sel
);
return
cmp_left
==
skip_upconv
(
mux_false
)
?
mux_false
:
mux_true
;
}
/**
* Optimize a Mux into some simpler cases.
*/
static
ir_node
*
transform_node_Mux
(
ir_node
*
n
)
{
ir_node
*
oldn
=
n
,
*
sel
=
get_Mux_sel
(
n
);
ir_mode
*
mode
=
get_irn_mode
(
n
);
ir_node
*
t
=
get_Mux_true
(
n
);
ir_node
*
f
=
get_Mux_false
(
n
);
ir_graph
*
irg
=
get_irn_irg
(
n
);
ir_node
*
oldn
=
n
;
ir_node
*
sel
=
get_Mux_sel
(
n
);
ir_mode
*
mode
=
get_irn_mode
(
n
);
ir_node
*
t
=
get_Mux_true
(
n
);
ir_node
*
f
=
get_Mux_false
(
n
);
ir_graph
*
irg
=
get_irn_irg
(
n
);
if
(
is_irg_state
(
irg
,
IR_GRAPH_STATE_KEEP_MUX
))
return
n
;
/* implement integer abs: abs(x) = x^(x >>s 31) - (x >>s 31) */
if
(
get_mode_arithmetic
(
mode
)
==
irma_twos_complement
)
{
int
abs
=
ir_mux_is_abs
(
sel
,
t
,
f
);
if
(
abs
!=
0
)
{
dbg_info
*
dbgi
=
get_irn_dbg_info
(
n
);
ir_node
*
block
=
get_nodes_block
(
n
);
ir_node
*
op
=
ir_get_abs_op
(
sel
,
t
,
f
);
int
bits
=
get_mode_size_bits
(
mode
);
ir_node
*
shiftconst
=
new_r_Const_long
(
irg
,
mode_Iu
,
bits
-
1
);
ir_node
*
sext
=
new_rd_Shrs
(
dbgi
,
block
,
op
,
shiftconst
,
mode
);
ir_node
*
xorn
=
new_rd_Eor
(
dbgi
,
block
,
op
,
sext
,
mode
);
ir_node
*
res
;
if
(
abs
>
0
)
{
res
=
new_rd_Sub
(
dbgi
,
block
,
xorn
,
sext
,
mode
);
}
else
{
res
=
new_rd_Sub
(
dbgi
,
block
,
sext
,
xorn
,
mode
);
}
return
res
;
}
}
if
(
is_Mux
(
t
))
{
ir_node
*
block
=
get_nodes_block
(
n
);
ir_node
*
c0
=
sel
;
...
...
ir/ir/iropt_t.h
View file @
d1f02410
...
...
@@ -136,4 +136,10 @@ bool ir_zero_when_converted(const ir_node *node, ir_mode *dest_mode);
*/
ir_op_ops
*
firm_set_default_operations
(
unsigned
code
,
ir_op_ops
*
ops
);
int
ir_mux_is_abs
(
const
ir_node
*
sel
,
const
ir_node
*
mux_true
,
const
ir_node
*
mux_false
);
ir_node
*
ir_get_abs_op
(
const
ir_node
*
sel
,
ir_node
*
mux_true
,
ir_node
*
mux_false
);
#endif
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