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 <[email protected]>
+
+ * 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 <[email protected]>
* 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 <[email protected]>
+ * 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 <[email protected]>
PR c++/92031 - bogus taking address of rvalue error.
Regards,
Nidal Faour
remove-redundant-zero-extend.patch
Description: remove-redundant-zero-extend.patch
