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
e787df99
Commit
e787df99
authored
Jun 15, 2007
by
Matthias Braun
Browse files
psi transform and emit logical rewritten from scratch
[r14513]
parent
11107302
Changes
10
Hide whitespace changes
Inline
Side-by-side
ir/be/ia32/bearch_ia32.c
View file @
e787df99
...
...
@@ -867,17 +867,10 @@ ia32_irn_ops_t ia32_irn_ops = {
static
void
ia32_prepare_graph
(
void
*
self
)
{
ia32_code_gen_t
*
cg
=
self
;
/* transform psi condition trees */
ia32_pre_transform_phase
(
cg
);
/* transform all remaining nodes */
/* transform nodes into assembler instructions */
ia32_transform_graph
(
cg
);
//add_fpu_edges(cg->birg);
// Matze: disabled for now. Because after transformation start block has no
// self-loop anymore so it might be merged with its successor block. This
// will bring several nodes to the startblock which sometimes get scheduled
// before the initial IncSP/Barrier
/* do local optimisations (mainly CSE) */
local_optimize_graph
(
cg
->
irg
);
if
(
cg
->
dump
)
...
...
ir/be/ia32/ia32_emitter.c
View file @
e787df99
...
...
@@ -930,25 +930,58 @@ void emit_ia32_x87CondJmp(ia32_emit_env_t *env, const ir_node *node) {
finish_CondJmp
(
env
,
node
,
mode_E
,
pnc
);
}
static
void
emit_register_or_immediate
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
int
pos
)
{
ir_node
*
op
=
get_irn_n
(
node
,
pos
);
if
(
is_ia32_Immediate
(
op
))
{
emit_ia32_Immediate
(
env
,
op
);
}
else
{
ia32_emit_source_register
(
env
,
node
,
pos
);
}
}
static
int
is_ia32_Immediate_0
(
const
ir_node
*
node
)
{
const
ia32_immediate_attr_t
*
attr
=
get_ia32_immediate_attr_const
(
node
);
tarval
*
tv
=
attr
->
offset
;
if
(
tv
==
NULL
||
attr
->
symconst
!=
NULL
)
return
0
;
return
classify_tarval
(
tv
)
==
CNST_NULL
;
}
static
void
CMov_emitter
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
long
pnc
=
get_ia32_pncode
(
node
);
int
is_PsiCondCMov
=
is_ia32_PsiCondCMov
(
node
);
int
idx_left
=
2
-
is_PsiCondCMov
;
int
idx_right
=
3
-
is_PsiCondCMov
;
const
arch_register_t
*
in1
,
*
in2
,
*
out
;
out
=
arch_get_irn_register
(
env
->
arch_env
,
node
);
in1
=
arch_get_irn_register
(
env
->
arch_env
,
get_irn_n
(
node
,
idx_left
));
in2
=
arch_get_irn_register
(
env
->
arch_env
,
get_irn_n
(
node
,
idx_right
));
in1
=
arch_get_irn_register
(
env
->
arch_env
,
get_irn_n
(
node
,
2
));
in2
=
arch_get_irn_register
(
env
->
arch_env
,
get_irn_n
(
node
,
3
));
/* we have to emit the cmp first, because the destination register */
/* could be one of the compare registers */
if
(
is_ia32_CmpCMov
(
node
))
{
be_emit_cstring
(
env
,
"
\t
cmp "
);
ia32_emit_source_register
(
env
,
node
,
1
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
0
);
long
pncr
=
pnc
&
~
ia32_pn_Cmp_Unsigned
;
ir_node
*
cmp_right
=
get_irn_n
(
node
,
1
);
if
(
(
pncr
==
pn_Cmp_Eq
||
pncr
==
pn_Cmp_Lg
)
&&
is_ia32_Immediate
(
cmp_right
)
&&
is_ia32_Immediate_0
(
cmp_right
))
{
be_emit_cstring
(
env
,
"
\t
test "
);
ia32_emit_source_register
(
env
,
node
,
0
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
0
);
}
else
{
be_emit_cstring
(
env
,
"
\t
cmp "
);
emit_register_or_immediate
(
env
,
node
,
1
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
0
);
}
}
else
if
(
is_ia32_xCmpCMov
(
node
))
{
be_emit_cstring
(
env
,
"
\t
ucomis"
);
ia32_emit_mode_suffix_mode
(
env
,
get_irn_mode
(
node
));
...
...
@@ -956,12 +989,6 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
ia32_emit_source_register
(
env
,
node
,
1
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
0
);
}
else
if
(
is_PsiCondCMov
)
{
/* omit compare because flags are already set by And/Or */
be_emit_cstring
(
env
,
"
\t
test "
);
ia32_emit_source_register
(
env
,
node
,
0
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
0
);
}
else
{
assert
(
0
&&
"unsupported CMov"
);
}
...
...
@@ -972,42 +999,26 @@ void CMov_emitter(ia32_emit_env_t *env, const ir_node *node) {
}
else
if
(
REGS_ARE_EQUAL
(
out
,
in1
))
{
ir_node
*
n
=
(
ir_node
*
)
node
;
/* true in == out -> need complement compare and exchange true and default in */
ir_node
*
t
=
get_irn_n
(
n
,
idx_left
);
set_irn_n
(
n
,
idx_left
,
get_irn_n
(
n
,
idx_right
));
set_irn_n
(
n
,
idx_right
,
t
);
ir_node
*
t
=
get_irn_n
(
n
,
2
);
set_irn_n
(
n
,
2
,
get_irn_n
(
n
,
3
));
set_irn_n
(
n
,
3
,
t
);
pnc
=
get_negated_pnc
(
pnc
,
get_irn_mode
(
node
));
}
else
{
/* out is different from in: need copy default -> out */
if
(
is_PsiCondCMov
)
{
be_emit_cstring
(
env
,
"
\t
movl "
);
ia32_emit_dest_register
(
env
,
node
,
2
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_dest_register
(
env
,
node
,
0
);
}
else
{
be_emit_cstring
(
env
,
"
\t
movl "
);
ia32_emit_source_register
(
env
,
node
,
3
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_dest_register
(
env
,
node
,
0
);
}
be_emit_finish_line_gas
(
env
,
node
);
}
if
(
is_PsiCondCMov
)
{
be_emit_cstring
(
env
,
"
\t
cmov"
);
ia32_emit_cmp_suffix
(
env
,
pnc
);
be_emit_cstring
(
env
,
"l "
);
ia32_emit_source_register
(
env
,
node
,
1
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_dest_register
(
env
,
node
,
0
);
}
else
{
be_emit_cstring
(
env
,
"
\t
cmov"
);
ia32_emit_cmp_suffix
(
env
,
pnc
);
be_emit_cstring
(
env
,
"l "
);
ia32_emit_source_register
(
env
,
node
,
2
);
be_emit_cstring
(
env
,
"
\t
movl "
);
ia32_emit_source_register
(
env
,
node
,
3
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_dest_register
(
env
,
node
,
0
);
be_emit_finish_line_gas
(
env
,
node
);
}
be_emit_cstring
(
env
,
"
\t
cmov"
);
ia32_emit_cmp_suffix
(
env
,
pnc
);
be_emit_cstring
(
env
,
"l "
);
ia32_emit_source_register
(
env
,
node
,
2
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_dest_register
(
env
,
node
,
0
);
be_emit_finish_line_gas
(
env
,
node
);
}
...
...
@@ -1016,11 +1027,6 @@ void emit_ia32_CmpCMov(ia32_emit_env_t *env, const ir_node *node) {
CMov_emitter
(
env
,
node
);
}
static
void
emit_ia32_PsiCondCMov
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
CMov_emitter
(
env
,
node
);
}
static
void
emit_ia32_xCmpCMov
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
CMov_emitter
(
env
,
node
);
...
...
@@ -1028,7 +1034,7 @@ void emit_ia32_xCmpCMov(ia32_emit_env_t *env, const ir_node *node) {
static
void
Set_emitter
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
,
ir_mode
*
mode
)
{
int
pnc
=
get_ia32_pncode
(
node
);
long
pnc
=
get_ia32_pncode
(
node
);
const
char
*
reg8bit
;
const
arch_register_t
*
out
;
...
...
@@ -1036,16 +1042,25 @@ void Set_emitter(ia32_emit_env_t *env, const ir_node *node, ir_mode *mode) {
reg8bit
=
ia32_get_mapped_reg_name
(
env
->
isa
->
regs_8bit
,
out
);
if
(
is_ia32_CmpSet
(
node
))
{
be_emit_cstring
(
env
,
"
\t
cmp "
);
ia32_emit_binop
(
env
,
node
);
long
pncr
=
pnc
&
~
ia32_pn_Cmp_Unsigned
;
ir_node
*
cmp_right
=
get_irn_n
(
node
,
n_ia32_CmpSet_cmp_right
);
if
(
(
pncr
==
pn_Cmp_Eq
||
pncr
==
pn_Cmp_Lg
)
&&
is_ia32_Immediate
(
cmp_right
)
&&
is_ia32_Immediate_0
(
cmp_right
))
{
be_emit_cstring
(
env
,
"
\t
test "
);
ia32_emit_source_register
(
env
,
node
,
n_ia32_CmpSet_cmp_left
);
be_emit_cstring
(
env
,
", "
);
ia32_emit_source_register
(
env
,
node
,
n_ia32_CmpSet_cmp_left
);
}
else
{
be_emit_cstring
(
env
,
"
\t
cmp "
);
ia32_emit_binop
(
env
,
node
);
}
}
else
if
(
is_ia32_xCmpSet
(
node
))
{
be_emit_cstring
(
env
,
"
\t
ucomis"
);
ia32_emit_mode_suffix_mode
(
env
,
get_irn_mode
(
get_irn_n
(
node
,
2
)));
be_emit_char
(
env
,
' '
);
ia32_emit_binop
(
env
,
node
);
}
else
if
(
is_ia32_PsiCondSet
(
node
))
{
be_emit_cstring
(
env
,
"
\t
cmp $0, "
);
ia32_emit_source_register
(
env
,
node
,
0
);
}
else
{
assert
(
0
&&
"unsupported Set"
);
}
...
...
@@ -1068,11 +1083,6 @@ void emit_ia32_CmpSet(ia32_emit_env_t *env, const ir_node *node) {
Set_emitter
(
env
,
node
,
get_irn_mode
(
get_irn_n
(
node
,
2
)));
}
static
void
emit_ia32_PsiCondSet
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
Set_emitter
(
env
,
node
,
get_irn_mode
(
get_irn_n
(
node
,
0
)));
}
static
void
emit_ia32_xCmpSet
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
Set_emitter
(
env
,
node
,
get_irn_mode
(
get_irn_n
(
node
,
2
)));
...
...
@@ -1336,22 +1346,22 @@ void emit_Jmp(ia32_emit_env_t *env, const ir_node *node) {
static
void
emit_ia32_Immediate
(
ia32_emit_env_t
*
env
,
const
ir_node
*
node
)
{
const
ia32_attr_t
*
attr
=
get_ia32_attr_const
(
node
);
const
ia32_
immediate_
attr_t
*
attr
=
get_ia32_
immediate_
attr_const
(
node
);
assert
(
attr
->
am_sc
!=
NULL
||
attr
->
cnst_val
.
tv
!=
NULL
);
if
(
attr
->
am_sc
!=
NULL
)
{
ident
*
id
=
get_entity_ld_ident
(
attr
->
am_sc
);
assert
(
attr
->
symconst
!=
NULL
||
attr
->
offset
!=
NULL
);
if
(
attr
->
symconst
!=
NULL
)
{
ident
*
id
=
get_entity_ld_ident
(
attr
->
symconst
);
if
(
attr
->
data
.
am_sc_sign
)
if
(
attr
->
attr
.
data
.
am_sc_sign
)
be_emit_char
(
env
,
'-'
);
be_emit_ident
(
env
,
id
);
}
if
(
attr
->
cnst_val
.
tv
!=
NULL
)
{
if
(
attr
->
am_sc
!=
NULL
)
if
(
attr
->
offset
!=
NULL
)
{
if
(
attr
->
symconst
!=
NULL
)
be_emit_char
(
env
,
'+'
);
else
be_emit_char
(
env
,
'$'
);
be_emit_tarval
(
env
,
attr
->
cnst_val
.
tv
);
be_emit_tarval
(
env
,
attr
->
offset
);
}
}
...
...
@@ -1956,9 +1966,7 @@ void ia32_register_emitters(void) {
IA32_EMIT
(
CJmp
);
IA32_EMIT
(
CJmpAM
);
IA32_EMIT
(
CmpCMov
);
IA32_EMIT
(
PsiCondCMov
);
IA32_EMIT
(
CmpSet
);
IA32_EMIT
(
PsiCondSet
);
IA32_EMIT
(
SwitchJmp
);
IA32_EMIT
(
CopyB
);
IA32_EMIT
(
CopyB_i
);
...
...
ir/be/ia32/ia32_finish.c
View file @
e787df99
...
...
@@ -272,7 +272,6 @@ static INLINE int need_constraint_copy(ir_node *irn) {
!
is_ia32_Conv_I2I
(
irn
)
&&
!
is_ia32_Conv_I2I8Bit
(
irn
)
&&
!
is_ia32_CmpCMov
(
irn
)
&&
!
is_ia32_PsiCondCMov
(
irn
)
&&
!
is_ia32_CmpSet
(
irn
);
}
...
...
ir/be/ia32/ia32_new_nodes.c
View file @
e787df99
...
...
@@ -430,6 +430,15 @@ const ia32_asm_attr_t *get_ia32_asm_attr_const(const ir_node *node) {
return
asm_attr
;
}
const
ia32_immediate_attr_t
*
get_ia32_immediate_attr_const
(
const
ir_node
*
node
)
{
const
ia32_attr_t
*
attr
=
get_ia32_attr_const
(
node
);
const
ia32_immediate_attr_t
*
immediate_attr
=
CONST_CAST_IA32_ATTR
(
ia32_immediate_attr_t
,
attr
);
return
immediate_attr
;
}
/**
* Gets the type of an ia32 node.
*/
...
...
@@ -1195,6 +1204,20 @@ init_ia32_asm_attributes(ir_node *res)
#endif
}
void
init_ia32_immediate_attributes
(
ir_node
*
res
,
ir_entity
*
symconst
,
int
symconst_sign
,
tarval
*
offset
)
{
ia32_immediate_attr_t
*
attr
=
get_irn_generic_attr
(
res
);
#ifndef DEBUG
attr
->
attr
.
attr_type
|=
IA32_ATTR_ia32_immediate_attr_t
;
#endif
attr
->
symconst
=
symconst
;
attr
->
attr
.
data
.
am_sc_sign
=
symconst_sign
;
attr
->
offset
=
offset
;
}
ir_node
*
get_ia32_result_proj
(
const
ir_node
*
node
)
{
const
ir_edge_t
*
edge
;
...
...
@@ -1291,6 +1314,20 @@ int ia32_compare_asm_attr(ir_node *a, ir_node *b)
return
0
;
}
static
int
ia32_compare_immediate_attr
(
ir_node
*
a
,
ir_node
*
b
)
{
const
ia32_immediate_attr_t
*
attr_a
=
get_ia32_immediate_attr_const
(
a
);
const
ia32_immediate_attr_t
*
attr_b
=
get_ia32_immediate_attr_const
(
b
);
if
(
attr_a
->
symconst
!=
attr_b
->
symconst
||
attr_a
->
attr
.
data
.
am_sc_sign
!=
attr_b
->
attr
.
data
.
am_sc_sign
||
attr_a
->
offset
!=
attr_b
->
offset
)
return
1
;
return
0
;
}
/* copies the ia32 attributes */
static
void
ia32_copy_attr
(
const
ir_node
*
old_node
,
ir_node
*
new_node
)
{
...
...
ir/be/ia32/ia32_new_nodes.h
View file @
e787df99
...
...
@@ -57,6 +57,8 @@ const ia32_attr_t *get_ia32_attr_const(const ir_node *node);
ia32_x87_attr_t
*
get_ia32_x87_attr
(
ir_node
*
node
);
const
ia32_x87_attr_t
*
get_ia32_x87_attr_const
(
const
ir_node
*
node
);
const
ia32_immediate_attr_t
*
get_ia32_immediate_attr_const
(
const
ir_node
*
node
);
/**
* Gets the type of an ia32 node.
*/
...
...
@@ -492,6 +494,8 @@ void init_ia32_attributes(ir_node *node, arch_irn_flags_t flags,
void
init_ia32_x87_attributes
(
ir_node
*
node
);
void
init_ia32_asm_attributes
(
ir_node
*
node
);
void
init_ia32_immediate_attributes
(
ir_node
*
node
,
ir_entity
*
symconst
,
int
symconst_sign
,
tarval
*
offset
);
/**
* Registers the ia32_copy_attr function for all ia32 opcodes.
...
...
ir/be/ia32/ia32_nodes_attr.h
View file @
e787df99
...
...
@@ -31,6 +31,7 @@
#include "firm_types.h"
#include "../bearch_t.h"
#include "../bemachine.h"
#include "irnode_t.h"
typedef
enum
{
flavour_Div
=
1
,
flavour_Mod
,
flavour_DivMod
}
ia32_op_flavour_t
;
typedef
enum
{
pn_EAX
,
pn_EDX
}
pn_ia32_Register
;
...
...
@@ -87,15 +88,17 @@ enum {
#ifndef NDEBUG
typedef
enum
{
IA32_ATTR_INVALID
=
0
,
IA32_ATTR_ia32_attr_t
=
1
<<
0
,
IA32_ATTR_ia32_x87_attr_t
=
1
<<
1
,
IA32_ATTR_ia32_asm_attr_t
=
1
<<
2
,
IA32_ATTR_INVALID
=
0
,
IA32_ATTR_ia32_attr_t
=
1
<<
0
,
IA32_ATTR_ia32_x87_attr_t
=
1
<<
1
,
IA32_ATTR_ia32_asm_attr_t
=
1
<<
2
,
IA32_ATTR_ia32_immediate_attr_t
=
1
<<
3
,
}
ia32_attr_type_t
;
#endif
typedef
struct
ia32_attr_t
ia32_attr_t
;
struct
ia32_attr_t
{
except_attr
exc
;
/**< the exception attribute. MUST be the first one. */
struct
{
unsigned
tp
:
3
;
/**< ia32 node type. */
unsigned
imm_tp
:
2
;
/**< ia32 immop type. */
...
...
@@ -152,6 +155,13 @@ struct ia32_attr_t {
const
arch_register_t
**
slots
;
/**< register slots for assigned registers */
};
typedef
struct
ia32_immediate_attr_t
ia32_immediate_attr_t
;
struct
ia32_immediate_attr_t
{
ia32_attr_t
attr
;
ir_entity
*
symconst
;
tarval
*
offset
;
};
typedef
struct
ia32_x87_attr_t
ia32_x87_attr_t
;
struct
ia32_x87_attr_t
{
ia32_attr_t
attr
;
...
...
@@ -167,9 +177,10 @@ struct ia32_asm_attr_t {
/* the following union is necessary to indicate to the compiler that we might want to cast
* the structs (we use them to simulate OO-inheritance) */
union
allow_casts_attr_t_
{
ia32_attr_t
attr
;
ia32_x87_attr_t
x87_attr
;
ia32_asm_attr_t
asm_attr
;
ia32_attr_t
attr
;
ia32_x87_attr_t
x87_attr
;
ia32_asm_attr_t
asm_attr
;
ia32_immediate_attr_t
immediate_attr
;
};
#ifndef NDEBUG
...
...
ir/be/ia32/ia32_optimize.c
View file @
e787df99
...
...
@@ -71,15 +71,6 @@ static INLINE int be_is_NoReg(ia32_code_gen_t *cg, const ir_node *irn) {
return
irn
==
cg
->
noreg_gp
||
irn
==
cg
->
noreg_xmm
||
irn
==
cg
->
noreg_vfp
;
}
void
ia32_pre_transform_phase
(
ia32_code_gen_t
*
cg
)
{
/*
We need to transform the consts twice:
- the psi condition tree transformer needs existing constants to be ia32 constants
- the psi condition tree transformer inserts new firm constants which need to be transformed
*/
irg_walk_graph
(
cg
->
irg
,
NULL
,
ia32_transform_psi_cond_tree
,
cg
);
}
/********************************************************************************************************
* _____ _ _ ____ _ _ _ _ _
* | __ \ | | | | / __ \ | | (_) (_) | | (_)
...
...
ir/be/ia32/ia32_spec.pl
View file @
e787df99
...
...
@@ -303,13 +303,17 @@ $default_attr_type = "ia32_attr_t";
ia32_asm_attr_t
=>
"
\t
init_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);
\n
"
.
"
\t
init_ia32_x87_attributes(res);
"
.
"
\t
init_ia32_asm_attributes(res);
"
"
\t
init_ia32_asm_attributes(res);
",
ia32_immediate_attr_t
=>
"
\t
init_ia32_attributes(res, flags, in_reqs, out_reqs, exec_units, n_res, latency);
\n
"
.
"
\t
init_ia32_immediate_attributes(res, symconst, symconst_sign, offset);
"
);
%compare_attr
=
(
ia32_attr_t
=>
"
ia32_compare_nodes_attr
",
ia32_x87_attr_t
=>
"
ia32_compare_x87_attr
",
ia32_asm_attr_t
=>
"
ia32_compare_asm_attr
",
ia32_attr_t
=>
"
ia32_compare_nodes_attr
",
ia32_x87_attr_t
=>
"
ia32_compare_x87_attr
",
ia32_asm_attr_t
=>
"
ia32_compare_asm_attr
",
ia32_immediate_attr_t
=>
"
ia32_compare_immediate_attr
",
);
%operands
=
(
...
...
@@ -329,6 +333,8 @@ Immediate => {
op_flags
=>
"
c
",
irn_flags
=>
"
I
",
reg_req
=>
{
out
=>
[
"
gp_NOREG
"
]
},
attr
=>
"
ir_entity *symconst, int symconst_sign, tarval *offset
",
attr_type
=>
"
ia32_immediate_attr_t
",
mode
=>
$mode_gp
,
},
...
...
@@ -752,6 +758,7 @@ Dec => {
Not
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
",
"
none
"
],
out
=>
[
"
in_r3
"
]
},
ins
=>
[
"
base
",
"
index
",
"
val
",
"
mem
"
],
emit
=>
'
. not%M %unop2
',
units
=>
[
"
GP
"
],
mode
=>
$mode_gp
,
...
...
@@ -1321,14 +1328,9 @@ Conv_FP2FP => {
CmpCMov
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
",
"
gp
"
],
out
=>
[
"
in_r4
"
]
},
latency
=>
2
,
units
=>
[
"
GP
"
],
mode
=>
$mode_gp
,
},
PsiCondCMov
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
"
],
out
=>
[
"
in_r3
"
]
},
ins
=>
[
"
cmp_left
",
"
cmp_right
",
"
val_true
",
"
val_false
"
],
attr
=>
"
pn_Cmp pn_code
",
init_attr
=>
"
attr->pn_code = pn_code;
",
latency
=>
2
,
units
=>
[
"
GP
"
],
mode
=>
$mode_gp
,
...
...
@@ -1354,14 +1356,9 @@ vfCmpCMov => {
CmpSet
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
",
"
gp
",
"
gp
",
"
gp
",
"
none
"
],
out
=>
[
"
eax ebx ecx edx
"
]
},
latency
=>
2
,
units
=>
[
"
GP
"
],
mode
=>
$mode_gp
,
},
PsiCondSet
=>
{
irn_flags
=>
"
R
",
reg_req
=>
{
in
=>
[
"
gp
"
],
out
=>
[
"
eax ebx ecx edx
"
]
},
ins
=>
[
"
base
",
"
index
",
"
cmp_left
",
"
cmp_right
",
"
mem
"
],
attr
=>
"
pn_Cmp pn_code
",
init_attr
=>
"
attr->pn_code = pn_code;
",
latency
=>
2
,
units
=>
[
"
GP
"
],
mode
=>
$mode_gp
,
...
...
ir/be/ia32/ia32_transform.c
View file @
e787df99
...
...
@@ -238,6 +238,20 @@ static ir_entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst)
return
res
;
}
static
int
is_Const_0
(
ir_node
*
node
)
{
if
(
!
is_Const
(
node
))
return
0
;
return
classify_Const
(
node
)
==
CNST_NULL
;
}
static
int
is_Const_1
(
ir_node
*
node
)
{
if
(
!
is_Const
(
node
))
return
0
;
return
classify_Const
(
node
)
==
CNST_ONE
;
}
/**
* Transforms a Const.
*/
...
...
@@ -352,6 +366,7 @@ static ir_node *gen_SymConst(ir_node *node) {
return
cnst
;
}
#if 0
/**
* SSE convert of an integer node into a floating point node.
*/
...
...
@@ -392,6 +407,7 @@ static ir_node *gen_sse_conv_f2d(ia32_code_gen_t *cg, dbg_info *dbgi,
return conv;
}
#endif
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
ir_entity
*
ia32_gen_fp_known_const
(
ia32_known_const_t
kct
)
{
...
...
@@ -1004,9 +1020,8 @@ static ir_node *gen_Max(ir_node *node) {
if
(
!
mode_is_signed
(
op_mode
))
{
pnc
|=
ia32_pn_Cmp_Unsigned
;
}
new_op
=
new_rd_ia32_CmpCMov
(
dbgi
,
irg
,
block
,
new_op1
,
new_op2
,
new_op1
,
new_op2
);
set_ia32_pncode
(
new_op
,
pnc
);
set_ia32_am_support
(
new_op
,
ia32_am_None
);
new_op
=
new_rd_ia32_CmpCMov
(
dbgi
,
irg
,
block
,
new_op1
,
new_op2
,
new_op1
,
new_op2
,
pnc
);
}
SET_IA32_ORIG_NODE
(
new_op
,
ia32_get_old_node_name
(
env_cg
,
node
));
...
...
@@ -1044,9 +1059,8 @@ static ir_node *gen_Min(ir_node *node) {
if
(
!
mode_is_signed
(
op_mode
))
{
pnc
|=
ia32_pn_Cmp_Unsigned
;
}
new_op
=
new_rd_ia32_CmpCMov
(
dbgi
,
irg
,
block
,
new_op1
,
new_op2
,
new_op1
,
new_op2
);
set_ia32_pncode
(
new_op
,
pnc
);
set_ia32_am_support
(
new_op
,
ia32_am_None
);
new_op
=
new_rd_ia32_CmpCMov
(
dbgi
,
irg
,
block
,
new_op1
,
new_op2
,
new_op1
,
new_op2
,
pnc
);
}
SET_IA32_ORIG_NODE
(
new_op
,
ia32_get_old_node_name
(
env_cg
,
node
));
...
...
@@ -1657,6 +1671,7 @@ static ir_node *gen_Load(ir_node *node) {
}
}
set_irn_pinned
(
new_op
,
get_irn_pinned
(
node
));
set_ia32_am_support
(
new_op
,
ia32_am_Source
);
set_ia32_op_type
(
new_op
,
ia32_AddrModeS
);
set_ia32_am_flavour
(
new_op
,
am_flav
);
...
...
@@ -1744,6 +1759,7 @@ static ir_node *gen_Store(ir_node *node) {
}
}
set_irn_pinned
(
new_op
,
get_irn_pinned
(
node
));
set_ia32_am_support
(
new_op
,
ia32_am_Dest
);
set_ia32_op_type
(
new_op
,
ia32_AddrModeD
);
set_ia32_am_flavour
(
new_op
,
am_flav
);
...
...
@@ -1997,36 +2013,83 @@ typedef ir_node *cmov_func_t(dbg_info *db, ir_graph *irg, ir_node *block,
static
ir_node
*
gen_Psi
(
ir_node
*
node
)
{
ir_node
*
block
=
be_transform_node
(
get_nodes_block
(
node
));
ir_node
*
psi_true
=
get_Psi_val
(
node
,
0
);
ir_node
*
new_psi_true
=
be_transform_node
(
psi_true
);
ir_node
*
psi_default
=
get_Psi_default
(
node
);
ir_node
*
new_psi_default
=
be_transform_node
(
psi_default
);
ia32_code_gen_t
*
cg
=
env_cg
;
ir_graph
*
irg
=
current_ir_graph
;
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
ir_
m
ode
*
mode
=
get_
irn_mode
(
node
);
ir_node
*
cmp_proj
=
get_Mux_sel
(
node
);
ir_node
*
no
reg
=
ia32_
new_No
Reg_gp
(
cg
);
ir_node
*
n
omem
=
new_rd_NoMem
(
irg
)
;
ir_node
*
cmp
,
*
cmp_a
,
*
cmp_b
,
*
and1
,
*
and2
,
*
new_op
=
NULL
;
ir_
n
ode
*
cond
=
get_
Psi_cond
(
node
,
0
);
ir_node
*
noreg
=
ia32_new_NoReg_gp
(
env_cg
);
ir_node
*
no
mem
=
new_No
Mem
(
);
ir_node
*
n
ew_op
;
ir_node
*
cmp
,
*
cmp_a
,
*
cmp_b
;
ir_node
*
new_cmp_a
,
*
new_cmp_b
;
ir_mode
*
cmp_mode
;
int
pnc
;
assert
(
get_irn_mode
(
cmp_proj
)
==
mode_b
&&
"Condition for Psi must have mode_b"
);
int
pnc
;
assert
(
get_Psi_n_conds
(
node
)
==
1
);
assert
(
get_irn_mode
(
cond
)
==
mode_b
);
if
(
is_And
(
cond
)
||
is_Or
(
cond
))
{
ir_node
*
new_cond
=
be_transform_node
(
cond
);
tarval
*
tv_zero
=
new_tarval_from_long
(
0
,
mode_Iu
);
ir_node
*
zero
=
new_rd_ia32_Immediate
(
NULL
,
irg
,
block
,
NULL
,
0
,
tv_zero
);
arch_set_irn_register
(
env_cg
->
arch_env
,
zero
,
&
ia32_gp_regs
[
REG_GP_NOREG
]);
/* we have to compare the result against zero */
new_cmp_a
=
new_cond
;
new_cmp_b
=
zero
;
pnc
=
pn_Cmp_Lg
;
}
else
{
cmp
=
get_Proj_pred
(
cond
);