This patch is a code density oriented and attempt to remove redundant sign/zero extension from assignment statement. The approach taken is to use VRP data while expanding the assignment to RTL to determine whether a sign/zero extension is necessary. Thought the motivation of the patch is code density but it also good for speed.
for example: extern unsigned int func (); unsigned char foo (unsigned int arg) { if (arg == 2) return 0; return (func() == arg || arg == 7); } the result of the comparison in the return will yield a False or True, which will be converted to integer and then casting to unsigned char. this casting from integer to unsigned char is redundant because the value is either 0 or 1. this patch is targeting the RISCV-32bit only. This patch has been tested on a real embedded project and saved about 0.2% of code size. P.S. I have an FSF license under Western Digital incorporation. P.S. I've attached the patch as a file in case my email client corrupted the patch itself diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 9864e4344d2..c3739b2f331 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ +#include <algorithm> #include "config.h" #include "system.h" #include "coretypes.h" @@ -73,6 +74,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-address.h" #include "output.h" #include "builtins.h" +#include "tree-vrp.h" + /* Some systems use __main in a way incompatible with its use in gcc, in these cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to @@ -3640,6 +3643,107 @@ expand_clobber (tree lhs) } } +/* Print the ranges of the operand and save it to the dump file + used for debug purposes only. */ + +void +print_range (tree operand, wide_int min, wide_int max) +{ + pretty_printer buffer; + pp_needs_newline (&buffer) = false; + buffer.buffer->stream = dump_file; + fprintf (dump_file, "Range for lhs: ["); + pp_wide_int (&buffer, min, TYPE_SIGN (TREE_TYPE (operand))); + pp_printf (&buffer, ", "); + pp_wide_int (&buffer, max, TYPE_SIGN (TREE_TYPE (operand))); + pp_printf (&buffer, "]"); + pp_flush (&buffer); + fprintf (dump_file, "\n"); +} + + + +/* Check that REG and SUBREG modes match between src and dest, + and that there is a cast to be removed. */ + +bool +cast_to_remove_p (rtx src, rtx dest, machine_mode from + , machine_mode to) +{ + if (GET_CODE (src) != SUBREG + || GET_CODE (dest) != SUBREG + || GET_CODE (SUBREG_REG (src)) != REG + || GET_CODE (SUBREG_REG (dest)) != REG + || GET_MODE (src) != GET_MODE (dest) + || GET_MODE (SUBREG_REG (src)) != GET_MODE (SUBREG_REG (dest)) + || GET_MODE (src) != to + || GET_MODE (SUBREG_REG (src)) != from) + return false; + return true; +} + +bool +remove_cast_p (rtx temp, rtx target, gassign *assign_stmt) +{ + enum gimple_code code; + value_range_kind lhs_range, rhs_range; + unsigned int ops_num; + wide_int lhs_min, lhs_max, rhs_min, rhs_max; + if (gimple_assign_cast_p (assign_stmt)) + { + code = gimple_code (assign_stmt); + ops_num = gimple_num_ops (assign_stmt); + if (code == GIMPLE_ASSIGN && ops_num < 3) + { + tree lhs = gimple_assign_lhs (assign_stmt); + if (POINTER_TYPE_P (TREE_TYPE (lhs))) + return false; + lhs_range = get_range_info (lhs, &lhs_min, &lhs_max); + if (dump_file && lhs_range == VR_RANGE) + print_range (lhs, lhs_min, lhs_max); + + tree rhs = gimple_assign_rhs1 (assign_stmt); + if (POINTER_TYPE_P (TREE_TYPE (rhs))) + return false; + rhs_range = get_range_info (rhs, &rhs_min, &rhs_max); + if (rhs_range == VR_RANGE) + { + unsigned int rhs_precision + = std::max (wi::min_precision (rhs_max, TYPE_SIGN (TREE_TYPE (rhs))), + wi::min_precision (rhs_min, TYPE_SIGN (TREE_TYPE (rhs)))); + unsigned int lhs_precision = TYPE_PRECISION (TREE_TYPE (lhs)); + if (lhs_precision > rhs_precision) + { + + if (dump_file) + { + print_range (rhs, rhs_min, rhs_max); + if (lhs_precision > rhs_precision) + fprintf (dump_file, + "EXPAND-CAST: This casting can be optimized\n"); + } + + return cast_to_remove_p (temp, + target, + TYPE_MODE (TREE_TYPE (rhs)), + TYPE_MODE (TREE_TYPE (lhs))); + } + else + if (dump_file) + fprintf (dump_file, "EXPAND-CAST: lhs_precision < rhs_precision\n"); + } + else + if (dump_file) + fprintf (dump_file, "EXPAND-CAST: Range is not VR_RANGE\n"); + } + else + if (dump_file) + fprintf (dump_file, "EXPAND-CAST: Got more than 2 ops \n"); + } + return false; +} + + /* A subroutine of expand_gimple_stmt, expanding one gimple statement STMT that doesn't require special handling for outgoing edges. That is no tailcalls and no GIMPLE_COND. */ @@ -3801,6 +3905,11 @@ expand_gimple_stmt_1 (gimple *stmt) temp = convert_modes (GET_MODE (SUBREG_REG (target)), GET_MODE (target), temp, unsignedp); } + if (targetm.remove_redundant_cast) + if (remove_cast_p (temp, + target, + assign_stmt)) + temp = SUBREG_REG (temp); convert_move (SUBREG_REG (target), temp, unsignedp); } diff --git a/gcc/config/riscv/riscv.c b/gcc/config/riscv/riscv.c index 94b5ac01762..504b1abf85e 100644 --- a/gcc/config/riscv/riscv.c +++ b/gcc/config/riscv/riscv.c @@ -5226,6 +5226,9 @@ riscv_hard_regno_rename_ok (unsigned from_regno ATTRIBUTE_UNUSED, #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG riscv_reorg +#undef TARGET_REMOVE_REDUNDANT_CAST +#define TARGET_REMOVE_REDUNDANT_CAST true + struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-riscv.h" diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 19985adac3e..3a0d4813d96 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -12194,3 +12194,9 @@ This target hook can be used to generate a target-specific code @deftypefn {Target Hook} void TARGET_RUN_TARGET_SELFTESTS (void) If selftests are enabled, run any selftests for this target. @end deftypefn + +@deftypevr {Target Hook} bool TARGET_REMOVE_REDUNDANT_CAST +If this flag is true, @code{remove_cast_p} will be called +and remove unneeded cast +The default is false. +@end deftypevr \ No newline at end of file diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 1a16150bfc5..984e18e1697 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -8178,3 +8178,5 @@ maintainer is familiar with. @hook TARGET_SPECULATION_SAFE_VALUE @hook TARGET_RUN_TARGET_SELFTESTS + +@hook TARGET_REMOVE_REDUNDANT_CAST \ No newline at end of file diff --git a/gcc/target.def b/gcc/target.def index b5e82ff826e..014e5a22d4d 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -6770,6 +6770,15 @@ following it should not be run. Usually true only for virtual assembler\n\ targets.", bool, false) +/* True if remove_redundant_cast should be called to remove unneeded + casting. */ +DEFHOOKPOD +(remove_redundant_cast, + "If this flag is true, @code{remove_cast_p} will be called\n\ +and remove unneeded cast\n\ +The default is false.", + bool, false) + /* Leave the boolean fields at the end. */ /* Functions related to mode switching. */ @@ -6835,4 +6844,3 @@ DEFHOOK /* Close the 'struct gcc_target' definition. */ HOOK_VECTOR_END (C90_EMPTY_HACK) - ----------------------------------------------------------------------- Change log: diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 085ef66a207..ffe7e061985 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2020-02-19 Nidal Faour <nidal.fa...@wdc.com> + + * doc/tm.texi.in (TARGET_REMOVE_REDUNDANT_CAST): New hook. + * doc/tm.texi: Regenerate. + *cfgexpand.c (algorith.h): New include. + (tree-vrp.h): Likewise + (print_range): New function + (check_assign_can_be_free): Likewise + (adjust_assign_to_remove_cast): Likewise + (expand_gimple_stmt_1): Call adjust_assign_to_remove_cast + *config/riscv/riscv.c (TARGET_REMOVE_REDUNDANT_CAST): Define + *target.def (remove_redundant_cast): New target hook + 2020-03-09 Jason Merrill <ja...@redhat.com> * gdbinit.in (pgs): Fix typo in documentation. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f91af78a302..c5a701e08af 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-02-19 Nidal Faour <nidal.fa...@wdc.com> + * gcc.target/riscv/masking-to-byte-1.c: New test + * gcc.target/riscv/masking-to-byte-2.c: New test + 2020-03-09 Marek Polacek <pola...@redhat.com> PR c++/92031 - bogus taking address of rvalue error. Regards, Nidal Faour
remove-redundant-zero-extend.patch
Description: remove-redundant-zero-extend.patch