diff mbox

[PR68083] stop ifcombine from moving uninitialized uses before their guards

Message ID or8u6kfp8l.fsf@livre.home
State New
Headers show

Commit Message

Alexandre Oliva Oct. 30, 2015, 1:41 p.m. UTC
The ifcombine pass may move a conditional access to an uninitialized
value before the condition that ensures it is always well-defined,
thus introducing undefined behavior.  Stop it from doing so.

Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?


Incidentally, bb_no_side_effects_p (inner_cond_bb) is called in all four
tests in tree_ssa_ifcombine_bb_1, for each outer_cond_bb that
tree_ssa_ifcombine_bb might choose.  Is there any reason to not factor
it out to the test that checks whether the inner_cond_bb is indeed an
if_then_else block, early in tree_ssa_ifcombine_bb, so as to
short-circuit the whole thing when the inner block is not viable?


for  gcc/ChangeLog

	PR tree-optimization/68083
	* tree-ssa-ifcombine.c: Include tree-ssa.h.
	(bb_no_side_effects_p): Test for undefined uses too.
	* tree-ssa.c (gimple_uses_undefined_value_p): New.
	* tree-ssa.h (gimple_uses_undefined_value_p): Declare.

for  gcc/testsuite/ChangeLog

	PR tree-optimization/68083
	* gcc.dg/torture/pr68083.c: New.  From Zhendong Su.
---
 gcc/testsuite/gcc.dg/torture/pr68083.c |   35 ++++++++++++++++++++++++++++++++
 gcc/tree-ssa-ifcombine.c               |    2 ++
 gcc/tree-ssa.c                         |   18 ++++++++++++++++
 gcc/tree-ssa.h                         |    1 +
 4 files changed, 56 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr68083.c

Comments

Richard Biener Nov. 2, 2015, 9:32 a.m. UTC | #1
On Fri, Oct 30, 2015 at 2:41 PM, Alexandre Oliva <aoliva@redhat.com> wrote:
> The ifcombine pass may move a conditional access to an uninitialized
> value before the condition that ensures it is always well-defined,
> thus introducing undefined behavior.  Stop it from doing so.
>
> Regstrapped on x86_64-linux-gnu and i686-linux-gnu.  Ok to install?

Ok.

Thanks,
Richard.

>
> Incidentally, bb_no_side_effects_p (inner_cond_bb) is called in all four
> tests in tree_ssa_ifcombine_bb_1, for each outer_cond_bb that
> tree_ssa_ifcombine_bb might choose.  Is there any reason to not factor
> it out to the test that checks whether the inner_cond_bb is indeed an
> if_then_else block, early in tree_ssa_ifcombine_bb, so as to
> short-circuit the whole thing when the inner block is not viable?
>
>
> for  gcc/ChangeLog
>
>         PR tree-optimization/68083
>         * tree-ssa-ifcombine.c: Include tree-ssa.h.
>         (bb_no_side_effects_p): Test for undefined uses too.
>         * tree-ssa.c (gimple_uses_undefined_value_p): New.
>         * tree-ssa.h (gimple_uses_undefined_value_p): Declare.
>
> for  gcc/testsuite/ChangeLog
>
>         PR tree-optimization/68083
>         * gcc.dg/torture/pr68083.c: New.  From Zhendong Su.
> ---
>  gcc/testsuite/gcc.dg/torture/pr68083.c |   35 ++++++++++++++++++++++++++++++++
>  gcc/tree-ssa-ifcombine.c               |    2 ++
>  gcc/tree-ssa.c                         |   18 ++++++++++++++++
>  gcc/tree-ssa.h                         |    1 +
>  4 files changed, 56 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.dg/torture/pr68083.c
>
> diff --git a/gcc/testsuite/gcc.dg/torture/pr68083.c b/gcc/testsuite/gcc.dg/torture/pr68083.c
> new file mode 100644
> index 0000000..ae24781
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/torture/pr68083.c
> @@ -0,0 +1,35 @@
> +/* { dg-do run } */
> +
> +int a = 2, b = 1, c = 1;
> +
> +int
> +fn1 ()
> +{
> +  int d;
> +  for (; a; a--)
> +    {
> +      for (d = 0; d < 4; d++)
> +       {
> +         int k;
> +         if (c < 1)
> +           if (k)
> +             c = 0;
> +         if (b)
> +           continue;
> +         return 0;
> +       }
> +      b = !1;
> +    }
> +  return 0;
> +}
> +
> +int
> +main ()
> +{
> +  fn1 ();
> +
> +  if (a != 1)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
> index ca55b57..622dc6b 100644
> --- a/gcc/tree-ssa-ifcombine.c
> +++ b/gcc/tree-ssa-ifcombine.c
> @@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "gimple-iterator.h"
>  #include "gimplify-me.h"
>  #include "tree-cfg.h"
> +#include "tree-ssa.h"
>
>  #ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
>  #define LOGICAL_OP_NON_SHORT_CIRCUIT \
> @@ -125,6 +126,7 @@ bb_no_side_effects_p (basic_block bb)
>         continue;
>
>        if (gimple_has_side_effects (stmt)
> +         || gimple_uses_undefined_value_p (stmt)
>           || gimple_could_trap_p (stmt)
>           || gimple_vuse (stmt))
>         return false;
> diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> index c7be442..8dc2d61 100644
> --- a/gcc/tree-ssa.c
> +++ b/gcc/tree-ssa.c
> @@ -1210,6 +1210,24 @@ ssa_undefined_value_p (tree t, bool partial)
>  }
>
>
> +/* Return TRUE iff STMT, a gimple statement, references an undefined
> +   SSA name.  */
> +
> +bool
> +gimple_uses_undefined_value_p (gimple *stmt)
> +{
> +  ssa_op_iter iter;
> +  tree op;
> +
> +  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
> +    if (ssa_undefined_value_p (op))
> +      return true;
> +
> +  return false;
> +}
> +
> +
> +
>  /* If necessary, rewrite the base of the reference tree *TP from
>     a MEM_REF to a plain or converted symbol.  */
>
> diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h
> index 5a409e5..3b5bd70 100644
> --- a/gcc/tree-ssa.h
> +++ b/gcc/tree-ssa.h
> @@ -51,6 +51,7 @@ extern bool tree_ssa_useless_type_conversion (tree);
>  extern tree tree_ssa_strip_useless_type_conversions (tree);
>
>  extern bool ssa_undefined_value_p (tree, bool = true);
> +extern bool gimple_uses_undefined_value_p (gimple *);
>  extern void execute_update_addresses_taken (void);
>
>  /* Given an edge_var_map V, return the PHI arg definition.  */
>
>
> --
> Alexandre Oliva, freedom fighter    http://FSFLA.org/~lxoliva/
> You must be the change you wish to see in the world. -- Gandhi
> Be Free! -- http://FSFLA.org/   FSF Latin America board member
> Free Software Evangelist|Red Hat Brasil GNU Toolchain Engineer
diff mbox

Patch

diff --git a/gcc/testsuite/gcc.dg/torture/pr68083.c b/gcc/testsuite/gcc.dg/torture/pr68083.c
new file mode 100644
index 0000000..ae24781
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr68083.c
@@ -0,0 +1,35 @@ 
+/* { dg-do run } */
+
+int a = 2, b = 1, c = 1;
+
+int
+fn1 ()
+{
+  int d;
+  for (; a; a--)
+    {
+      for (d = 0; d < 4; d++)
+	{
+	  int k;
+	  if (c < 1)
+	    if (k)
+	      c = 0;
+	  if (b)
+	    continue;
+	  return 0;
+	}
+      b = !1;
+    }
+  return 0;
+}
+
+int
+main ()
+{
+  fn1 ();
+
+  if (a != 1)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c
index ca55b57..622dc6b 100644
--- a/gcc/tree-ssa-ifcombine.c
+++ b/gcc/tree-ssa-ifcombine.c
@@ -41,6 +41,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimplify-me.h"
 #include "tree-cfg.h"
+#include "tree-ssa.h"
 
 #ifndef LOGICAL_OP_NON_SHORT_CIRCUIT
 #define LOGICAL_OP_NON_SHORT_CIRCUIT \
@@ -125,6 +126,7 @@  bb_no_side_effects_p (basic_block bb)
 	continue;
 
       if (gimple_has_side_effects (stmt)
+	  || gimple_uses_undefined_value_p (stmt)
 	  || gimple_could_trap_p (stmt)
 	  || gimple_vuse (stmt))
 	return false;
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index c7be442..8dc2d61 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1210,6 +1210,24 @@  ssa_undefined_value_p (tree t, bool partial)
 }
 
 
+/* Return TRUE iff STMT, a gimple statement, references an undefined
+   SSA name.  */
+
+bool
+gimple_uses_undefined_value_p (gimple *stmt)
+{
+  ssa_op_iter iter;
+  tree op;
+
+  FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
+    if (ssa_undefined_value_p (op))
+      return true;
+
+  return false;
+}
+
+
+
 /* If necessary, rewrite the base of the reference tree *TP from
    a MEM_REF to a plain or converted symbol.  */
 
diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h
index 5a409e5..3b5bd70 100644
--- a/gcc/tree-ssa.h
+++ b/gcc/tree-ssa.h
@@ -51,6 +51,7 @@  extern bool tree_ssa_useless_type_conversion (tree);
 extern tree tree_ssa_strip_useless_type_conversions (tree);
 
 extern bool ssa_undefined_value_p (tree, bool = true);
+extern bool gimple_uses_undefined_value_p (gimple *);
 extern void execute_update_addresses_taken (void);
 
 /* Given an edge_var_map V, return the PHI arg definition.  */