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
0d3ffb21
Commit
0d3ffb21
authored
Mar 14, 2006
by
Christian Würdig
Browse files
code cleanups
fixed some bugs added sub -> neg-add transformation in case OUT==IN2
parent
3c42b8dc
Changes
7
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
0d3ffb21
...
...
@@ -286,6 +286,7 @@ static void ia32_prepare_graph(void *self) {
/**
* Insert copies for all ia32 nodes where the should_be_same requirement
* is not fulfilled.
* Transform Sub into Neg -- Add if IN2 == OUT
*/
static
void
ia32_finish_irg_walker
(
ir_node
*
irn
,
void
*
env
)
{
ia32_code_gen_t
*
cg
=
env
;
...
...
@@ -331,6 +332,9 @@ static void ia32_finish_irg_walker(ir_node *irn, void *env) {
}
}
}
/* check if there is a sub which need to be transformed */
ia32_transform_sub_to_neg_add
(
irn
,
cg
);
}
/**
...
...
ir/be/ia32/ia32_emitter.c
View file @
0d3ffb21
...
...
@@ -44,147 +44,6 @@ extern int obstack_printf(struct obstack *obst, char *fmt, ...);
static
const
arch_env_t
*
arch_env
=
NULL
;
/**
* Emits registers and/or address mode of a binary operation.
*/
char
*
ia32_emit_binop
(
const
ir_node
*
n
)
{
static
char
*
buf
=
NULL
;
/* verify that this function is never called on non-AM supporting operations */
assert
(
get_ia32_am_support
(
n
)
!=
ia32_am_None
&&
"emit binop expects addressmode support"
);
if
(
!
buf
)
{
buf
=
xcalloc
(
1
,
SNPRINTF_BUF_LEN
);
}
else
{
memset
(
buf
,
0
,
SNPRINTF_BUF_LEN
);
}
switch
(
get_ia32_op_type
(
n
))
{
case
ia32_Normal
:
if
(
get_ia32_cnst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%3S, %s"
,
n
,
get_ia32_cnst
(
n
));
}
else
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%3S,%4S"
,
n
,
n
);
}
break
;
case
ia32_AddrModeS
:
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%4S, %s"
,
n
,
ia32_emit_am
(
n
));
break
;
case
ia32_AddrModeD
:
if
(
get_ia32_cnst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%s, %s"
,
ia32_emit_am
(
n
),
get_ia32_cnst
(
n
));
}
else
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%s, %3S"
,
ia32_emit_am
(
n
),
n
);
}
break
;
default:
assert
(
0
&&
"unsupported op type"
);
}
return
buf
;
}
/**
* Emits registers and/or address mode of a unary operation.
*/
char
*
ia32_emit_unop
(
const
ir_node
*
n
)
{
static
char
*
buf
=
NULL
;
if
(
!
buf
)
{
buf
=
xcalloc
(
1
,
SNPRINTF_BUF_LEN
);
}
else
{
memset
(
buf
,
0
,
SNPRINTF_BUF_LEN
);
}
switch
(
get_ia32_op_type
(
n
))
{
case
ia32_Normal
:
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%1D"
,
n
);
break
;
case
ia32_am_Dest
:
snprintf
(
buf
,
SNPRINTF_BUF_LEN
,
ia32_emit_am
(
n
));
break
;
default:
assert
(
0
&&
"unsupported op type"
);
}
return
buf
;
}
/**
* Emits adressmode.
*/
char
*
ia32_emit_am
(
const
ir_node
*
n
)
{
ia32_am_flavour_t
am_flav
=
get_ia32_am_flavour
(
n
);
int
had_output
=
0
;
char
*
s
;
int
size
;
static
struct
obstack
*
obst
=
NULL
;
ir_mode
*
mode
=
get_ia32_ls_mode
(
n
);
if
(
!
is_ia32_Lea
(
n
))
assert
(
mode
&&
"AM node must have ls_mode attribute set."
);
if
(
!
obst
)
{
obst
=
xcalloc
(
1
,
sizeof
(
*
obst
));
}
else
{
obstack_free
(
obst
,
NULL
);
}
/* obstack_free with NULL results in an uninitialized obstack */
obstack_init
(
obst
);
if
(
mode
)
{
switch
(
get_mode_size_bits
(
mode
))
{
case
8
:
obstack_printf
(
obst
,
"BYTE PTR "
);
break
;
case
16
:
obstack_printf
(
obst
,
"WORD PTR "
);
break
;
default:
break
;
}
}
obstack_printf
(
obst
,
"["
);
if
(
am_flav
&
ia32_B
)
{
lc_eoprintf
(
ia32_get_arg_env
(),
obst
,
"%1S"
,
n
);
had_output
=
1
;
}
if
(
am_flav
&
ia32_I
)
{
if
(
had_output
)
{
obstack_printf
(
obst
,
"+"
);
}
lc_eoprintf
(
ia32_get_arg_env
(),
obst
,
"%2S"
,
n
);
if
(
am_flav
&
ia32_S
)
{
obstack_printf
(
obst
,
"*%d"
,
1
<<
get_ia32_am_scale
(
n
));
}
had_output
=
1
;
}
if
(
am_flav
&
ia32_O
)
{
obstack_printf
(
obst
,
get_ia32_am_offs
(
n
));
}
obstack_printf
(
obst
,
"] "
);
size
=
obstack_object_size
(
obst
);
s
=
obstack_finish
(
obst
);
s
[
size
-
1
]
=
'\0'
;
return
s
;
}
/*************************************************************
* _ _ __ _ _
* (_) | | / _| | | | |
...
...
@@ -372,8 +231,159 @@ const lc_arg_env_t *ia32_get_arg_env(void) {
return
env
;
}
/**
* Emits registers and/or address mode of a binary operation.
*/
char
*
ia32_emit_binop
(
const
ir_node
*
n
)
{
static
char
*
buf
=
NULL
;
/*
/* verify that this function is never called on non-AM supporting operations */
assert
(
get_ia32_am_support
(
n
)
!=
ia32_am_None
&&
"emit binop expects addressmode support"
);
if
(
!
buf
)
{
buf
=
xcalloc
(
1
,
SNPRINTF_BUF_LEN
);
}
else
{
memset
(
buf
,
0
,
SNPRINTF_BUF_LEN
);
}
switch
(
get_ia32_op_type
(
n
))
{
case
ia32_Normal
:
if
(
get_ia32_cnst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%3S, %s"
,
n
,
get_ia32_cnst
(
n
));
}
else
{
const
arch_register_t
*
in1
=
get_in_reg
(
n
,
2
);
const
arch_register_t
*
in2
=
get_in_reg
(
n
,
3
);
const
arch_register_t
*
out
=
get_ia32_n_res
(
n
)
>
0
?
get_out_reg
(
n
,
0
)
:
NULL
;
const
arch_register_t
*
in
;
in
=
out
?
(
REGS_ARE_EQUAL
(
out
,
in2
)
?
in1
:
in2
)
:
in2
;
out
=
out
?
out
:
in1
;
snprintf
(
buf
,
SNPRINTF_BUF_LEN
,
"%s, %s"
,
\
arch_register_get_name
(
out
),
arch_register_get_name
(
in
));
}
break
;
case
ia32_AddrModeS
:
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%4S, %s"
,
n
,
ia32_emit_am
(
n
));
break
;
case
ia32_AddrModeD
:
if
(
get_ia32_cnst
(
n
))
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%s, %s"
,
ia32_emit_am
(
n
),
get_ia32_cnst
(
n
));
}
else
{
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%s, %3S"
,
ia32_emit_am
(
n
),
n
);
}
break
;
default:
assert
(
0
&&
"unsupported op type"
);
}
return
buf
;
}
/**
* Emits registers and/or address mode of a unary operation.
*/
char
*
ia32_emit_unop
(
const
ir_node
*
n
)
{
static
char
*
buf
=
NULL
;
if
(
!
buf
)
{
buf
=
xcalloc
(
1
,
SNPRINTF_BUF_LEN
);
}
else
{
memset
(
buf
,
0
,
SNPRINTF_BUF_LEN
);
}
switch
(
get_ia32_op_type
(
n
))
{
case
ia32_Normal
:
lc_esnprintf
(
ia32_get_arg_env
(),
buf
,
SNPRINTF_BUF_LEN
,
"%1D"
,
n
);
break
;
case
ia32_am_Dest
:
snprintf
(
buf
,
SNPRINTF_BUF_LEN
,
ia32_emit_am
(
n
));
break
;
default:
assert
(
0
&&
"unsupported op type"
);
}
return
buf
;
}
/**
* Emits adress mode.
*/
char
*
ia32_emit_am
(
const
ir_node
*
n
)
{
ia32_am_flavour_t
am_flav
=
get_ia32_am_flavour
(
n
);
int
had_output
=
0
;
char
*
s
;
int
size
;
static
struct
obstack
*
obst
=
NULL
;
ir_mode
*
mode
=
get_ia32_ls_mode
(
n
);
if
(
!
is_ia32_Lea
(
n
))
assert
(
mode
&&
"AM node must have ls_mode attribute set."
);
if
(
!
obst
)
{
obst
=
xcalloc
(
1
,
sizeof
(
*
obst
));
}
else
{
obstack_free
(
obst
,
NULL
);
}
/* obstack_free with NULL results in an uninitialized obstack */
obstack_init
(
obst
);
if
(
mode
)
{
switch
(
get_mode_size_bits
(
mode
))
{
case
8
:
obstack_printf
(
obst
,
"BYTE PTR "
);
break
;
case
16
:
obstack_printf
(
obst
,
"WORD PTR "
);
break
;
default:
break
;
}
}
obstack_printf
(
obst
,
"["
);
if
(
am_flav
&
ia32_B
)
{
lc_eoprintf
(
ia32_get_arg_env
(),
obst
,
"%1S"
,
n
);
had_output
=
1
;
}
if
(
am_flav
&
ia32_I
)
{
if
(
had_output
)
{
obstack_printf
(
obst
,
"+"
);
}
lc_eoprintf
(
ia32_get_arg_env
(),
obst
,
"%2S"
,
n
);
if
(
am_flav
&
ia32_S
)
{
obstack_printf
(
obst
,
"*%d"
,
1
<<
get_ia32_am_scale
(
n
));
}
had_output
=
1
;
}
if
(
am_flav
&
ia32_O
)
{
obstack_printf
(
obst
,
get_ia32_am_offs
(
n
));
}
obstack_printf
(
obst
,
"] "
);
size
=
obstack_object_size
(
obst
);
s
=
obstack_finish
(
obst
);
s
[
size
-
1
]
=
'\0'
;
return
s
;
}
/**
* Add a number to a prefix. This number will not be used a second time.
*/
static
char
*
get_unique_label
(
char
*
buf
,
size_t
buflen
,
const
char
*
prefix
)
{
...
...
@@ -383,6 +393,7 @@ static char *get_unique_label(char *buf, size_t buflen, const char *prefix) {
}
/*************************************************
* _ _ _
* (_) | | |
...
...
@@ -974,9 +985,8 @@ static void ia32_emit_node(const ir_node *irn, void *env) {
void
(
*
emit
)(
const
ir_node
*
,
void
*
)
=
(
void
(
*
)(
const
ir_node
*
,
void
*
))
op
->
ops
.
generic
;
(
*
emit
)(
irn
,
env
);
}
else
{
ir_fprintf
(
F
,
"
\t\t\t\t\t
/* %+F */
\n
"
,
irn
);
}
ir_fprintf
(
F
,
"
\t\t\t\t\t
/* %+F */
\n
"
,
irn
);
}
/**
...
...
ir/be/ia32/ia32_map_regs.h
View file @
0d3ffb21
...
...
@@ -7,6 +7,15 @@
#include "../bearch.h"
#include "ia32_nodes_attr.h"
/**
* Convenience macro to check if register <code>out<\code>
* and register <code>in<\code> are equal.
*/
#define REGS_ARE_EQUAL(out, in) \
((arch_register_get_class(out) == arch_register_get_class(in)) && \
(arch_register_get_index(out) == arch_register_get_index(in)))
int
ia32_cmp_irn_reg_assoc
(
const
void
*
a
,
const
void
*
b
,
size_t
len
);
void
ia32_set_firm_reg
(
ir_node
*
irn
,
const
arch_register_t
*
reg
,
set
*
reg_set
);
const
arch_register_t
*
ia32_get_firm_reg
(
const
ir_node
*
irn
,
set
*
reg_set
);
...
...
ir/be/ia32/ia32_optimize.c
View file @
0d3ffb21
...
...
@@ -328,6 +328,10 @@ static int pred_is_specific_nodeblock(const ir_node *bl, const ir_node *pred,
return
0
;
}
static
int
is_addr_candidate
(
const
ir_node
*
block
,
const
ir_node
*
irn
)
{
}
/**
* Checks if irn is a candidate for address calculation or address mode.
*
...
...
ir/be/ia32/ia32_spec.pl
View file @
0d3ffb21
...
...
@@ -424,7 +424,7 @@ $arch = "ia32";
"
comment
"
=>
"
construct SSE Add: Add(a, b) = Add(b, a) = a + b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
fp
",
"
fp
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A
1
, %A
2
) -> %D1 */
'
"
emit
"
=>
'
. adds%M %ia32_emit_binop\t\t\t/* SSE Add(%A
3
, %A
4
) -> %D1 */
'
},
"
fMul
"
=>
{
...
...
@@ -432,7 +432,7 @@ $arch = "ia32";
"
comment
"
=>
"
construct SSE Mul: Mul(a, b) = Mul(b, a) = a * b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
fp
",
"
fp
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A
1
, %A
2
) -> %D1 */
'
"
emit
"
=>
'
. muls%M %ia32_emit_binop\t\t\t/* SSE Mul(%A
3
, %A
4
) -> %D1 */
'
},
"
fMax
"
=>
{
...
...
@@ -440,7 +440,7 @@ $arch = "ia32";
"
comment
"
=>
"
construct SSE Max: Max(a, b) = Max(b, a) = a > b ? a : b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
fp
",
"
fp
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A
1
, %A
2
) -> %D1 */
'
"
emit
"
=>
'
. maxs%M %ia32_emit_binop\t\t\t/* SSE Max(%A
3
, %A
4
) -> %D1 */
'
},
"
fMin
"
=>
{
...
...
@@ -448,7 +448,7 @@ $arch = "ia32";
"
comment
"
=>
"
construct SSE Min: Min(a, b) = Min(b, a) = a < b ? a : b
",
"
cmp_attr
"
=>
"
return ia32_compare_immop_attr(attr_a, attr_b);
\n
",
"
reg_req
"
=>
{
"
in
"
=>
[
"
gp
",
"
gp
",
"
fp
",
"
fp
",
"
none
"
],
"
out
"
=>
[
"
in_r3 !in_r4
"
]
},
"
emit
"
=>
'
. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A
1
, %A
2
) -> %D1 */
'
"
emit
"
=>
'
. mins%M %ia32_emit_binop\t\t\t/* SSE Min(%A
3
, %A
4
) -> %D1 */
'
},
"
fAnd
"
=>
{
...
...
ir/be/ia32/ia32_transform.c
View file @
0d3ffb21
...
...
@@ -24,12 +24,15 @@
#include "debug.h"
#include "../benode_t.h"
#include "../besched.h"
#include "bearch_ia32_t.h"
#include "ia32_nodes_attr.h"
#include "../arch/archop.h"
/* we need this for Min and Max nodes */
#include "ia32_transform.h"
#include "ia32_new_nodes.h"
#include "ia32_map_regs.h"
#include "gen_ia32_regalloc_if.h"
...
...
@@ -1574,6 +1577,70 @@ static ir_node *gen_FrameStore(ia32_transform_env_t *env) {
*
*********************************************************/
/**
* Transforms a Sub or fSub into Neg--Add iff OUT_REG == SRC2_REG.
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void
ia32_transform_sub_to_neg_add
(
ir_node
*
irn
,
ia32_code_gen_t
*
cg
)
{
ia32_transform_env_t
tenv
;
ir_node
*
in1
,
*
in2
,
*
noreg
,
*
nomem
,
*
res
;
const
arch_register_t
*
in1_reg
,
*
in2_reg
,
*
out_reg
,
**
slots
;
/* Return if AM node or not a Sub or fSub */
if
(
get_ia32_op_type
(
irn
)
!=
ia32_Normal
||
!
(
is_ia32_Sub
(
irn
)
||
is_ia32_fSub
(
irn
)))
return
;
noreg
=
ia32_new_NoReg_gp
(
cg
);
nomem
=
new_rd_NoMem
(
cg
->
irg
);
in1
=
get_irn_n
(
irn
,
2
);
in2
=
get_irn_n
(
irn
,
3
);
in1_reg
=
arch_get_irn_register
(
cg
->
arch_env
,
in1
);
in2_reg
=
arch_get_irn_register
(
cg
->
arch_env
,
in2
);
out_reg
=
get_ia32_out_reg
(
irn
,
0
);
tenv
.
block
=
get_nodes_block
(
irn
);
tenv
.
dbg
=
get_irn_dbg_info
(
irn
);
tenv
.
irg
=
cg
->
irg
;
tenv
.
irn
=
irn
;
tenv
.
mod
=
cg
->
mod
;
tenv
.
mode
=
get_ia32_res_mode
(
irn
);
tenv
.
cg
=
cg
;
/* in case of sub and OUT == SRC2 we can transform the sequence into neg src2 -- add */
if
(
REGS_ARE_EQUAL
(
out_reg
,
in2_reg
))
{
/* generate the neg src2 */
res
=
gen_Minus
(
&
tenv
,
in2
);
arch_set_irn_register
(
cg
->
arch_env
,
res
,
in2_reg
);
/* add to schedule */
sched_add_before
(
irn
,
res
);
/* generate the add */
if
(
mode_is_float
(
tenv
.
mode
))
{
res
=
new_rd_ia32_fAdd
(
tenv
.
dbg
,
tenv
.
irg
,
tenv
.
block
,
noreg
,
noreg
,
res
,
in1
,
nomem
,
mode_T
);
}
else
{
res
=
new_rd_ia32_Add
(
tenv
.
dbg
,
tenv
.
irg
,
tenv
.
block
,
noreg
,
noreg
,
res
,
in1
,
nomem
,
mode_T
);
}
#ifndef NDEBUG
set_ia32_orig_node
(
res
,
get_old_node_name
(
&
tenv
));
#endif
/* NDEBUG */
/* copy register */
slots
=
get_ia32_slots
(
res
);
slots
[
0
]
=
in2_reg
;
/* add to schedule */
sched_add_before
(
irn
,
res
);
/* remove the old sub */
sched_remove
(
irn
);
/* exchange the add and the sub */
exchange
(
irn
,
res
);
}
}
/**
* Transforms the given firm node (and maybe some other related nodes)
* into one or more assembler nodes.
...
...
ir/be/ia32/ia32_transform.h
View file @
0d3ffb21
#ifndef _IA32_TRANSFORM_H_
#define _IA32_TRANSFORM_H_
/**
* Transforms the given Firm node into one or more appropriate ia32 nodes.
*/
void
ia32_transform_node
(
ir_node
*
node
,
void
*
env
);
/**
* Transforms a Sub or fSub into Neg--Add iff OUT_REG == SRC2_REG.
* THIS FUNCTIONS MUST BE CALLED AFTER REGISTER ALLOCATION.
*/
void
ia32_transform_sub_to_neg_add
(
ir_node
*
irn
,
ia32_code_gen_t
*
cg
);
#endif
/* _IA32_TRANSFORM_H_ */
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