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
8b5aac95
Commit
8b5aac95
authored
Feb 09, 2011
by
Matthias Braun
Browse files
remove DivMod
[r28345]
parent
43e469da
Changes
21
Hide whitespace changes
Inline
Side-by-side
include/libfirm/firmstat.h
View file @
8b5aac95
...
...
@@ -35,7 +35,7 @@
enum
firmstat_options_t
{
FIRMSTAT_ENABLED
=
0x00000001
,
/**< enable statistics */
FIRMSTAT_PATTERN_ENABLED
=
0x00000002
,
/**< enable pattern calculation */
FIRMSTAT_COUNT_STRONG_OP
=
0x00000004
,
/**< if set, count Mul/Div/Mod
/DivMod
by constant */
FIRMSTAT_COUNT_STRONG_OP
=
0x00000004
,
/**< if set, count Mul/Div/Mod by constant */
FIRMSTAT_COUNT_DAG
=
0x00000008
,
/**< if set, count DAG statistics */
FIRMSTAT_COUNT_DELETED
=
0x00000010
,
/**< if set, count deleted graphs */
FIRMSTAT_COUNT_SELS
=
0x00000020
,
/**< if set, count Sel(Sel(..)) differently */
...
...
include/libfirm/irarch.h
View file @
8b5aac95
...
...
@@ -140,25 +140,6 @@ FIRM_API ir_node *arch_dep_replace_div_by_const(ir_node *irn);
*/
FIRM_API
ir_node
*
arch_dep_replace_mod_by_const
(
ir_node
*
irn
);
/**
* Replace DivMods with Shifts and Add/Subs and Mulh.
* This function is driven by the 3 parameters:
* - allow_mulhu
* - allow_mulhs
* - max_bits_for_mulh
*
* If irn is a DivMod with a Const, the constant is inspected if it meets the
* requirements of the variables stated above. If a Shl/Add/Sub/Mulh
* 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.
*/
FIRM_API
void
arch_dep_replace_divmod_by_const
(
ir_node
**
div
,
ir_node
**
mod
,
ir_node
*
irn
);
#include
"end.h"
#endif
include/libfirm/ircons.h
View file @
8b5aac95
...
...
@@ -269,7 +269,6 @@
* ir_node *new_Mul (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Mulh (ir_node *op1, ir_node *op2, ir_mode *mode);
* ir_node *new_Quot (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state);
* ir_node *new_Mod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state;
* ir_node *new_And (ir_node *op1, ir_node *op2, ir_mode *mode);
...
...
@@ -700,15 +699,6 @@
* A tuple containing a memory and a execution for modeling exceptions
* and the result of the arithmetic operation.
*
* ir_node *new_DivMod (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
* ---------------------------------------------------------------------------------------------------
*
* Performs Div and Mod on integer values.
*
* Output:
* A tuple containing a memory and a execution for modeling exceptions
* and the two result of the arithmetic operations.
*
* ir_node *new_Div (ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state)
* ------------------------------------------------------------------------------------------------
*
...
...
include/libfirm/irhooks.h
View file @
8b5aac95
...
...
@@ -159,7 +159,7 @@ typedef struct hook_entry {
/** This hook is called after a Mul was replaced by a series of Shift and Add/Sub operations. */
void
(
*
_hook_arch_dep_replace_mul_with_shifts
)(
void
*
context
,
ir_node
*
irn
);
/** This hook is called after a Div/Mod
/DivMod
by a constant value was replaced. */
/** This hook is called after a Div/Mod by a constant value was replaced. */
void
(
*
_hook_arch_dep_replace_division_by_const
)(
void
*
context
,
ir_node
*
irn
);
/** This hook is called after a new mode was registered. */
...
...
include/libfirm/irnode.h
View file @
8b5aac95
...
...
@@ -482,7 +482,7 @@ FIRM_API const char *get_builtin_kind_name(ir_builtin_kind kind);
operands can be factored out. Left is the first, right the
second arithmetic value as listed in tech report 1999-44.
unops are: Minus, Abs, Not, Conv, Cast
binops are: Add, Sub, Mul, Quot,
DivMod,
Div, Mod, And, Or, Eor, Shl,
binops are: Add, Sub, Mul, Quot, Div, Mod, And, Or, Eor, Shl,
Shr, Shrs, Rotl, Cmp */
FIRM_API
int
is_unop
(
const
ir_node
*
node
);
FIRM_API
ir_node
*
get_unop_op
(
const
ir_node
*
node
);
...
...
@@ -619,13 +619,11 @@ FIRM_API ir_node *skip_HighLevel_ops(ir_node *node);
FIRM_API
int
is_cfop
(
const
ir_node
*
node
);
/** Returns true if the operation can change the control flow because
of an exception: Call, Quot,
DivMod,
Div, Mod, Load, Store, Alloc,
of an exception: Call, Quot, Div, Mod, Load, Store, Alloc,
Bad. Raise is not fragile, but a unconditional jump. */
FIRM_API
int
is_fragile_op
(
const
ir_node
*
node
);
/** Returns the memory operand of fragile operations. */
FIRM_API
ir_node
*
get_fragile_op_mem
(
ir_node
*
node
);
/** Returns the result mode of a Div operation. */
FIRM_API
ir_mode
*
get_divop_resmod
(
const
ir_node
*
node
);
/** Returns true if the operation is a forking control flow
* operation: Cond. */
...
...
ir/ana/vrp.c
View file @
8b5aac95
...
...
@@ -366,7 +366,7 @@ static int vrp_update_node(ir_node *node)
is_Abs(node) is_Alloc(node) is_Anchor(node) is_Borrow(node) is_Bound(node)
is_Break(node) is_Builtin(node) is_Call(node)
is_Carry(node) is_Cast(node) is_Cmp(node) is_Cond(node)
is_CopyB(node) is_Div(node)
is_DivMod(node)
is_Dummy(node)
is_CopyB(node) is_Div(node) is_Dummy(node)
is_End(node) is_Free(node)
is_IJmp(node) is_InstOf(node) is_Jmp(node) is_Load(node) is_Minus(node)
is_Mod(node) is_Mul(node) is_Mulh(node) is_Mux(node) is_NoMem(node)
...
...
ir/be/ia32/ia32_transform.c
View file @
8b5aac95
...
...
@@ -1066,8 +1066,14 @@ static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
match_flags_t
flags
=
match_commutative
;
/* happens for div nodes... */
if
(
mode
==
mode_T
)
mode
=
get_divop_resmod
(
node
);
if
(
mode
==
mode_T
)
{
if
(
is_Div
(
node
))
mode
=
get_Div_resmode
(
node
);
else
if
(
is_Mod
(
node
))
mode
=
get_Mod_resmode
(
node
);
else
panic
(
"can't determine mode"
);
}
/* cannot use address mode with long double on x87 */
if
(
get_mode_size_bits
(
mode
)
<=
64
)
...
...
@@ -1533,7 +1539,7 @@ static ir_node *create_sex_32_64(dbg_info *dbgi, ir_node *block,
}
/**
* Generates an ia32 Div
Mod
with additional infrastructure for the
* Generates an ia32 Div with additional infrastructure for the
* register allocator if needed.
*/
static
ir_node
*
create_Div
(
ir_node
*
node
)
...
...
@@ -1565,12 +1571,6 @@ static ir_node *create_Div(ir_node *node)
mem
=
get_Mod_mem
(
node
);
mode
=
get_Mod_resmode
(
node
);
break
;
case
iro_DivMod
:
op1
=
get_DivMod_left
(
node
);
op2
=
get_DivMod_right
(
node
);
mem
=
get_DivMod_mem
(
node
);
mode
=
get_DivMod_resmode
(
node
);
break
;
default:
panic
(
"invalid divmod node %+F"
,
node
);
}
...
...
@@ -1621,15 +1621,6 @@ static ir_node *gen_Div(ir_node *node)
return
create_Div
(
node
);
}
/**
* Generates an ia32 DivMod.
*/
static
ir_node
*
gen_DivMod
(
ir_node
*
node
)
{
return
create_Div
(
node
);
}
/**
* Creates an ia32 floating Div.
...
...
@@ -4583,9 +4574,9 @@ static ir_node *gen_Proj_Load(ir_node *node)
}
/**
* Transform and renumber the Projs from a Div
Mod like
instruction.
* Transform and renumber the Projs from a Div
or Mod
instruction.
*/
static
ir_node
*
gen_Proj_DivMod
(
ir_node
*
node
)
static
ir_node
*
gen_Proj_Div
_
Mod
(
ir_node
*
node
)
{
ir_node
*
block
=
be_transform_node
(
get_nodes_block
(
node
));
ir_node
*
pred
=
get_Proj_pred
(
node
);
...
...
@@ -4624,28 +4615,11 @@ static ir_node *gen_Proj_DivMod(ir_node *node)
break
;
}
break
;
case
iro_DivMod
:
switch
(
proj
)
{
case
pn_DivMod_M
:
return
new_rd_Proj
(
dbgi
,
new_pred
,
mode_M
,
pn_ia32_Div_M
);
case
pn_DivMod_res_div
:
return
new_rd_Proj
(
dbgi
,
new_pred
,
mode_Iu
,
pn_ia32_Div_div_res
);
case
pn_DivMod_res_mod
:
return
new_rd_Proj
(
dbgi
,
new_pred
,
mode_Iu
,
pn_ia32_Div_mod_res
);
case
pn_DivMod_X_regular
:
return
new_rd_Jmp
(
dbgi
,
block
);
case
pn_DivMod_X_except
:
set_ia32_exc_label
(
new_pred
,
1
);
return
new_rd_Proj
(
dbgi
,
new_pred
,
mode_X
,
pn_ia32_Div_X_exc
);
default:
break
;
}
break
;
default:
break
;
}
panic
(
"No idea how to transform proj->DivMod"
);
panic
(
"No idea how to transform proj->Div
/
Mod"
);
}
/**
...
...
@@ -5625,8 +5599,7 @@ static ir_node *gen_Proj(ir_node *node)
return
gen_Proj_Builtin
(
node
);
case
iro_Div
:
case
iro_Mod
:
case
iro_DivMod
:
return
gen_Proj_DivMod
(
node
);
return
gen_Proj_Div_Mod
(
node
);
case
iro_CopyB
:
return
gen_Proj_CopyB
(
node
);
case
iro_Quot
:
...
...
@@ -5706,7 +5679,6 @@ static void register_transformers(void)
be_set_transform_function
(
op_Conv
,
gen_Conv
);
be_set_transform_function
(
op_CopyB
,
ia32_gen_CopyB
);
be_set_transform_function
(
op_Div
,
gen_Div
);
be_set_transform_function
(
op_DivMod
,
gen_DivMod
);
be_set_transform_function
(
op_Eor
,
gen_Eor
);
be_set_transform_function
(
op_ia32_l_Adc
,
gen_ia32_l_Adc
);
be_set_transform_function
(
op_ia32_l_Add
,
gen_ia32_l_Add
);
...
...
ir/ir/irarch.c
View file @
8b5aac95
...
...
@@ -820,7 +820,7 @@ static struct mu magicu(ir_tarval *d)
/**
* Build the Mulh replacement code for n / tv.
*
* Note that 'div' might be a
mod or Div
Mod operation as well
* Note that 'div' might be a Mod operation as well
*/
static
ir_node
*
replace_div_by_mulh
(
ir_node
*
div
,
ir_tarval
*
tv
)
{
...
...
@@ -1088,111 +1088,3 @@ ir_node *arch_dep_replace_mod_by_const(ir_node *irn)
return
res
;
}
/* Replace DivMods with Shifts and Add/Subs and Mulh. */
void
arch_dep_replace_divmod_by_const
(
ir_node
**
div
,
ir_node
**
mod
,
ir_node
*
irn
)
{
const
ir_settings_arch_dep_t
*
params
=
be_get_backend_param
()
->
dep_param
;
*
div
=
*
mod
=
NULL
;
/* If the architecture dependent optimizations were not initialized
or this optimization was not enabled. */
if
(
params
==
NULL
||
((
opts
&
(
arch_dep_div_by_const
|
arch_dep_mod_by_const
))
!=
(
arch_dep_div_by_const
|
arch_dep_mod_by_const
)))
return
;
if
(
is_DivMod
(
irn
))
{
ir_node
*
c
=
get_DivMod_right
(
irn
);
ir_node
*
block
,
*
left
;
ir_mode
*
mode
;
ir_tarval
*
tv
,
*
ntv
;
dbg_info
*
dbg
;
int
n
,
bits
;
int
k
;
int
n_flag
=
0
;
if
(
!
is_Const
(
c
))
return
;
tv
=
get_Const_tarval
(
c
);
/* check for division by zero */
if
(
tarval_is_null
(
tv
))
return
;
left
=
get_DivMod_left
(
irn
);
mode
=
get_irn_mode
(
left
);
block
=
get_irn_n
(
irn
,
-
1
);
dbg
=
get_irn_dbg_info
(
irn
);
bits
=
get_mode_size_bits
(
mode
);
n
=
(
bits
+
7
)
/
8
;
k
=
-
1
;
if
(
mode_is_signed
(
mode
))
{
/* for signed divisions, the algorithm works for a / -2^k by negating the result */
ntv
=
tarval_neg
(
tv
);
n_flag
=
1
;
k
=
tv_ld2
(
ntv
,
n
);
}
if
(
k
<
0
)
{
n_flag
=
0
;
k
=
tv_ld2
(
tv
,
n
);
}
if
(
k
>=
0
)
{
/* division by 2^k or -2^k */
ir_graph
*
irg
=
get_irn_irg
(
irn
);
if
(
mode_is_signed
(
mode
))
{
ir_node
*
k_node
,
*
c_k
;
ir_node
*
curr
=
left
;
if
(
k
!=
1
)
{
k_node
=
new_r_Const_long
(
irg
,
mode_Iu
,
k
-
1
);
curr
=
new_rd_Shrs
(
dbg
,
block
,
left
,
k_node
,
mode
);
}
k_node
=
new_r_Const_long
(
irg
,
mode_Iu
,
bits
-
k
);
curr
=
new_rd_Shr
(
dbg
,
block
,
curr
,
k_node
,
mode
);
curr
=
new_rd_Add
(
dbg
,
block
,
left
,
curr
,
mode
);
c_k
=
new_r_Const_long
(
irg
,
mode_Iu
,
k
);
*
div
=
new_rd_Shrs
(
dbg
,
block
,
curr
,
c_k
,
mode
);
if
(
n_flag
)
{
/* negate the div result */
ir_node
*
k_node
=
new_r_Const
(
irg
,
get_mode_null
(
mode
));
*
div
=
new_rd_Sub
(
dbg
,
block
,
k_node
,
*
div
,
mode
);
}
k_node
=
new_r_Const_long
(
irg
,
mode
,
(
-
1
)
<<
k
);
curr
=
new_rd_And
(
dbg
,
block
,
curr
,
k_node
,
mode
);
*
mod
=
new_rd_Sub
(
dbg
,
block
,
left
,
curr
,
mode
);
}
else
{
/* unsigned case */
ir_node
*
k_node
=
new_r_Const_long
(
irg
,
mode_Iu
,
k
);
*
div
=
new_rd_Shr
(
dbg
,
block
,
left
,
k_node
,
mode
);
k_node
=
new_r_Const_long
(
irg
,
mode
,
(
1
<<
k
)
-
1
);
*
mod
=
new_rd_And
(
dbg
,
block
,
left
,
k_node
,
mode
);
}
}
else
{
/* other constant */
if
(
allow_Mulh
(
params
,
mode
))
{
ir_node
*
t
;
*
div
=
replace_div_by_mulh
(
irn
,
tv
);
t
=
new_rd_Mul
(
dbg
,
block
,
*
div
,
c
,
mode
);
/* t = arch_dep_mul_to_shift(t); */
*
mod
=
new_rd_Sub
(
dbg
,
block
,
left
,
t
,
mode
);
}
}
}
if
(
*
div
)
hook_arch_dep_replace_division_by_const
(
irn
);
}
ir/ir/irdump.c
View file @
8b5aac95
...
...
@@ -724,9 +724,6 @@ void dump_node_opcode(FILE *F, ir_node *n)
case
iro_Mod
:
fprintf
(
F
,
"%s[%s]"
,
get_irn_opname
(
n
),
get_mode_name_ex
(
get_Mod_resmode
(
n
),
NULL
));
break
;
case
iro_DivMod
:
fprintf
(
F
,
"%s[%s]"
,
get_irn_opname
(
n
),
get_mode_name_ex
(
get_DivMod_resmode
(
n
),
NULL
));
break
;
case
iro_Builtin
:
fprintf
(
F
,
"%s[%s]"
,
get_irn_opname
(
n
),
get_builtin_kind_name
(
get_Builtin_kind
(
n
)));
break
;
...
...
@@ -845,17 +842,6 @@ static const pns_lookup_t quot_lut[] = {
#undef X
};
/** the lookup table for Proj(DivMod) names */
static
const
pns_lookup_t
divmod_lut
[]
=
{
#define X(a) { pn_DivMod_##a, #a }
X
(
M
),
X
(
X_regular
),
X
(
X_except
),
X
(
res_div
),
X
(
res_mod
)
#undef X
};
/** the lookup table for Proj(Div) names */
static
const
pns_lookup_t
div_lut
[]
=
{
#define X(a) { pn_Div_##a, #a }
...
...
@@ -949,7 +935,6 @@ static const proj_lookup_t proj_lut[] = {
{
iro_Cond
,
E
(
cond_lut
)
},
{
iro_Call
,
E
(
call_lut
)
},
{
iro_Quot
,
E
(
quot_lut
)
},
{
iro_DivMod
,
E
(
divmod_lut
)
},
{
iro_Div
,
E
(
div_lut
)
},
{
iro_Mod
,
E
(
mod_lut
)
},
{
iro_Load
,
E
(
load_lut
)
},
...
...
ir/ir/irnode.c
View file @
8b5aac95
...
...
@@ -968,15 +968,6 @@ void set_Sel_index(ir_node *node, int pos, ir_node *index)
set_irn_n
(
node
,
pos
+
SEL_INDEX_OFFSET
,
index
);
}
/* For unary and binary arithmetic operations the access to the
operands can be factored out. Left is the first, right the
second arithmetic value as listed in tech report 0999-33.
unops are: Minus, Abs, Not, Conv, Cast
binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
Shr, Shrs, Rotate, Cmp */
ir_node
**
get_Call_param_arr
(
ir_node
*
node
)
{
assert
(
is_Call
(
node
));
...
...
@@ -1585,7 +1576,6 @@ ir_node *get_fragile_op_mem(ir_node *node)
switch
(
get_irn_opcode
(
node
))
{
case
iro_Call
:
case
iro_Quot
:
case
iro_DivMod
:
case
iro_Div
:
case
iro_Mod
:
case
iro_Load
:
...
...
@@ -1602,19 +1592,6 @@ ir_node *get_fragile_op_mem(ir_node *node)
}
}
/* Returns the result mode of a Div operation. */
ir_mode
*
get_divop_resmod
(
const
ir_node
*
node
)
{
switch
(
get_irn_opcode
(
node
))
{
case
iro_Quot
:
return
get_Quot_resmode
(
node
);
case
iro_DivMod
:
return
get_DivMod_resmode
(
node
);
case
iro_Div
:
return
get_Div_resmode
(
node
);
case
iro_Mod
:
return
get_Mod_resmode
(
node
);
default:
panic
(
"should not be reached"
);
}
}
/* Returns true if the operation is a forking control flow operation. */
int
(
is_irn_forking
)(
const
ir_node
*
node
)
{
...
...
ir/ir/iropt.c
View file @
8b5aac95
...
...
@@ -593,24 +593,6 @@ static ir_tarval *do_computed_value_Mod(const ir_node *a, const ir_node *b)
return
tarval_bad
;
}
/* do_computed_value_Mod */
/**
* Return the value of a Proj(DivMod).
*/
static
ir_tarval
*
computed_value_Proj_DivMod
(
const
ir_node
*
n
)
{
long
proj_nr
=
get_Proj_proj
(
n
);
/* compute either the Div or the Mod part */
if
(
proj_nr
==
pn_DivMod_res_div
)
{
const
ir_node
*
a
=
get_Proj_pred
(
n
);
return
do_computed_value_Div
(
get_DivMod_left
(
a
),
get_DivMod_right
(
a
));
}
else
if
(
proj_nr
==
pn_DivMod_res_mod
)
{
const
ir_node
*
a
=
get_Proj_pred
(
n
);
return
do_computed_value_Mod
(
get_DivMod_left
(
a
),
get_DivMod_right
(
a
));
}
return
tarval_bad
;
}
/* computed_value_Proj_DivMod */
/**
* Return the value of a Proj(Div).
*/
...
...
@@ -723,7 +705,6 @@ static ir_op_ops *firm_set_default_computed_value(ir_opcode code, ir_op_ops *ops
CASE
(
Mux
);
CASE
(
Confirm
);
CASE_PROJ
(
Cmp
);
CASE_PROJ
(
DivMod
);
CASE_PROJ
(
Div
);
CASE_PROJ
(
Mod
);
CASE_PROJ
(
Quot
);
...
...
@@ -1565,40 +1546,6 @@ static ir_node *equivalent_node_Proj_Quot(ir_node *proj)
return
proj
;
}
/* equivalent_node_Proj_Quot */
/**
* Optimize a / 1 = a.
*/
static
ir_node
*
equivalent_node_Proj_DivMod
(
ir_node
*
proj
)
{
ir_node
*
oldn
=
proj
;
ir_node
*
divmod
=
get_Proj_pred
(
proj
);
ir_node
*
b
=
get_DivMod_right
(
divmod
);
ir_tarval
*
tb
=
value_of
(
b
);
/* Div is not commutative. */
if
(
tarval_is_one
(
tb
))
{
/* div(x, 1) == x */
switch
(
get_Proj_proj
(
proj
))
{
case
pn_DivMod_M
:
proj
=
get_DivMod_mem
(
divmod
);
DBG_OPT_ALGSIM0
(
oldn
,
proj
,
FS_OPT_NEUTRAL_1
);
return
proj
;
case
pn_DivMod_res_div
:
proj
=
get_DivMod_left
(
divmod
);
DBG_OPT_ALGSIM0
(
oldn
,
proj
,
FS_OPT_NEUTRAL_1
);
return
proj
;
default:
/* we cannot replace the exception Proj's here, this is done in
transform_node_Proj_DivMod().
Note further that the pn_DivMod_res_div case is handled in
computed_value_Proj(). */
return
proj
;
}
}
return
proj
;
}
/* equivalent_node_Proj_DivMod */
/**
* Optimize CopyB(mem, x, x) into a Nop.
*/
...
...
@@ -1949,7 +1896,6 @@ static ir_op_ops *firm_set_default_equivalent_node(ir_opcode code, ir_op_ops *op
CASE_PROJ
(
Tuple
);
CASE_PROJ
(
Div
);
CASE_PROJ
(
Quot
);
CASE_PROJ
(
DivMod
);
CASE_PROJ
(
CopyB
);
CASE_PROJ
(
Bound
);
CASE_PROJ
(
Load
);
...
...
@@ -3071,121 +3017,6 @@ make_tuple:
return
n
;
}
/* transform_node_Mod */
/**
* Transform a DivMod node.
*/
static
ir_node
*
transform_node_DivMod
(
ir_node
*
n
)
{
const
ir_node
*
dummy
;
ir_node
*
a
=
get_DivMod_left
(
n
);
ir_node
*
b
=
get_DivMod_right
(
n
);
ir_mode
*
mode
=
get_DivMod_resmode
(
n
);
ir_node
*
va
,
*
vb
;
ir_graph
*
irg
=
get_irn_irg
(
n
);
ir_tarval
*
ta
,
*
tb
;
int
evaluated
=
0
;
if
(
is_Const
(
b
)
&&
is_const_Phi
(
a
))
{
/* check for Div(Phi, Const) */
va
=
apply_binop_on_phi
(
a
,
get_Const_tarval
(
b
),
(
eval_func
)
tarval_div
,
mode
,
0
);
vb
=
apply_binop_on_phi
(
a
,
get_Const_tarval
(
b
),
(
eval_func
)
tarval_mod
,
mode
,
0
);
if
(
va
&&
vb
)
{
DBG_OPT_ALGSIM0
(
n
,
va
,
FS_OPT_CONST_PHI
);
DBG_OPT_ALGSIM0
(
n
,
vb
,
FS_OPT_CONST_PHI
);
goto
make_tuple
;
}
}
else
if
(
is_Const
(
a
)
&&
is_const_Phi
(
b
))
{
/* check for Div(Const, Phi) */
va
=
apply_binop_on_phi
(
b
,
get_Const_tarval
(
a
),
(
eval_func
)
tarval_div
,
mode
,
1
);
vb
=
apply_binop_on_phi
(
b
,
get_Const_tarval
(
a
),
(
eval_func
)
tarval_mod
,
mode
,
1
);
if
(
va
&&
vb
)
{
DBG_OPT_ALGSIM0
(
n
,
va
,
FS_OPT_CONST_PHI
);
DBG_OPT_ALGSIM0
(
n
,
vb
,
FS_OPT_CONST_PHI
);
goto
make_tuple
;
}
}
else
if
(
is_const_Phi
(
a
)
&&
is_const_Phi
(
b
))
{
/* check for Div(Phi, Phi) */
va
=
apply_binop_on_2_phis
(
a
,
b
,
(
eval_func
)
tarval_div
,
mode
);
vb
=
apply_binop_on_2_phis
(
a
,
b
,
(
eval_func
)
tarval_mod
,
mode
);
if
(
va
&&
vb
)
{
DBG_OPT_ALGSIM0
(
n
,
va
,
FS_OPT_CONST_PHI
);
DBG_OPT_ALGSIM0
(
n
,
vb
,
FS_OPT_CONST_PHI
);
goto
make_tuple
;
}
}
ta
=
value_of
(
a
);
tb
=
value_of
(
b
);
if
(
tb
!=
tarval_bad
)
{
if
(
tb
==
get_mode_one
(
get_tarval_mode
(
tb
)))
{
va
=
a
;
vb
=
new_r_Const
(
irg
,
get_mode_null
(
mode
));
DBG_OPT_CSTEVAL
(
n
,
vb
);
goto
make_tuple
;
}
else
if
(
ta
!=
tarval_bad
)
{
ir_tarval
*
resa
,
*
resb
;
resa
=
tarval_div
(
ta
,
tb
);
if
(
resa
==
tarval_bad
)
return
n
;
/* Causes exception!!! Model by replacing through
Jmp for X result!? */
resb
=
tarval_mod
(
ta
,
tb
);
if
(
resb
==
tarval_bad
)
return
n
;
/* Causes exception! */
va
=
new_r_Const
(
irg
,
resa
);
vb
=
new_r_Const
(
irg
,
resb
);
DBG_OPT_CSTEVAL
(
n
,
va
);
DBG_OPT_CSTEVAL
(
n
,
vb
);
goto
make_tuple
;
}
else
if
(
mode_is_signed
(
mode
)
&&
tb
==
get_mode_minus_one
(
mode
))
{
va
=
new_rd_Minus
(
get_irn_dbg_info
(
n
),
get_nodes_block
(
n
),
a
,
mode
);
vb
=
new_r_Const
(
irg
,
get_mode_null
(
mode
));
DBG_OPT_CSTEVAL
(
n
,
va
);
DBG_OPT_CSTEVAL
(
n
,
vb
);
goto
make_tuple
;
}
else
{
/* Try architecture dependent optimization */
va
=
a
;
vb
=
b
;
arch_dep_replace_divmod_by_const
(
&
va
,
&
vb
,
n
);
evaluated
=
va
!=
NULL
;
}
}
else
if
(
a
==
b
)
{
if
(
value_not_zero
(
a
,
&
dummy
))
{
/* a/a && a != 0 */
va
=
new_r_Const
(
irg
,
get_mode_one
(
mode
));
vb
=
new_r_Const
(
irg
,
get_mode_null
(
mode
));
DBG_OPT_CSTEVAL
(
n
,
va
);
DBG_OPT_CSTEVAL
(
n
,
vb
);
goto
make_tuple
;
}
else
{
/* BEWARE: it is NOT possible to optimize a/a to 1, as this may cause a exception */
return
n
;
}
}
else
if
(
ta
==
get_mode_null
(
mode
)
&&
value_not_zero
(
b
,
&
dummy
))
{
/* 0 / non-Const = 0 */
vb
=
va
=
a
;
goto
make_tuple
;
}
if
(
evaluated
)
{
/* replace by tuple */
ir_node
*
mem
,
*
blk
;
make_tuple:
mem
=
get_DivMod_mem
(
n
);
/* skip a potential Pin */
mem
=
skip_Pin
(
mem
);
blk
=
get_nodes_block
(
n
);
turn_into_tuple
(
n
,
pn_DivMod_max
);
set_Tuple_pred
(
n
,
pn_DivMod_M
,
mem
);
set_Tuple_pred
(
n
,
pn_DivMod_X_regular
,
new_r_Jmp
(
blk
));
set_Tuple_pred
(
n
,
pn_DivMod_X_except
,
get_irg_bad
(
irg
));
/*no exception*/
set_Tuple_pred
(
n
,
pn_DivMod_res_div
,
va
);
set_Tuple_pred
(
n
,
pn_DivMod_res_mod
,
vb
);
}
return
n
;
}
/* transform_node_DivMod */
/**
* Optimize x / c to x * (1/c)
*/
...
...
@@ -3977,71 +3808,6 @@ static ir_node *transform_node_Proj_Mod(ir_node *proj)