Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
9ae28adf
Commit
9ae28adf
authored
Jul 02, 2014
by
Tobias Rapp
Browse files
amd64: Add intrinsic phase and rewrite unsigned long to floating point conversion
parent
a6de0672
Changes
1
Hide whitespace changes
Inline
Side-by-side
ir/be/amd64/bearch_amd64.c
View file @
9ae28adf
...
...
@@ -23,7 +23,7 @@
#include
"be_t.h"
#include
"debug.h"
#include
"panic.h"
#include
"ircons.h"
#include
"ircons
_t
.h"
#include
"irdump.h"
#include
"irgmod.h"
#include
"irgwalk.h"
...
...
@@ -292,6 +292,111 @@ static void amd64_after_ra_walker(ir_node *block, void *data)
}
}
/**
* rewrite unsigned long -> float/double conversion
* x86_64 only has a signed conversion
*/
static
void
rewrite_unsigned_float_Conv
(
ir_node
*
node
)
{
ir_graph
*
irg
=
get_irn_irg
(
node
);
dbg_info
*
dbgi
=
get_irn_dbg_info
(
node
);
ir_node
*
lower_block
=
get_nodes_block
(
node
);
ir_mode
*
dest_mode
=
get_irn_mode
(
node
);
part_block
(
node
);
ir_node
*
block
=
get_nodes_block
(
node
);
ir_node
*
unsigned_x
=
get_Conv_op
(
node
);
ir_mode
*
mode_u
=
get_irn_mode
(
unsigned_x
);
ir_mode
*
mode_s
=
find_signed_mode
(
mode_u
);
ir_node
*
signed_x
=
new_rd_Conv
(
dbgi
,
block
,
unsigned_x
,
mode_s
);
ir_node
*
zero
=
new_r_Const_null
(
irg
,
mode_s
);
ir_node
*
cmp
=
new_rd_Cmp
(
dbgi
,
block
,
signed_x
,
zero
,
ir_relation_less
);
ir_node
*
cond
=
new_rd_Cond
(
dbgi
,
block
,
cmp
);
ir_node
*
proj_true
=
new_r_Proj
(
cond
,
mode_X
,
pn_Cond_true
);
ir_node
*
proj_false
=
new_r_Proj
(
cond
,
mode_X
,
pn_Cond_false
);
ir_node
*
in_true
[
1
]
=
{
proj_true
};
ir_node
*
in_false
[
1
]
=
{
proj_false
};
/* true block: Do some arithmetic to use the signed conversion */
ir_node
*
true_block
=
new_r_Block
(
irg
,
ARRAY_SIZE
(
in_true
),
in_true
);
ir_node
*
true_jmp
=
new_r_Jmp
(
true_block
);
ir_node
*
one
=
new_r_Const_one
(
irg
,
mode_u
);
ir_node
*
and
=
new_r_And
(
true_block
,
unsigned_x
,
one
,
mode_u
);
ir_node
*
shr
=
new_r_Shr
(
true_block
,
unsigned_x
,
one
,
mode_u
);
ir_node
*
or
=
new_r_Or
(
true_block
,
and
,
shr
,
mode_u
);
ir_node
*
or_signed
=
new_rd_Conv
(
dbgi
,
true_block
,
or
,
mode_s
);
ir_node
*
half
=
new_rd_Conv
(
dbgi
,
true_block
,
or_signed
,
dest_mode
);
ir_node
*
true_res
=
new_r_Add
(
true_block
,
half
,
half
,
dest_mode
);
/* false block: Simply convert to floating point */
ir_node
*
false_block
=
new_r_Block
(
irg
,
ARRAY_SIZE
(
in_false
),
in_false
);
ir_node
*
false_jmp
=
new_r_Jmp
(
false_block
);
ir_node
*
false_res
=
new_rd_Conv
(
dbgi
,
false_block
,
signed_x
,
dest_mode
);
/* lower block */
ir_node
*
lower_in
[
2
]
=
{
true_jmp
,
false_jmp
};
ir_node
*
phi_in
[
2
]
=
{
true_res
,
false_res
};
set_irn_in
(
lower_block
,
ARRAY_SIZE
(
lower_in
),
lower_in
);
ir_node
*
phi
=
new_r_Phi
(
lower_block
,
ARRAY_SIZE
(
phi_in
),
phi_in
,
dest_mode
);
assert
(
get_Block_phis
(
lower_block
)
==
NULL
);
set_Block_phis
(
lower_block
,
phi
);
set_Phi_next
(
phi
,
NULL
);
exchange
(
node
,
phi
);
}
static
bool
amd64_rewrite_Conv
(
ir_node
*
node
)
{
ir_mode
*
to_mode
=
get_irn_mode
(
node
);
ir_node
*
op
=
get_Conv_op
(
node
);
ir_mode
*
from_mode
=
get_irn_mode
(
op
);
bool
to_float
=
mode_is_float
(
to_mode
);
bool
from_float
=
mode_is_float
(
from_mode
);
if
(
to_float
&&
!
from_float
&&
!
mode_is_signed
(
from_mode
)
&&
get_mode_size_bits
(
from_mode
)
==
64
)
{
rewrite_unsigned_float_Conv
(
node
);
return
true
;
}
else
if
(
from_float
&&
!
to_float
&&
!
mode_is_signed
(
to_mode
)
&&
get_mode_size_bits
(
to_mode
)
==
64
)
{
panic
(
"Cannot yet convert floating point to unsigned long!
\n
"
);
return
true
;
}
return
false
;
}
static
void
amd64_intrinsics_walker
(
ir_node
*
node
,
void
*
data
)
{
bool
*
changed
=
(
bool
*
)
data
;
if
(
is_Conv
(
node
))
{
if
(
amd64_rewrite_Conv
(
node
))
*
changed
=
true
;
}
}
static
void
amd64_handle_intrinsics
(
ir_graph
*
irg
)
{
ir_reserve_resources
(
irg
,
IR_RESOURCE_IRN_LINK
|
IR_RESOURCE_PHI_LIST
);
collect_phiprojs
(
irg
);
bool
changed
=
false
;
irg_walk_graph
(
irg
,
amd64_intrinsics_walker
,
NULL
,
&
changed
);
ir_free_resources
(
irg
,
IR_RESOURCE_IRN_LINK
|
IR_RESOURCE_PHI_LIST
);
if
(
changed
)
{
confirm_irg_properties
(
irg
,
IR_GRAPH_PROPERTY_NO_BADS
|
IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
|
IR_GRAPH_PROPERTY_MANY_RETURNS
|
IR_GRAPH_PROPERTY_ONE_RETURN
);
}
}
static
void
amd64_set_frame_entity
(
ir_node
*
node
,
ir_entity
*
entity
,
const
ir_type
*
type
)
{
...
...
@@ -625,7 +730,7 @@ const arch_isa_if_t amd64_isa_if = {
amd64_new_reload
,
NULL
,
NULL
,
/*
handle
intrinsics
*/
amd64_
handle
_
intrinsics
,
amd64_prepare_graph
,
amd64_before_ra
,
amd64_finish_graph
,
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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