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
4908bfb8
Commit
4908bfb8
authored
Nov 22, 2014
by
Christoph Mallon
Browse files
ia32: Use fdup instead of fpush.
This properly models the data dependencies and avoids keep edges.
parent
9a8dd92f
Changes
4
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/ia32_emitter.c
View file @
4908bfb8
...
...
@@ -3065,11 +3065,6 @@ static void bemit_fpop(const ir_node *node)
bemit_fop_reg
(
node
,
0xDD
,
0xD8
);
}
static
void
bemit_fpush
(
const
ir_node
*
node
)
{
bemit_fop_reg
(
node
,
0xD9
,
0xC0
);
}
static
void
bemit_fdup
(
const
ir_node
*
node
)
{
bemit_fop_reg
(
node
,
0xD9
,
0xC0
);
...
...
@@ -3250,7 +3245,6 @@ static void ia32_register_binary_emitters(void)
be_set_emitter
(
op_ia32_fldz
,
bemit_fldz
);
be_set_emitter
(
op_ia32_fmul
,
bemit_fmul
);
be_set_emitter
(
op_ia32_fpop
,
bemit_fpop
);
be_set_emitter
(
op_ia32_fpush
,
bemit_fpush
);
be_set_emitter
(
op_ia32_fdup
,
bemit_fdup
);
be_set_emitter
(
op_ia32_fst
,
bemit_fst
);
be_set_emitter
(
op_ia32_fsub
,
bemit_fsub
);
...
...
ir/be/ia32/ia32_new_nodes.c
View file @
4908bfb8
...
...
@@ -97,7 +97,6 @@ static bool has_ia32_x87_attr(ir_node const *const node)
case
iro_ia32_fisttp
:
case
iro_ia32_fmul
:
case
iro_ia32_fpop
:
case
iro_ia32_fpush
:
case
iro_ia32_fst
:
case
iro_ia32_fsub
:
case
iro_ia32_fxch
:
...
...
ir/be/ia32/ia32_spec.pl
View file @
4908bfb8
...
...
@@ -2065,7 +2065,7 @@ Sahf => {
mode
=>
$mode_flags
,
},
# fxch, f
push
, fpop
# fxch, f
dup
, fpop
# Note that it is NEVER allowed to do CSE on these nodes
# Moreover, note the virtual register requierements!
...
...
@@ -2079,16 +2079,6 @@ fxch => {
latency
=>
1
,
},
fpush
=>
{
op_flags
=>
[
"
keep
"
],
reg_req
=>
{
out
=>
[
"
none
"
]
},
attrs_equal
=>
"
attrs_equal_false
",
emit
=>
"
fld %F0
",
attr_type
=>
"
ia32_x87_attr_t
",
mode
=>
"
mode_ANY
",
latency
=>
1
,
},
fdup
=>
{
reg_req
=>
{
in
=>
[
"
fp
"
],
out
=>
[
"
fp
"
]
},
ins
=>
[
"
val
"
],
...
...
ir/be/ia32/ia32_x87.c
View file @
4908bfb8
...
...
@@ -433,26 +433,31 @@ static x87_state *x87_shuffle(ir_node *block, x87_state *state, const x87_state
return
state
;
}
static
ir_node
*
x87_create_fdup
(
x87_state
*
const
state
,
ir_node
*
const
block
,
ir_node
*
const
val
,
arch_register_t
const
*
const
out
)
{
ir_node
*
const
fdup
=
new_bd_ia32_fdup
(
NULL
,
block
,
val
);
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
fdup
);
unsigned
const
pos
=
x87_on_stack_val
(
state
,
val
);
attr
->
reg
=
get_st_reg
(
pos
);
arch_set_irn_register
(
fdup
,
out
);
x87_push
(
state
,
out
->
index
,
fdup
);
DB
((
dbg
,
LEVEL_1
,
"<<< %s %s
\n
"
,
get_irn_opname
(
fdup
),
attr
->
reg
->
name
));
return
fdup
;
}
/**
* Create a f
push
before node n.
* Create a
n
f
dup
before node
@p n replacing operand @p op_
n.
*
* @param state the x87 state
* @param n the node after the f
push
* @param val the value to
push
* @param n the node after the f
dup
* @param val the value to
duplicate
*/
static
void
x87_
create_fpush
(
x87_state
*
const
state
,
ir_node
*
const
n
,
unsigned
const
o
ut_reg_idx
,
ir_node
*
const
val
)
static
void
x87_
dup_operand
(
x87_state
*
const
state
,
ir_node
*
const
n
,
unsigned
const
o
p_n
,
ir_node
*
const
val
,
arch_register_t
const
*
const
out
)
{
x87_push
(
state
,
out_reg_idx
,
val
);
ir_node
*
const
fpush
=
new_bd_ia32_fpush
(
NULL
,
get_nodes_block
(
n
));
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
fpush
);
unsigned
const
pos
=
x87_on_stack_val
(
state
,
val
);
attr
->
reg
=
get_st_reg
(
pos
);
keep_alive
(
fpush
);
sched_add_before
(
n
,
fpush
);
DB
((
dbg
,
LEVEL_1
,
"<<< %s %s
\n
"
,
get_irn_opname
(
fpush
),
attr
->
reg
->
name
));
ir_node
*
const
block
=
get_nodes_block
(
n
);
ir_node
*
const
fdup
=
x87_create_fdup
(
state
,
block
,
val
,
out
);
sched_add_before
(
n
,
fdup
);
set_irn_n
(
n
,
op_n
,
fdup
);
}
/**
...
...
@@ -636,9 +641,8 @@ static void sim_binop(x87_state *const state, ir_node *const n)
unsigned
op2_idx
;
unsigned
out_idx
;
bool
pop
=
false
;
unsigned
const
out_reg_idx
=
out
->
index
;
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
n
);
bool
pop
=
false
;
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
n
);
if
(
reg_index_2
!=
REG_FP_FP_NOREG
)
{
/* second operand is a fp register */
op2_idx
=
x87_on_stack
(
state
,
reg_index_2
);
...
...
@@ -651,7 +655,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
if
(
op1_live_after
)
{
/* Both operands are live: push the first one.
* This works even for op1 == op2. */
x87_
create_fpush
(
state
,
n
,
out_reg_idx
,
op1
);
x87_
dup_operand
(
state
,
n
,
n_ia32_binary_left
,
op1
,
out
);
/* now do fxxx (tos=tos X op) */
op1_idx
=
0
;
op2_idx
+=
1
;
...
...
@@ -707,7 +711,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
/* second operand is an address mode */
if
(
op1_live_after
)
{
/* first operand is live: push it here */
x87_
create_fpush
(
state
,
n
,
out_reg_idx
,
op1
);
x87_
dup_operand
(
state
,
n
,
n_ia32_binary_left
,
op1
,
out
);
}
else
{
/* first operand is dead: bring it to tos */
if
(
op1_idx
!=
0
)
...
...
@@ -721,7 +725,7 @@ static void sim_binop(x87_state *const state, ir_node *const n)
assert
(
op1_idx
==
0
||
op2_idx
==
0
);
assert
(
out_idx
==
op1_idx
||
out_idx
==
op2_idx
);
x87_set_st
(
state
,
out
_reg_id
x
,
n
,
out_idx
);
x87_set_st
(
state
,
out
->
inde
x
,
n
,
out_idx
);
if
(
pop
)
x87_pop
(
state
);
...
...
@@ -756,10 +760,9 @@ static void sim_unop(x87_state *state, ir_node *n)
ir_node
*
const
op1
=
get_irn_n
(
n
,
0
);
arch_register_t
const
*
const
op1_reg
=
arch_get_irn_register
(
op1
);
unsigned
const
op1_reg_idx
=
op1_reg
->
index
;
unsigned
const
out_reg_idx
=
out
->
index
;
if
(
is_fp_live
(
op1_reg_idx
,
live
))
{
/* push the operand here */
x87_
create_fpush
(
state
,
n
,
out_reg_idx
,
op1
);
x87_
dup_operand
(
state
,
n
,
0
,
op1
,
out
);
}
else
{
/* operand is dead, bring it to tos */
unsigned
const
op1_idx
=
x87_on_stack
(
state
,
op1_reg_idx
);
...
...
@@ -767,7 +770,7 @@ static void sim_unop(x87_state *state, ir_node *n)
x87_create_fxch
(
state
,
n
,
op1_idx
);
}
x87_set_st
(
state
,
out
_reg_id
x
,
n
,
0
);
x87_set_st
(
state
,
out
->
inde
x
,
n
,
0
);
DB
((
dbg
,
LEVEL_1
,
"<<< %s -> %s
\n
"
,
get_irn_opname
(
n
),
get_st_reg
(
0
)
->
name
));
}
...
...
@@ -820,7 +823,8 @@ static void sim_store(x87_state *state, ir_node *n)
if
(
get_mode_size_bits
(
mode
)
>
(
mode_is_int
(
mode
)
?
32U
:
64U
))
{
if
(
x87_get_depth
(
state
)
<
N_FLOAT_REGS
)
{
/* ok, we have a free register: push + fstp */
x87_create_fpush
(
state
,
n
,
REG_FP_FP_NOREG
,
val
);
arch_register_t
const
*
const
out
=
get_st_reg
(
REG_FP_FP_NOREG
);
x87_dup_operand
(
state
,
n
,
n_ia32_fst_val
,
val
,
out
);
do_pop:
x87_pop
(
state
);
}
else
{
...
...
@@ -1097,24 +1101,19 @@ static void sim_Copy(x87_state *state, ir_node *n)
DEBUG_ONLY
(
fp_dump_live
(
live
);)
if
(
is_fp_live
(
op1
->
index
,
live
))
{
/* Operand is still live, a real copy.
We need here an fpush that can
*
hold a a register, so u
se a fdup or recreate constants. */
/* Operand is still live, a real copy.
*
U
se a
n
fdup or recreate constants. */
ir_node
*
copy
;
ir_node
*
const
block
=
get_nodes_block
(
n
);
if
(
is_irn_constlike
(
pred
))
{
/* Copy a constant. */
copy
=
exact_copy
(
pred
);
set_nodes_block
(
copy
,
block
);
x87_push
(
state
,
out
->
index
,
copy
);
arch_set_irn_register
(
copy
,
out
);
}
else
{
dbg_info
*
const
dbgi
=
get_irn_dbg_info
(
n
);
copy
=
new_bd_ia32_fdup
(
dbgi
,
block
,
pred
);
ia32_x87_attr_t
*
const
attr
=
get_ia32_x87_attr
(
copy
);
unsigned
const
op1_idx
=
x87_on_stack_val
(
state
,
pred
);
attr
->
reg
=
get_st_reg
(
op1_idx
);
copy
=
x87_create_fdup
(
state
,
block
,
pred
,
out
);
}
x87_push
(
state
,
out
->
index
,
copy
);
arch_set_irn_register
(
copy
,
out
);
sched_replace
(
n
,
copy
);
exchange
(
n
,
copy
);
...
...
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