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
277830bf
Commit
277830bf
authored
Sep 30, 2007
by
Matthias Braun
Browse files
- first real peephole optimisation mov 0, reg -> xor reg, reg when we don't
care about flags - fixed some bugs in bepeephole [r16013]
parent
28337840
Changes
6
Hide whitespace changes
Inline
Side-by-side
ir/be/bepeephole.c
View file @
277830bf
...
...
@@ -19,14 +19,16 @@
/**
* @file
* @brief
modifies schedule so flags dependencies are respected.
* @author Matthias Braun
, Christoph Mallon
* @brief
Peephole optimisation framework keeps track of which registers contain which values
* @author Matthias Braun
* @version $Id$
*/
#ifdef HAVE_CONFIG_H
#include
"config.h"
#endif
#include
"bepeephole.h"
#include
"iredges_t.h"
#include
"irgwalk.h"
#include
"irprintf.h"
...
...
@@ -38,8 +40,8 @@
#include
"besched_t.h"
static
const
arch_env_t
*
arch_env
;
static
const
be_lv_t
*
lv
;
ir_node
***
register_values
;
static
be_lv_t
*
lv
;
ir_node
***
register_values
;
static
void
clear_value
(
ir_node
*
node
)
{
...
...
@@ -61,6 +63,7 @@ static void clear_value(ir_node *node)
reg_idx
=
arch_register_get_index
(
reg
);
cls_idx
=
arch_register_class_index
(
cls
);
//assert(register_values[cls_idx][reg_idx] != NULL);
register_values
[
cls_idx
][
reg_idx
]
=
NULL
;
}
...
...
@@ -93,10 +96,8 @@ static void set_value(ir_node *node)
register_values
[
cls_idx
][
reg_idx
]
=
node
;
}
static
void
advance
(
ir_node
*
node
)
static
void
clear_defs
(
ir_node
*
node
)
{
int
i
,
arity
;
/* clear values defined */
if
(
get_irn_mode
(
node
)
==
mode_T
)
{
const
ir_edge_t
*
edge
;
...
...
@@ -107,6 +108,11 @@ static void advance(ir_node *node)
}
else
{
clear_value
(
node
);
}
}
static
void
set_uses
(
ir_node
*
node
)
{
int
i
,
arity
;
/* set values used */
arity
=
get_irn_arity
(
node
);
...
...
@@ -140,11 +146,28 @@ static void process_block(ir_node *block, void *data)
}
/* walk the block */
sched_foreach_reverse
(
block
,
node
)
{
node
=
sched_last
(
block
);
for
(
;
!
sched_is_begin
(
node
);
node
=
sched_prev
(
node
))
{
ir_op
*
op
;
peephole_opt_func
func
;
if
(
is_Phi
(
node
))
break
;
advance
(
node
);
clear_defs
(
node
);
set_uses
(
node
);
op
=
get_irn_op
(
node
);
func
=
(
peephole_opt_func
)
op
->
ops
.
generic
;
if
(
func
!=
NULL
)
{
ir_node
*
new_node
=
func
(
node
);
if
(
new_node
!=
NULL
&&
new_node
!=
node
)
{
be_liveness_remove
(
lv
,
node
);
be_liveness_introduce
(
lv
,
new_node
);
node
=
new_node
;
set_uses
(
node
);
}
}
}
}
...
...
@@ -174,3 +197,8 @@ void be_peephole_opt(be_irg_t *birg)
irg_block_walk_graph
(
irg
,
process_block
,
NULL
,
NULL
);
}
void
be_peephole_init
(
void
)
{
clear_irp_opcodes_generic_func
();
}
ir/be/bepeephole.h
View file @
277830bf
/*
* Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
*
* This file is part of libFirm.
*
* This file may be distributed and/or modified under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation and appearing in the file LICENSE.GPL included in the
* packaging of this file.
*
* Licensees holding valid libFirm Professional Edition licenses may use
* this file in accordance with the libFirm Commercial License.
* Agreement provided with the Software.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**
* @file
* @brief peephole optimisation framework
* @author Matthias Braun
* @version $Id$
*/
#ifndef BEPEEPHOLE_H
#define BEPEEPHOLE_H
#include
"beirg.h"
#include
"bearch_t.h"
extern
ir_node
***
register_values
;
static
inline
ir_node
*
get_value
_in_reg
(
unsigned
regclass_idx
,
unsigned
register_idx
)
static
inline
ir_node
*
be_peephole_
get_value
(
unsigned
regclass_idx
,
unsigned
register_idx
)
{
return
register_values
[
regclass_idx
][
register_idx
];
}
static
inline
ir_node
*
be_peephole_get_reg_value
(
const
arch_register_t
*
reg
)
{
unsigned
regclass_idx
=
arch_register_class_index
(
arch_register_get_class
(
reg
));
unsigned
register_idx
=
arch_register_get_index
(
reg
);
return
be_peephole_get_value
(
regclass_idx
,
register_idx
);
}
typedef
ir_node
*
(
*
peephole_opt_func
)
(
ir_node
*
node
);
/**
* Do peephole optimisations, works backwards over blockschedules and calls the generic op handler function
* which should be of type peephole_opt_func. The values of the values in the registers are availble
* in the register_values variable during the optimisation functions.
*/
void
be_peephole_opt
(
be_irg_t
*
birg
);
#endif
ir/be/ia32/ia32_emitter.c
View file @
277830bf
...
...
@@ -1621,21 +1621,10 @@ static void emit_be_Perm(const ir_node *node)
*/
static
void
emit_ia32_Const
(
const
ir_node
*
node
)
{
const
ia32_immediate_attr_t
*
attr
=
get_ia32_immediate_attr_const
(
node
);
/* a zero? */
if
(
attr
->
symconst
==
NULL
&&
attr
->
offset
==
0
)
{
assert
(
get_ia32_flags
(
node
)
&
arch_irn_flags_modify_flags
);
be_emit_cstring
(
"
\t
xorl "
);
ia32_emit_dest_register
(
node
,
0
);
be_emit_cstring
(
", "
);
ia32_emit_dest_register
(
node
,
0
);
}
else
{
be_emit_cstring
(
"
\t
movl "
);
emit_ia32_Immediate
(
node
);
be_emit_cstring
(
", "
);
ia32_emit_dest_register
(
node
,
0
);
}
be_emit_cstring
(
"
\t
movl "
);
emit_ia32_Immediate
(
node
);
be_emit_cstring
(
", "
);
ia32_emit_dest_register
(
node
,
0
);
be_emit_finish_line_gas
(
node
);
}
...
...
ir/be/ia32/ia32_optimize.c
View file @
277830bf
...
...
@@ -54,6 +54,9 @@
DEBUG_ONLY
(
static
firm_dbg_module_t
*
dbg
=
NULL
;)
static
const
arch_env_t
*
arch_env
;
static
ia32_code_gen_t
*
cg
;
typedef
int
is_op_func_t
(
const
ir_node
*
n
);
typedef
ir_node
*
load_func_t
(
dbg_info
*
db
,
ir_graph
*
irg
,
ir_node
*
block
,
ir_node
*
base
,
ir_node
*
index
,
ir_node
*
mem
);
...
...
@@ -85,7 +88,8 @@ static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
/**
* Tries to create pushs from IncSP,Store combinations
*/
static
void
ia32_create_Pushs
(
ir_node
*
irn
,
ia32_code_gen_t
*
cg
)
{
static
void
ia32_create_Pushs
(
ir_node
*
irn
)
{
int
i
;
int
offset
;
ir_node
*
node
;
...
...
@@ -265,32 +269,75 @@ static void ia32_optimize_IncSP(ir_node *node)
/**
* Performs Peephole Optimizations.
*/
static
void
ia32_peephole_optimize_node
(
ir_node
*
node
,
void
*
env
)
{
ia32_code_gen_t
*
cg
=
env
;
static
void
ia32_peephole_optimize_node
(
ir_node
*
node
,
void
*
env
)
{
(
void
)
env
;
if
(
be_is_IncSP
(
node
))
{
ia32_optimize_IncSP
(
node
);
if
(
cg
->
opt
&
IA32_OPT_PUSHARGS
)
ia32_create_Pushs
(
node
,
cg
);
ia32_create_Pushs
(
node
);
}
}
void
ia32_peephole_optimization
(
ir_graph
*
irg
,
ia32_code_gen_t
*
cg
)
static
ir_node
*
optimize_ia32_Const
(
ir_node
*
node
)
{
be_peephole_opt
(
cg
->
birg
);
irg_walk_graph
(
irg
,
ia32_peephole_optimize_node
,
NULL
,
cg
);
const
ia32_immediate_attr_t
*
attr
=
get_ia32_immediate_attr_const
(
node
);
const
arch_register_t
*
reg
;
ir_graph
*
irg
=
current_ir_graph
;
ir_node
*
block
;
dbg_info
*
dbgi
;
ir_node
*
produceval
;
ir_node
*
xor
;
ir_node
*
noreg
;
/* try to transform a mov 0, reg to xor reg reg */
if
(
attr
->
offset
!=
0
||
attr
->
symconst
!=
NULL
)
return
NULL
;
/* xor destroys the flags, so noone must be using them */
if
(
be_peephole_get_value
(
CLASS_ia32_flags
,
REG_EFLAGS
)
!=
NULL
)
return
NULL
;
reg
=
arch_get_irn_register
(
arch_env
,
node
);
assert
(
be_peephole_get_reg_value
(
reg
)
==
NULL
);
/* create xor(produceval, produceval) */
block
=
get_nodes_block
(
node
);
dbgi
=
get_irn_dbg_info
(
node
);
produceval
=
new_rd_ia32_ProduceVal
(
dbgi
,
irg
,
block
);
arch_set_irn_register
(
arch_env
,
produceval
,
reg
);
noreg
=
ia32_new_NoReg_gp
(
cg
);
xor
=
new_rd_ia32_Xor
(
dbgi
,
irg
,
block
,
noreg
,
noreg
,
new_NoMem
(),
produceval
,
produceval
);
arch_set_irn_register
(
arch_env
,
xor
,
reg
);
sched_add_before
(
node
,
produceval
);
sched_add_before
(
node
,
xor
);
exchange
(
node
,
xor
);
sched_remove
(
node
);
return
xor
;
}
/******************************************************************
* _ _ __ __ _
* /\ | | | | | \/ | | |
* / \ __| | __| |_ __ ___ ___ ___| \ / | ___ __| | ___
* / /\ \ / _` |/ _` | '__/ _ \/ __/ __| |\/| |/ _ \ / _` |/ _ \
* / ____ \ (_| | (_| | | | __/\__ \__ \ | | | (_) | (_| | __/
* /_/ \_\__,_|\__,_|_| \___||___/___/_| |_|\___/ \__,_|\___|
*
******************************************************************/
static
void
register_peephole_optimisation
(
ir_op
*
op
,
peephole_opt_func
func
)
{
assert
(
op
->
ops
.
generic
==
NULL
);
op
->
ops
.
generic
=
(
void
*
)
func
;
}
void
ia32_peephole_optimization
(
ir_graph
*
irg
,
ia32_code_gen_t
*
new_cg
)
{
cg
=
new_cg
;
arch_env
=
cg
->
arch_env
;
/* register peephole optimisations */
clear_irp_opcodes_generic_func
();
register_peephole_optimisation
(
op_ia32_Const
,
optimize_ia32_Const
);
be_peephole_opt
(
cg
->
birg
);
irg_walk_graph
(
irg
,
ia32_peephole_optimize_node
,
NULL
,
NULL
);
}
/**
* Removes node from schedule if it is not used anymore. If irn is a mode_T node
...
...
ir/be/ia32/ia32_transform.c
View file @
277830bf
...
...
@@ -330,10 +330,6 @@ static ir_node *gen_Const(ir_node *node) {
cnst
=
new_rd_ia32_Const
(
dbgi
,
irg
,
block
,
NULL
,
0
,
val
);
SET_IA32_ORIG_NODE
(
cnst
,
ia32_get_old_node_name
(
env_cg
,
node
));
if
(
val
==
0
)
{
set_ia32_flags
(
cnst
,
get_ia32_flags
(
cnst
)
|
arch_irn_flags_modify_flags
);
}
/* see above */
if
(
get_irg_start_block
(
irg
)
==
block
)
{
...
...
ir/be/ia32/ia32_transform.h
View file @
277830bf
...
...
@@ -36,7 +36,7 @@ typedef struct {
int
use_sse2
;
/** use ffreep instead of fpop */
int
use_ffreep
;
/** use ftst
instead of compar
e */
/** use ftst
where possibl
e */
int
use_ftst
;
/** use femms to pop all float registers */
int
use_femms
;
...
...
Write
Preview
Supports
Markdown
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