gcc/gcc48-pr58956.patch

100 lines
3.0 KiB
Diff

2013-12-12 Jakub Jelinek <jakub@redhat.com>
PR middle-end/58956
PR middle-end/59470
* tree-ssa-ter.c (find_ssa_name): New helper function.
(find_replaceable_in_bb): For calls, only set same_root_var
if USE is used somewhere in gimple_call_lhs, for GIMPLE_ASM,
only set same_root_var if USE is used somewhere in output operand
trees.
* gcc.target/i386/pr59470.c: New test.
--- gcc/tree-ssa-ter.c.jj 2013-12-10 08:52:13.000000000 +0100
+++ gcc/tree-ssa-ter.c 2013-12-12 10:43:26.177866960 +0100
@@ -554,6 +554,20 @@ mark_replaceable (temp_expr_table_p tab,
}
+/* Helper function for find_replaceable_in_bb. Called via walk_tree to
+ find a SSA_NAME DATA somewhere in *TP. */
+
+static tree
+find_ssa_name (tree *tp, int *walk_subtrees, void *data)
+{
+ tree var = (tree) data;
+ if (*tp == var)
+ return var;
+ else if (IS_TYPE_OR_DECL_P (*tp))
+ *walk_subtrees = 0;
+ return NULL_TREE;
+}
+
/* This function processes basic block BB, and looks for variables which can
be replaced by their expressions. Results are stored in the table TAB. */
@@ -618,7 +632,42 @@ find_replaceable_in_bb (temp_expr_table_
&& gimple_assign_single_p (def_stmt)
&& stmt_may_clobber_ref_p (stmt,
gimple_assign_rhs1 (def_stmt)))
- same_root_var = true;
+ {
+ if (is_gimple_call (stmt))
+ {
+ /* For calls, it is not a problem if USE is among
+ call's arguments or say OBJ_TYPE_REF argument,
+ all those necessarily need to be evaluated before
+ the call that may clobber the memory. But if
+ LHS of the call refers to USE, expansion might
+ evaluate it after the call, prevent TER in that
+ case. */
+ if (gimple_call_lhs (stmt)
+ && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME
+ && walk_tree (gimple_call_lhs_ptr (stmt),
+ find_ssa_name, use, NULL))
+ same_root_var = true;
+ }
+ else if (gimple_code (stmt) == GIMPLE_ASM)
+ {
+ /* For inline asm, allow TER of loads into input
+ arguments, but disallow TER for USEs that occur
+ somewhere in outputs. */
+ unsigned int i;
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ if (TREE_CODE (gimple_asm_output_op (stmt, i))
+ != SSA_NAME
+ && walk_tree (gimple_asm_output_op_ptr (stmt,
+ i),
+ find_ssa_name, use, NULL))
+ {
+ same_root_var = true;
+ break;
+ }
+ }
+ else
+ same_root_var = true;
+ }
}
/* Mark expression as replaceable unless stmt is volatile, or the
--- gcc/testsuite/gcc.target/i386/pr59470.c.jj 2013-12-12 10:31:54.746517544 +0100
+++ gcc/testsuite/gcc.target/i386/pr59470.c 2013-12-12 10:32:42.045273313 +0100
@@ -0,0 +1,17 @@
+/* PR middle-end/58956 */
+/* PR middle-end/59470 */
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+int a, b, d[1024];
+
+int
+main ()
+{
+ int c = a;
+ asm ("{movl $6, (%2); movl $1, %0|mov dword ptr [%2], 6; mov %0, 1}"
+ : "=r" (d[c]) : "rm" (b), "r" (&a) : "memory");
+ if (d[0] != 1 || d[6] != 0)
+ __builtin_abort ();
+ return 0;
+}