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
3d41a571
Commit
3d41a571
authored
Oct 06, 2004
by
Michael Beck
Browse files
Added Mod/DivMod optimizations
[r4064]
parent
83c392f1
Changes
2
Hide whitespace changes
Inline
Side-by-side
ir/ir/irarch.c
View file @
3d41a571
...
...
@@ -372,6 +372,170 @@ ir_node *arch_dep_replace_div_with_shifts(ir_node *irn)
return
res
;
}
ir_node
*
arch_dep_replace_mod_with_shifts
(
ir_node
*
irn
)
{
ir_node
*
res
=
irn
;
/* If the architecture dependent optimizations were not initialized
or this optimization was not enabled. */
if
(
params
==
NULL
||
(
opts
&
arch_dep_mod_to_shift
)
==
0
)
return
irn
;
if
(
get_irn_opcode
(
irn
)
==
iro_Mod
)
{
ir_node
*
c
=
get_Mod_right
(
irn
);
ir_node
*
block
,
*
left
;
ir_mode
*
mode
;
tarval
*
tv
;
dbg_info
*
dbg
;
int
n
,
bits
;
int
i
,
k
,
num
;
if
(
get_irn_op
(
c
)
!=
op_Const
)
return
irn
;
left
=
get_Mod_left
(
irn
);
mode
=
get_irn_mode
(
left
);
block
=
get_nodes_block
(
irn
);
dbg
=
get_irn_dbg_info
(
irn
);
tv
=
get_Const_tarval
(
c
);
bits
=
get_mode_size_bits
(
mode
);
n
=
(
bits
+
7
)
/
8
;
for
(
num
=
i
=
0
;
i
<
n
;
++
i
)
{
unsigned
char
v
=
get_tarval_sub_bits
(
tv
,
i
);
if
(
v
)
{
int
j
;
for
(
j
=
0
;
j
<
8
;
++
j
)
if
((
1
<<
j
)
&
v
)
{
++
num
;
k
=
8
*
i
+
j
;
}
}
}
if
(
num
==
1
)
{
/* remainder by 2^k */
if
(
mode_is_signed
(
mode
))
{
ir_node
*
k_node
;
ir_node
*
curr
=
left
;
if
(
k
!=
1
)
{
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
k
-
1
,
mode_Iu
));
curr
=
new_rd_Shrs
(
dbg
,
current_ir_graph
,
block
,
left
,
k_node
,
mode
);
}
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
bits
-
k
,
mode_Iu
));
curr
=
new_rd_Shr
(
dbg
,
current_ir_graph
,
block
,
curr
,
k_node
,
mode
);
curr
=
new_rd_Add
(
dbg
,
current_ir_graph
,
block
,
left
,
curr
,
mode
);
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode
,
new_tarval_from_long
((
-
1
)
<<
k
,
mode
));
curr
=
new_rd_And
(
dbg
,
current_ir_graph
,
block
,
curr
,
k_node
,
mode
);
res
=
new_rd_Sub
(
dbg
,
current_ir_graph
,
block
,
left
,
curr
,
mode
);
}
else
{
/* unsigned case */
ir_node
*
k_node
;
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode
,
new_tarval_from_long
((
1
<<
k
)
-
1
,
mode
));
res
=
new_rd_And
(
dbg
,
current_ir_graph
,
block
,
left
,
k_node
,
mode
);
}
}
}
if
(
res
!=
irn
)
stat_arch_dep_replace_mod_with_shifts
(
irn
);
return
res
;
}
void
arch_dep_replace_divmod_with_shifts
(
ir_node
**
div
,
ir_node
**
mod
,
ir_node
*
irn
)
{
*
div
=
*
mod
=
NULL
;
/* If the architecture dependent optimizations were not initialized
or this optimization was not enabled. */
if
(
params
==
NULL
||
(
opts
&
arch_dep_mod_to_shift
)
==
0
)
return
;
if
(
get_irn_opcode
(
irn
)
==
iro_DivMod
)
{
ir_node
*
c
=
get_DivMod_right
(
irn
);
ir_node
*
block
,
*
left
;
ir_mode
*
mode
;
tarval
*
tv
;
dbg_info
*
dbg
;
int
n
,
bits
;
int
i
,
k
,
num
;
if
(
get_irn_op
(
c
)
!=
op_Const
)
return
;
left
=
get_DivMod_left
(
irn
);
mode
=
get_irn_mode
(
left
);
block
=
get_nodes_block
(
irn
);
dbg
=
get_irn_dbg_info
(
irn
);
tv
=
get_Const_tarval
(
c
);
bits
=
get_mode_size_bits
(
mode
);
n
=
(
bits
+
7
)
/
8
;
for
(
num
=
i
=
0
;
i
<
n
;
++
i
)
{
unsigned
char
v
=
get_tarval_sub_bits
(
tv
,
i
);
if
(
v
)
{
int
j
;
for
(
j
=
0
;
j
<
8
;
++
j
)
if
((
1
<<
j
)
&
v
)
{
++
num
;
k
=
8
*
i
+
j
;
}
}
}
if
(
num
==
1
)
{
/* division & remainder by 2^k */
if
(
mode_is_signed
(
mode
))
{
ir_node
*
k_node
;
ir_node
*
curr
=
left
;
if
(
k
!=
1
)
{
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
k
-
1
,
mode_Iu
));
curr
=
new_rd_Shrs
(
dbg
,
current_ir_graph
,
block
,
left
,
k_node
,
mode
);
}
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
bits
-
k
,
mode_Iu
));
curr
=
new_rd_Shr
(
dbg
,
current_ir_graph
,
block
,
curr
,
k_node
,
mode
);
curr
=
new_rd_Add
(
dbg
,
current_ir_graph
,
block
,
left
,
curr
,
mode
);
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
k
,
mode_Iu
));
*
div
=
new_rd_Shrs
(
dbg
,
current_ir_graph
,
block
,
curr
,
k_node
,
mode
);
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode
,
new_tarval_from_long
((
-
1
)
<<
k
,
mode
));
curr
=
new_rd_And
(
dbg
,
current_ir_graph
,
block
,
curr
,
k_node
,
mode
);
*
mod
=
new_rd_Sub
(
dbg
,
current_ir_graph
,
block
,
left
,
curr
,
mode
);
}
else
{
/* unsigned case */
ir_node
*
k_node
;
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode_Iu
,
new_tarval_from_long
(
k
,
mode_Iu
));
*
div
=
new_rd_Shl
(
dbg
,
current_ir_graph
,
block
,
left
,
k_node
,
mode
);
k_node
=
new_r_Const
(
current_ir_graph
,
block
,
mode
,
new_tarval_from_long
((
1
<<
k
)
-
1
,
mode
));
*
mod
=
new_rd_And
(
dbg
,
current_ir_graph
,
block
,
left
,
k_node
,
mode
);
}
}
}
if
(
*
div
)
stat_arch_dep_replace_DivMod_with_shifts
(
irn
);
}
static
const
arch_dep_params_t
default_params
=
{
1
,
/* also use subs */
...
...
ir/ir/irarch.h
View file @
3d41a571
...
...
@@ -45,7 +45,8 @@ const arch_dep_params_t *arch_dep_default_factory(void);
typedef
enum
{
arch_dep_none
=
0
,
arch_dep_mul_to_shift
=
1
,
/**< optimize Mul into Shift/Add/Sub */
arch_dep_div_to_shift
=
2
/**< optimize Div into Shift/Add/Mul */
arch_dep_div_to_shift
=
2
,
/**< optimize Div into Shift/Add/Mul */
arch_dep_mod_to_shift
=
4
/**< optimize Mod into Shift/Add/Mul */
}
arch_dep_opts_t
;
/**
...
...
@@ -97,4 +98,40 @@ ir_node *arch_dep_replace_mul_with_shifts(ir_node *irn);
*/
ir_node
*
arch_dep_replace_div_with_shifts
(
ir_node
*
irn
);
/**
* Replace Mods with Shifts and Add/Subs.
* This function is driven by the 3 parameters:
* - also_use_subs
* - maximum_shifts
* - highest_shift_amount
*
* If irn is a Div with a Const, The constant is inspected, if it meets the
* requirements of the three variables stated above. If a Shl/Add/Sub
* sequence can be generated, that meets these requirements, this expression
* is returned. In each other case, irn is returned unmodified.
*
* @param irn The Firm node to inspect.
* @return A replacement expression for irn.
*/
ir_node
*
arch_dep_replace_mod_with_shifts
(
ir_node
*
irn
);
/**
* Replace Mods with Shifts and Add/Subs.
* This function is driven by the 3 parameters:
* - also_use_subs
* - maximum_shifts
* - highest_shift_amount
*
* If irn is a Div with a Const, The constant is inspected, if it meets the
* requirements of the three variables stated above. If a Shl/Add/Sub
* sequence can be generated, that meets these requirements, this expression
* is returned. In each other case, irn is returned unmodified.
*
* @param div After call contains the Firm node div result or NULL.
* @param mod After call contains the Firm node mod result or NULL.
* @param irn The Firm node to inspect.
* @return A replacement expression for irn.
*/
void
arch_dep_replace_divmod_with_shifts
(
ir_node
**
div
,
ir_node
**
mod
,
ir_node
*
irn
);
#endif
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