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
0506d9b4
Commit
0506d9b4
authored
Mar 23, 2006
by
Christian Würdig
Browse files
added peephole optimization for test/cmp
parent
cbab525f
Changes
5
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
0506d9b4
...
...
@@ -487,6 +487,9 @@ static void ia32_finish_irg_walker(ir_node *irn, void *env) {
/* transform a LEA into an Add if possible */
ia32_transform_lea_to_add
(
irn
,
cg
);
/* check for peephole optimization */
ia32_peephole_optimization
(
irn
,
cg
);
}
/**
...
...
ir/be/ia32/ia32_emitter.c
View file @
0506d9b4
...
...
@@ -665,6 +665,7 @@ static void TestJmp_emitter(const ir_node *irn, ia32_emit_env_t *env) {
snprintf
(
cmd_buf
,
SNPRINTF_BUF_LEN
,
"test %%%s,%s%s "
,
op1
,
get_ia32_cnst
(
irn
)
?
" "
:
" %"
,
op2
);
lc_esnprintf
(
ia32_get_arg_env
(),
cmnt_buf
,
SNPRINTF_BUF_LEN
,
"/* %+F */"
,
irn
);
IA32_DO_EMIT
;
finish_CondJmp
(
F
,
irn
,
get_irn_mode
(
get_irn_n
(
irn
,
0
)));
}
...
...
@@ -676,7 +677,27 @@ static void emit_ia32_TestJmp(const ir_node *irn, ia32_emit_env_t *env) {
TestJmp_emitter
(
irn
,
env
);
}
static
void
emit_ia32_CJmp
(
const
ir_node
*
irn
,
ia32_emit_env_t
*
env
)
{
FILE
*
F
=
env
->
out
;
char
cmd_buf
[
SNPRINTF_BUF_LEN
];
char
cmnt_buf
[
SNPRINTF_BUF_LEN
];
snprintf
(
cmd_buf
,
SNPRINTF_BUF_LEN
,
" "
);
lc_esnprintf
(
ia32_get_arg_env
(),
cmnt_buf
,
SNPRINTF_BUF_LEN
,
"/* %+F omitted redundant test/cmp */"
,
irn
);
IA32_DO_EMIT
;
finish_CondJmp
(
F
,
irn
,
get_irn_mode
(
get_irn_n
(
irn
,
0
)));
}
static
void
emit_ia32_CJmpAM
(
const
ir_node
*
irn
,
ia32_emit_env_t
*
env
)
{
FILE
*
F
=
env
->
out
;
char
cmd_buf
[
SNPRINTF_BUF_LEN
];
char
cmnt_buf
[
SNPRINTF_BUF_LEN
];
snprintf
(
cmd_buf
,
SNPRINTF_BUF_LEN
,
" "
);
lc_esnprintf
(
ia32_get_arg_env
(),
cmnt_buf
,
SNPRINTF_BUF_LEN
,
"/* %+F omitted redundant test/cmp */"
,
irn
);
IA32_DO_EMIT
;
finish_CondJmp
(
F
,
irn
,
get_irn_mode
(
get_irn_n
(
irn
,
2
)));
}
/*********************************************************
* _ _ _
...
...
@@ -1238,6 +1259,8 @@ static void ia32_register_emitters(void) {
/* other ia32 emitter functions */
IA32_EMIT
(
CondJmp
);
IA32_EMIT
(
TestJmp
);
IA32_EMIT
(
CJmp
);
IA32_EMIT
(
CJmpAM
);
IA32_EMIT
(
SwitchJmp
);
IA32_EMIT
(
CopyB
);
IA32_EMIT
(
CopyB_i
);
...
...
ir/be/ia32/ia32_optimize.c
View file @
0506d9b4
...
...
@@ -22,6 +22,8 @@
#undef is_NoMem
#define is_NoMem(irn) (get_irn_op(irn) == op_NoMem)
typedef
int
*
is_op_func_t
(
const
ir_node
*
n
);
static
int
be_is_NoReg
(
be_abi_irg_t
*
babi
,
const
ir_node
*
irn
)
{
if
(
be_abi_get_callee_save_irn
(
babi
,
&
ia32_gp_regs
[
REG_XXX
])
==
irn
||
be_abi_get_callee_save_irn
(
babi
,
&
ia32_fp_regs
[
REG_XXXX
])
==
irn
)
...
...
@@ -32,6 +34,18 @@ static int be_is_NoReg(be_abi_irg_t *babi, const ir_node *irn) {
return
0
;
}
/*************************************************
* _____ _ _
* / ____| | | | |
* | | ___ _ __ ___| |_ __ _ _ __ | |_ ___
* | | / _ \| '_ \/ __| __/ _` | '_ \| __/ __|
* | |___| (_) | | | \__ \ || (_| | | | | |_\__ \
* \_____\___/|_| |_|___/\__\__,_|_| |_|\__|___/
*
*************************************************/
/**
* creates a unique ident by adding a number to a tag
*
...
...
@@ -226,6 +240,169 @@ void ia32_place_consts_set_modes(ir_node *irn, void *env) {
}
/********************************************************************************************************
* _____ _ _ ____ _ _ _ _ _
* | __ \ | | | | / __ \ | | (_) (_) | | (_)
* | |__) |__ ___ _ __ | |__ ___ | | ___ | | | |_ __ | |_ _ _ __ ___ _ ______ _| |_ _ ___ _ __
* | ___/ _ \/ _ \ '_ \| '_ \ / _ \| |/ _ \ | | | | '_ \| __| | '_ ` _ \| |_ / _` | __| |/ _ \| '_ \
* | | | __/ __/ |_) | | | | (_) | | __/ | |__| | |_) | |_| | | | | | | |/ / (_| | |_| | (_) | | | |
* |_| \___|\___| .__/|_| |_|\___/|_|\___| \____/| .__/ \__|_|_| |_| |_|_/___\__,_|\__|_|\___/|_| |_|
* | | | |
* |_| |_|
********************************************************************************************************/
/**
* NOTE: THESE PEEPHOLE OPTIMIZATIONS MUST BE CALLED AFTER SCHEDULING AND REGISTER ALLOCATION.
*/
static
int
ia32_cnst_compare
(
ir_node
*
n1
,
ir_node
*
n2
)
{
char
*
c1
=
get_ia32_cnst
(
n1
);
char
*
c2
=
get_ia32_cnst
(
n2
);
if
(
c1
&&
c2
)
/* both consts are set -> compare */
return
strcmp
(
c1
,
c2
)
==
0
;
else
if
(
!
c1
&&
!
c2
)
/* both consts are not set -> true */
return
1
;
return
0
;
}
/**
* Checks for potential CJmp/CJmpAM optimization candidates.
*/
static
ir_node
*
ia32_determine_cjmp_cand
(
ir_node
*
irn
,
is_op_func_t
*
is_op_func
)
{
ir_node
*
cand
=
NULL
;
ir_node
*
prev
=
sched_prev
(
irn
);
if
(
is_Block
(
prev
))
{
if
(
get_Block_n_cfgpreds
(
prev
)
==
1
)
prev
=
get_Block_cfgpred
(
prev
,
0
);
else
prev
=
NULL
;
}
/* The predecessor must be a ProjX. */
if
(
prev
&&
is_Proj
(
prev
)
&&
get_irn_mode
(
prev
)
==
mode_X
)
{
prev
=
get_Proj_pred
(
prev
);
if
(
is_op_func
(
prev
))
cand
=
prev
;
}
return
cand
;
}
static
int
is_TestJmp_cand
(
const
ir_node
*
irn
)
{
return
is_ia32_TestJmp
(
irn
)
||
is_ia32_And
(
irn
);
}
/**
* Checks if two consecutive arguments of cand matches
* the two arguments of irn (TestJmp).
*/
static
int
is_TestJmp_replacement
(
ir_node
*
cand
,
ir_node
*
irn
)
{
ir_node
*
in1
=
get_irn_n
(
irn
,
0
);
ir_node
*
in2
=
get_irn_n
(
irn
,
1
);
int
i
,
n
=
get_irn_arity
(
cand
);
int
same_args
=
0
;
char
*
c1
,
*
c2
;
for
(
i
=
0
;
i
<
n
-
1
;
i
++
)
{
if
(
get_irn_n
(
cand
,
i
)
==
in1
&&
get_irn_n
(
cand
,
i
+
1
)
==
in2
)
{
same_args
=
1
;
break
;
}
}
if
(
same_args
)
return
ia32_cnst_compare
(
cand
,
irn
);
return
0
;
}
/**
* Tries to replace a TestJmp by a CJmp or CJmpAM (in case of And)
*/
static
void
ia32_optimize_TestJmp
(
ir_node
*
irn
,
ia32_code_gen_t
*
cg
)
{
ir_node
*
cand
=
ia32_determine_cjmp_cand
(
irn
,
is_TestJmp_cand
);
int
replace
=
0
;
/* we found a possible candidate */
replace
=
cand
?
is_TestJmp_replacement
(
cand
,
irn
)
:
0
;
if
(
replace
)
{
DBG
((
cg
->
mod
,
LEVEL_1
,
"replacing %+F by "
,
irn
));
if
(
is_ia32_And
(
cand
))
set_irn_op
(
irn
,
op_ia32_CJmpAM
);
else
set_irn_op
(
irn
,
op_ia32_CJmp
);
DB
((
cg
->
mod
,
LEVEL_1
,
"%+F
\n
"
,
irn
));
}
}
static
int
is_CondJmp_cand
(
const
ir_node
*
irn
)
{
return
is_ia32_CondJmp
(
irn
)
||
is_ia32_Sub
(
irn
);
}
/**
* Checks if the arguments of cand are the same of irn.
*/
static
int
is_CondJmp_replacement
(
ir_node
*
cand
,
ir_node
*
irn
)
{
int
i
,
n
=
get_irn_arity
(
cand
);
int
same_args
=
0
;
char
*
c1
,
*
c2
;
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
get_irn_n
(
cand
,
i
)
==
get_irn_n
(
irn
,
i
))
{
same_args
=
1
;
break
;
}
}
if
(
same_args
)
return
ia32_cnst_compare
(
cand
,
irn
);
return
0
;
}
/**
* Tries to replace a CondJmp by a CJmpAM
*/
static
void
ia32_optimize_CondJmp
(
ir_node
*
irn
,
ia32_code_gen_t
*
cg
)
{
ir_node
*
cand
=
ia32_determine_cjmp_cand
(
irn
,
is_CondJmp_cand
);
int
replace
=
0
;
/* we found a possible candidate */
replace
=
cand
?
is_CondJmp_replacement
(
cand
,
irn
)
:
0
;
if
(
replace
)
{
DBG
((
cg
->
mod
,
LEVEL_1
,
"replacing %+F by "
,
irn
));
set_irn_op
(
irn
,
op_ia32_CJmp
);
DB
((
cg
->
mod
,
LEVEL_1
,
"%+F
\n
"
,
irn
));
}
}
/**
* Performs Peephole Optimizations
*/
void
ia32_peephole_optimization
(
ir_node
*
irn
,
void
*
env
)
{
if
(
is_ia32_TestJmp
(
irn
))
{
ia32_optimize_TestJmp
(
irn
,
env
);
}
else
if
(
is_ia32_CondJmp
(
irn
))
{
ia32_optimize_CondJmp
(
irn
,
env
);
}
}
/******************************************************************
* _ _ __ __ _
* /\ | | | | | \/ | | |
...
...
@@ -300,7 +477,7 @@ static ir_node *get_res_proj(const ir_node *irn) {
* @param is_op_func The check-function
* @return 1 if conditions are fulfilled, 0 otherwise
*/
static
int
pred_is_specific_node
(
const
ir_node
*
pred
,
int
(
*
is_op_func
)(
const
ir_node
*
n
)
)
{
static
int
pred_is_specific_node
(
const
ir_node
*
pred
,
is_op_func
_t
*
is_op_func
)
{
if
(
is_Proj
(
pred
)
&&
is_op_func
(
get_Proj_pred
(
pred
)))
{
return
1
;
}
...
...
ir/be/ia32/ia32_optimize.h
View file @
0506d9b4
...
...
@@ -16,4 +16,10 @@ void ia32_place_consts_set_modes(ir_node *irn, void *env);
*/
void
ia32_optimize_am
(
ir_node
*
irn
,
void
*
env
);
/**
* Performs Peephole Optimizations
* This function is called by a walker.
*/
void
ia32_peephole_optimization
(
ir_node
*
irn
,
void
*
env
);
#endif
/* _IA32_OPTIMIZE_H_ */
ir/be/ia32/ia32_spec.pl
View file @
0506d9b4
...
...
@@ -344,14 +344,28 @@ $comment_string = "/*";
"
op_flags
"
=>
"
L|X|Y
",
"
comment
"
=>
"
construct conditional jump: CMP A, B && JMPxx LABEL
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
none
",
"
none
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
gp
",
"
none
"
]
},
},
"
TestJmp
"
=>
{
"
op_flags
"
=>
"
L|X|Y
",
"
comment
"
=>
"
construct conditional jump: TEST A, B && JMPxx LABEL
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
"
],
"
out
"
=>
[
"
none
",
"
none
"
]
},
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
"
]
},
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
},
"
CJmpAM
"
=>
{
"
op_flags
"
=>
"
L|X|Y
",
"
comment
"
=>
"
construct conditional jump without CMP (replaces CondJmp): JMPxx LABEL
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
gp
",
"
gp
",
"
none
"
],
"
out
"
=>
[
"
none
",
"
none
"
]
},
},
"
CJmp
"
=>
{
"
op_flags
"
=>
"
L|X|Y
",
"
comment
"
=>
"
construct conditional jump without CMP (replaces TestJmp): JMPxx LABEL
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
"
]
},
},
"
SwitchJmp
"
=>
{
...
...
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