[PATCH] Avoid more casts of switch values
Richard Biener
rguenther@suse.de
Wed Mar 26 11:56:00 GMT 2014
This avoids the (int) cast for switches on enums (which are
appearantly using an unsigned type in C++). It does so by
enhancing the code in simplify_gimple_switch to see if the
case value checks are preserved with a sign-change.
Bootstrap / regtest running on x86_64-unkown-linux-gnu, queued for stage1.
Richard.
2014-03-26 Richard Biener <rguenther@suse.de>
* tree-ssa-forwprop.c (simplify_gimple_switch): Enhance
check for which sign-changes we allow when forwarding
a converted value into a switch.
* g++.dg/tree-ssa/forwprop-switch.C: New testcase.
Index: gcc/tree-ssa-forwprop.c
===================================================================
*** gcc/tree-ssa-forwprop.c (revision 208812)
--- gcc/tree-ssa-forwprop.c (working copy)
*************** simplify_gimple_switch_label_vec (gimple
*** 1356,1398 ****
static bool
simplify_gimple_switch (gimple stmt)
{
- tree cond = gimple_switch_index (stmt);
- tree def, to, ti;
- gimple def_stmt;
-
/* The optimization that we really care about is removing unnecessary
casts. That will let us do much better in propagating the inferred
constant at the switch target. */
if (TREE_CODE (cond) == SSA_NAME)
{
! def_stmt = SSA_NAME_DEF_STMT (cond);
! if (is_gimple_assign (def_stmt))
{
! if (gimple_assign_rhs_code (def_stmt) == NOP_EXPR)
! {
! int need_precision;
! bool fail;
!
! def = gimple_assign_rhs1 (def_stmt);
! to = TREE_TYPE (cond);
! ti = TREE_TYPE (def);
!
! /* If we have an extension that preserves value, then we
! can copy the source value into the switch. */
!
! need_precision = TYPE_PRECISION (ti);
! fail = false;
! if (! INTEGRAL_TYPE_P (ti))
! fail = true;
! else if (TYPE_UNSIGNED (to) && !TYPE_UNSIGNED (ti))
! fail = true;
! else if (!TYPE_UNSIGNED (to) && TYPE_UNSIGNED (ti))
! need_precision += 1;
! if (TYPE_PRECISION (to) < need_precision)
! fail = true;
!
! if (!fail)
{
gimple_switch_set_index (stmt, def);
simplify_gimple_switch_label_vec (stmt, ti);
--- 1356,1391 ----
static bool
simplify_gimple_switch (gimple stmt)
{
/* The optimization that we really care about is removing unnecessary
casts. That will let us do much better in propagating the inferred
constant at the switch target. */
+ tree cond = gimple_switch_index (stmt);
if (TREE_CODE (cond) == SSA_NAME)
{
! gimple def_stmt = SSA_NAME_DEF_STMT (cond);
! if (gimple_assign_cast_p (def_stmt))
{
! tree def = gimple_assign_rhs1 (def_stmt);
! tree ti = TREE_TYPE (def);
! /* If we have an extension or sign-change that preserves the
! values we check against then we can copy the source value into
! the switch. */
! if (INTEGRAL_TYPE_P (ti)
! && TYPE_PRECISION (ti) <= TYPE_PRECISION (TREE_TYPE (cond)))
! {
! size_t n = gimple_switch_num_labels (stmt);
! tree min = NULL_TREE, max = NULL_TREE;
! if (n > 1)
! {
! min = CASE_LOW (gimple_switch_label (stmt, 1));
! if (CASE_HIGH (gimple_switch_label (stmt, n - 1)))
! max = CASE_HIGH (gimple_switch_label (stmt, n - 1));
! else
! max = CASE_LOW (gimple_switch_label (stmt, n - 1));
! }
! if ((!min || int_fits_type_p (min, ti))
! && (!max || int_fits_type_p (max, ti)))
{
gimple_switch_set_index (stmt, def);
simplify_gimple_switch_label_vec (stmt, ti);
Index: gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C
===================================================================
*** gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C (revision 0)
--- gcc/testsuite/g++.dg/tree-ssa/forwprop-switch.C (working copy)
***************
*** 0 ****
--- 1,24 ----
+ // { dg-do compile }
+ // { dg-options "-O -fdump-tree-cddce1" }
+
+ enum Scale { E1, E2, E3, E4, E5, E6, E7, E8 };
+
+ int Test(Scale s)
+ {
+ switch(s)
+ {
+ case E1: return 12;
+ case E2: return 17;
+ case E3: return 22;
+ case E4: return 42;
+ default: break;
+ }
+ return 0;
+ }
+
+ // tree forwprop should have eliminated the (int) s cast for the
+ // switch value and directly switch on the 's' parameter
+
+ // { dg-final { scan-tree-dump-not "\\\(int\\\)" "cddce1" } }
+ // { dg-final { scan-tree-dump "switch \\\(s_.\\\(D\\\)\\\)" "cddce1" } }
+ // { dg-final { cleanup-tree-dump "cddce1" } }
More information about the Gcc-patches
mailing list