diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2020-12-17 00:15:05 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2020-12-17 00:15:05 +0000 |
commit | f48b51496d08de2aabc5ed1deb45e5517333662c (patch) | |
tree | 9fa3b070c0356997a49224e484e4d3cf9b8f7f7b /gcc/rtl.h | |
parent | b665081f577d875903570ad64f40278faf0f79a0 (diff) | |
download | gcc-f48b51496d08de2aabc5ed1deb45e5517333662c.zip gcc-f48b51496d08de2aabc5ed1deb45e5517333662c.tar.gz gcc-f48b51496d08de2aabc5ed1deb45e5517333662c.tar.bz2 |
simplify-rtx: Put simplify routines into a class
One of the recurring warts of RTL is that multiplication by a power
of 2 is represented as a MULT inside a MEM but as an ASHIFT outside
a MEM. It would obviously be better if we didn't have this kind of
context sensitivity, but it would be difficult to remove.
Currently the simplify-rtx.c routines are hard-coded for the
ASHIFT form. This means that some callers have to convert the
ASHIFTs “back” into MULTs after calling the simplify-rtx.c
routines; see fwprop.c:canonicalize_address for an example.
I think we can relieve some of the pain by wrapping the simplify-rtx.c
routines in a simple class that tracks whether the expression occurs
in a MEM or not, so that no post-processing is needed.
An obvious concern is whether passing the “this” pointer around
will slow things down or bloat the code. I can't measure any
increase in compile time after applying the patch. Sizewise,
simplify-rtx.o text increases by 2.3% in default-checking builds
and 4.1% in release-checking builds.
I realise the MULT/ASHIFT thing isn't the most palatable
reason for doing this, but I think it might be useful for
other things in future, such as using local nonzero_bits
hooks/virtual functions instead of the global hooks.
The obvious alternative would be to add a static variable
and hope that it is always updated correctly.
Later patches make use of this.
gcc/
* rtl.h (simplify_context): New class.
(simplify_unary_operation, simplify_binary_operation): Use it.
(simplify_ternary_operation, simplify_relational_operation): Likewise.
(simplify_subreg, simplify_gen_unary, simplify_gen_binary): Likewise.
(simplify_gen_ternary, simplify_gen_relational): Likewise.
(simplify_gen_subreg, lowpart_subreg): Likewise.
* simplify-rtx.c (simplify_gen_binary): Turn into a member function
of simplify_context.
(simplify_gen_unary, simplify_gen_ternary, simplify_gen_relational)
(simplify_truncation, simplify_unary_operation): Likewise.
(simplify_unary_operation_1, simplify_byte_swapping_operation)
(simplify_associative_operation, simplify_logical_relational_operation)
(simplify_binary_operation, simplify_binary_operation_series)
(simplify_distributive_operation, simplify_plus_minus): Likewise.
(simplify_relational_operation, simplify_relational_operation_1)
(simplify_cond_clz_ctz, simplify_merge_mask): Likewise.
(simplify_ternary_operation, simplify_subreg, simplify_gen_subreg)
(lowpart_subreg): Likewise.
(simplify_binary_operation_1): Likewise. Test mem_depth when
deciding whether the ASHIFT or MULT form is canonical.
(simplify_merge_mask): Use simplify_context.
Diffstat (limited to 'gcc/rtl.h')
-rw-r--r-- | gcc/rtl.h | 149 |
1 files changed, 131 insertions, 18 deletions
@@ -3375,30 +3375,143 @@ extern rtx_insn *try_split (rtx, rtx_insn *, int); extern rtx_insn *split_insns (rtx, rtx_insn *); /* In simplify-rtx.c */ + +/* A class that records the context in which a simplification + is being mode. */ +class simplify_context +{ +public: + rtx simplify_unary_operation (rtx_code, machine_mode, rtx, machine_mode); + rtx simplify_binary_operation (rtx_code, machine_mode, rtx, rtx); + rtx simplify_ternary_operation (rtx_code, machine_mode, machine_mode, + rtx, rtx, rtx); + rtx simplify_relational_operation (rtx_code, machine_mode, machine_mode, + rtx, rtx); + rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64); + + rtx lowpart_subreg (machine_mode, rtx, machine_mode); + + rtx simplify_merge_mask (rtx, rtx, int); + + rtx simplify_gen_unary (rtx_code, machine_mode, rtx, machine_mode); + rtx simplify_gen_binary (rtx_code, machine_mode, rtx, rtx); + rtx simplify_gen_ternary (rtx_code, machine_mode, machine_mode, + rtx, rtx, rtx); + rtx simplify_gen_relational (rtx_code, machine_mode, machine_mode, rtx, rtx); + rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64); + + /* Tracks the level of MEM nesting for the value being simplified: + 0 means the value is not in a MEM, >0 means it is. This is needed + because the canonical representation of multiplication is different + inside a MEM than outside. */ + unsigned int mem_depth = 0; + +private: + rtx simplify_truncation (machine_mode, rtx, machine_mode); + rtx simplify_byte_swapping_operation (rtx_code, machine_mode, rtx, rtx); + rtx simplify_associative_operation (rtx_code, machine_mode, rtx, rtx); + rtx simplify_distributive_operation (rtx_code, machine_mode, rtx, rtx); + rtx simplify_logical_relational_operation (rtx_code, machine_mode, rtx, rtx); + rtx simplify_binary_operation_series (rtx_code, machine_mode, rtx, rtx); + rtx simplify_distribute_over_subregs (rtx_code, machine_mode, rtx, rtx); + rtx simplify_shift_const_int (rtx_code, machine_mode, rtx, unsigned int); + rtx simplify_plus_minus (rtx_code, machine_mode, rtx, rtx); + rtx simplify_cond_clz_ctz (rtx, rtx_code, rtx, rtx); + + rtx simplify_unary_operation_1 (rtx_code, machine_mode, rtx); + rtx simplify_binary_operation_1 (rtx_code, machine_mode, rtx, rtx, rtx, rtx); + rtx simplify_ternary_operation_1 (rtx_code, machine_mode, machine_mode, + rtx, rtx, rtx); + rtx simplify_relational_operation_1 (rtx_code, machine_mode, machine_mode, + rtx, rtx); +}; + +inline rtx +simplify_unary_operation (rtx_code code, machine_mode mode, rtx op, + machine_mode op_mode) +{ + return simplify_context ().simplify_unary_operation (code, mode, op, + op_mode); +} + +inline rtx +simplify_binary_operation (rtx_code code, machine_mode mode, rtx op0, rtx op1) +{ + return simplify_context ().simplify_binary_operation (code, mode, op0, op1); +} + +inline rtx +simplify_ternary_operation (rtx_code code, machine_mode mode, + machine_mode op0_mode, rtx op0, rtx op1, rtx op2) +{ + return simplify_context ().simplify_ternary_operation (code, mode, op0_mode, + op0, op1, op2); +} + +inline rtx +simplify_relational_operation (rtx_code code, machine_mode mode, + machine_mode op_mode, rtx op0, rtx op1) +{ + return simplify_context ().simplify_relational_operation (code, mode, + op_mode, op0, op1); +} + +inline rtx +simplify_subreg (machine_mode outermode, rtx op, machine_mode innermode, + poly_uint64 byte) +{ + return simplify_context ().simplify_subreg (outermode, op, innermode, byte); +} + +inline rtx +simplify_gen_unary (rtx_code code, machine_mode mode, rtx op, + machine_mode op_mode) +{ + return simplify_context ().simplify_gen_unary (code, mode, op, op_mode); +} + +inline rtx +simplify_gen_binary (rtx_code code, machine_mode mode, rtx op0, rtx op1) +{ + return simplify_context ().simplify_gen_binary (code, mode, op0, op1); +} + +inline rtx +simplify_gen_ternary (rtx_code code, machine_mode mode, machine_mode op0_mode, + rtx op0, rtx op1, rtx op2) +{ + return simplify_context ().simplify_gen_ternary (code, mode, op0_mode, + op0, op1, op2); +} + +inline rtx +simplify_gen_relational (rtx_code code, machine_mode mode, + machine_mode op_mode, rtx op0, rtx op1) +{ + return simplify_context ().simplify_gen_relational (code, mode, op_mode, + op0, op1); +} + +inline rtx +simplify_gen_subreg (machine_mode outermode, rtx op, machine_mode innermode, + poly_uint64 byte) +{ + return simplify_context ().simplify_gen_subreg (outermode, op, + innermode, byte); +} + +inline rtx +lowpart_subreg (machine_mode outermode, rtx op, machine_mode innermode) +{ + return simplify_context ().lowpart_subreg (outermode, op, innermode); +} + extern rtx simplify_const_unary_operation (enum rtx_code, machine_mode, rtx, machine_mode); -extern rtx simplify_unary_operation (enum rtx_code, machine_mode, rtx, - machine_mode); extern rtx simplify_const_binary_operation (enum rtx_code, machine_mode, rtx, rtx); -extern rtx simplify_binary_operation (enum rtx_code, machine_mode, rtx, - rtx); -extern rtx simplify_ternary_operation (enum rtx_code, machine_mode, - machine_mode, rtx, rtx, rtx); extern rtx simplify_const_relational_operation (enum rtx_code, machine_mode, rtx, rtx); -extern rtx simplify_relational_operation (enum rtx_code, machine_mode, - machine_mode, rtx, rtx); -extern rtx simplify_gen_binary (enum rtx_code, machine_mode, rtx, rtx); -extern rtx simplify_gen_unary (enum rtx_code, machine_mode, rtx, - machine_mode); -extern rtx simplify_gen_ternary (enum rtx_code, machine_mode, - machine_mode, rtx, rtx, rtx); -extern rtx simplify_gen_relational (enum rtx_code, machine_mode, - machine_mode, rtx, rtx); -extern rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64); -extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64); -extern rtx lowpart_subreg (machine_mode, rtx, machine_mode); extern rtx simplify_replace_fn_rtx (rtx, const_rtx, rtx (*fn) (rtx, const_rtx, void *), void *); extern rtx simplify_replace_rtx (rtx, const_rtx, rtx); |