This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[patch tree-ssa-forwprop]: Add type raising in shift-operations
- From: Kai Tietz <ktietz at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Cc: Richard Guenther <richard dot guenther at gmail dot com>, Jeff Law <law at redhat dot com>
- Date: Thu, 21 Nov 2013 10:15:27 -0500 (EST)
- Subject: [patch tree-ssa-forwprop]: Add type raising in shift-operations
- Authentication-results: sourceware.org; auth=none
Hi,
this is the required forward-propagation part for the type-demotion pass as separate patch.
This patch is sharing some adjustments in testsuite due new optimization of type-casts on shift-operations.
This patch tries to generate the "normal" form (TYPE) (X shift-op Y) out of the "denormal" form "((TYPE) X) shift-op Y".
ChangeLog
2013-11-21 Kai Tietz <ktietz@redhat.com>
* tree-ssa-forwprop.c (simplify_shift): New function.
(ssa_forward_propagate_and_combine): Use it.
ChangeLog testsuite
* gcc.dg/tree-ssa-ts-shift-2.c: New test.
Shared testsuite part between type-demotion and forward-propagation patches.
Changelog gcc/testsuite:
* gcc.dg/vect/vect-over-widen-1-big-array.c: Likewise.
* gcc.dg/vect/vect-over-widen-1.c: Likewise.
* gcc.dg/vect/vect-over-widen-3-big-array.c: Likewise.
* gcc.dg/vect/vect-over-widen-3.c: Likewise.
* gcc.dg/vect/vect-over-widen-4-big-array.c: Likewise.
* gcc.dg/vect/vect-over-widen-4.c: Likewise.
Bootstrapped for x86_64-unknown-linux-gnu. Ok for apply?
Index: gcc-org/gcc/testsuite/gcc.dg/tree-ssa/ts-shift-2.c
===================================================================
--- /dev/null
+++ gcc-org/gcc/testsuite/gcc.dg/tree-ssa/ts-shift-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+unsigned char f1 (char x)
+{
+ unsigned char x1 = (unsigned char) x;
+ return (x1 << 5);
+}
+
+unsigned short f2 (unsigned int x)
+{
+ unsigned short x1 = (unsigned short) x;
+ return (x1 << 15);
+}
+
+unsigned int f3 (unsigned short x)
+{
+ unsigned long long x1 = (unsigned long long) x;
+ return (unsigned int) (x1 >> 15);
+}
+
+unsigned long long f4 (unsigned short x)
+{
+ unsigned int x1 = (unsigned int) x;
+ return (unsigned long long) (x1 >> 7);
+}
+
+/* { dg-final { scan-tree-dump-times "= \\\(long long unsigned int\\\)" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= \\\(short unsigned int\\\)" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= \\\(unsigned int\\\)" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "= \\\(unsigned char\\\)" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
+
Index: gcc-org/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc-org.orig/gcc/tree-ssa-forwprop.c
+++ gcc-org/gcc/tree-ssa-forwprop.c
@@ -551,6 +551,107 @@ forward_propagate_into_gimple_cond (gimp
return 0;
}
+/* Try to simplify shift-statement ((TYPE1) X) CODE Y for
+ integral-kind types.
+ Returns none-zero if the stmt was changed. */
+
+static int
+simplify_shift (enum tree_code code, gimple_stmt_iterator *gsi_p)
+{
+ gimple stmt = gsi_stmt (*gsi_p);
+ gimple def, newop;
+ tree op1, opx, op2, t_opx, tem;
+ int ret;
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (stmt))))
+ return 0;
+
+ op1 = gimple_assign_rhs1 (stmt);
+ if (TREE_CODE (op1) != SSA_NAME
+ || !(def = SSA_NAME_DEF_STMT (op1))
+ || !is_gimple_assign (def)
+ || !gimple_assign_cast_p (def)
+ || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1)
+ || !has_single_use (op1))
+ return 0;
+
+ opx = gimple_assign_rhs1 (def);
+ if (TREE_CODE (opx) != SSA_NAME)
+ return 0;
+
+ t_opx = TREE_TYPE (opx);
+
+ if (!INTEGRAL_TYPE_P (t_opx))
+ return 0;
+
+ op2 = gimple_assign_rhs2 (stmt);
+
+ if (code == LSHIFT_EXPR)
+ {
+ if (TYPE_PRECISION (TREE_TYPE (op1))
+ > TYPE_PRECISION (t_opx))
+ return 0;
+ }
+ else if (code == RSHIFT_EXPR)
+ {
+ /* If type of OPX and OP1 are compatible, we don't need to check OP2
+ for validity as we don't change range of operation.
+ Otherwise we need to check that right-hand operand of shift-right
+ doesn't exceed type-precision of inner operand. */
+ if (!useless_type_conversion_p (TREE_TYPE (op1), t_opx))
+ {
+ if (TREE_CODE (op2) != INTEGER_CST)
+ return 0;
+ if (integer_zerop (fold_binary (LT_EXPR, boolean_type_node, op2,
+ build_int_cst (TREE_TYPE (op2),
+ TYPE_PRECISION (t_opx)))))
+ return 0;
+
+ /* See if cast can be moved out of the shift-right operation. */
+ if (TYPE_PRECISION (TREE_TYPE (op1)) <= TYPE_PRECISION (t_opx)
+ || (!TYPE_UNSIGNED (t_opx) && TYPE_UNSIGNED (TREE_TYPE (op1))))
+ return 0;
+ }
+ }
+ else
+ return 0;
+
+ /* Do transformation ((T1) X) shift-code N -> (T1) (X shift-code N). */
+ if (dump_file)
+ {
+ fprintf (dump_file, " Replaced ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ fprintf (dump_file, " ");
+ print_gimple_stmt (dump_file, def, 0, 0);
+ fprintf (dump_file, " by ");
+ }
+
+ tem = make_ssa_name (t_opx, NULL);
+ newop = gimple_build_assign_with_ops (code, tem, opx, op2);
+ gimple_set_location (newop, gimple_location (stmt));
+ gsi_insert_before (gsi_p, newop, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops_1 (gsi_p, NOP_EXPR, tem, NULL_TREE, NULL_TREE);
+
+ if (gimple_location (def) != UNKNOWN_LOCATION)
+ gimple_set_location (stmt, gimple_location (def));
+
+ stmt = gsi_stmt (*gsi_p);
+ update_stmt (stmt);
+
+ if (TREE_CODE (op1) == SSA_NAME)
+ ret = remove_prop_source_from_use (op1) ? 2 : 1;
+ else
+ ret = 1;
+ if (dump_file)
+ {
+ fprintf (dump_file, " by ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ fprintf (dump_file, " ");
+ print_gimple_stmt (dump_file, newop, 0, 0);
+ }
+
+ return ret;
+}
/* Propagate from the ssa name definition statements of COND_EXPR
in the rhs of statement STMT into the conditional if that simplifies it.
@@ -3432,6 +3533,15 @@ ssa_forward_propagate_and_combine (void)
|| code == NEGATE_EXPR)
&& TREE_CODE (rhs1) == SSA_NAME)
changed = simplify_not_neg_expr (&gsi);
+ else if (code == LSHIFT_EXPR
+ || code == RSHIFT_EXPR)
+ {
+ int did_something;
+ did_something = simplify_shift (code, &gsi);
+ if (did_something == 2)
+ cfg_changed = true;
+ changed = did_something != 0;
+ }
else if (code == COND_EXPR
|| code == VEC_COND_EXPR)
{
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-1-big-array.c
@@ -58,9 +58,8 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 4 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-1.c
@@ -58,10 +58,8 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 3 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-3-big-array.c
@@ -58,7 +58,7 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-3.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-3.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-3.c
@@ -58,7 +58,7 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump "vect_recog_over_widening_pattern: detected" "vect" } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-4-big-array.c
@@ -62,9 +62,8 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { ! vect_widen_shift } } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 4 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
Index: gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c
===================================================================
--- gcc-trunk.orig/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c
+++ gcc-trunk/gcc/testsuite/gcc.dg/vect/vect-over-widen-4.c
@@ -62,10 +62,8 @@ int main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 2 "vect" { target vect_widen_shift } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 4 "vect" { target { { ! vect_sizes_32B_16B } && { ! vect_widen_shift } } } } } */
-/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 8 "vect" { target vect_sizes_32B_16B } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_widen_shift_pattern: detected" 4 "vect" { target vect_widen_shift } } } */
+/* { dg-final { scan-tree-dump-times "vect_recog_over_widening_pattern: detected" 0 "vect" } } */
/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
/* { dg-final { cleanup-tree-dump "vect" } } */