re PR tree-optimization/34099 (optimizer problem)
authorRichard Guenther <rguenther@suse.de>
Fri, 16 Nov 2007 10:10:05 +0000 (10:10 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 16 Nov 2007 10:10:05 +0000 (10:10 +0000)
2007-11-16  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/34099
* tree-ssa-ccp.c (likely_value): Use a whitelist for operators
that produce UNDEFINED result if at least one of its operands
is UNDEFINED.  By default the result is only UNDEFINED if all
operands are UNDEFINED.

* g++.dg/torture/pr3499.C: New testcase.
* gcc.c-torture/execute/pr34099.c: Likewise.

From-SVN: r130222

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr34099.C [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr34099.c [new file with mode: 0644]
gcc/tree-ssa-ccp.c

index 6db268ff8695edbebab5775c6e33d4f0a2b51d18..80dac9c59107f679bb2a5b5e78553dc35118caa4 100644 (file)
@@ -1,3 +1,11 @@
+2007-11-16  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/34099
+       * tree-ssa-ccp.c (likely_value): Use a whitelist for operators
+       that produce UNDEFINED result if at least one of its operands
+       is UNDEFINED.  By default the result is only UNDEFINED if all
+       operands are UNDEFINED.
+
 2007-11-16  Jakub Jelinek  <jakub@redhat.com>
 
        PR driver/30460
index 0ef30d2a02e47607b43a2acf6c487ee3fb61a9d3..9c84667f81fab4f994718d3fbd5d7e5c63cc1f47 100644 (file)
@@ -1,3 +1,9 @@
+2007-11-16  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/34099
+       * g++.dg/torture/pr3499.C: New testcase.
+       * gcc.c-torture/execute/pr34099.c: Likewise.
+
 2007-11-16  Olivier Hainque  <hainque@adacore.com>
 
        * gnat.dg/release_unc_maxalign.adb: New test.
diff --git a/gcc/testsuite/g++.dg/torture/pr34099.C b/gcc/testsuite/g++.dg/torture/pr34099.C
new file mode 100644 (file)
index 0000000..49fa9ca
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+
+#include <complex>
+
+typedef std::complex<double> NumType;
+
+void
+multiply(NumType a, NumType b, unsigned ac, NumType &ab)
+{
+  NumType s;
+  for (unsigned j=0; j<ac; j++)
+    s = a * b;
+  ab = s;
+}
+extern "C" void abort (void);
+int main()
+{
+  NumType a(1,2), b(3,-2), c;
+  multiply(a, b, 1, c);
+  if (c.real() != 7
+      || c.imag() != 4)
+    abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr34099.c b/gcc/testsuite/gcc.c-torture/execute/pr34099.c
new file mode 100644 (file)
index 0000000..d6f5ad1
--- /dev/null
@@ -0,0 +1,16 @@
+int foo (int b, int c)
+{
+  int x;
+  if (b)
+    return x & c;
+  else
+    return 1;
+}
+extern void abort (void);
+int main()
+{
+  if (foo(1, 0) != 0)
+    abort ();
+  return 0;
+}
+
index 0fc4b4713b415088b58f2202483d3149ef8e5008..fc40449be8db8584d0ee0ca15963e0e8275ffd29 100644 (file)
@@ -507,7 +507,8 @@ set_lattice_value (tree var, prop_value_t new_val)
 
    If STMT has no operands, then return CONSTANT.
 
-   Else if any operands of STMT are undefined, then return UNDEFINED.
+   Else if undefinedness of operands of STMT cause its value to be
+   undefined, then return UNDEFINED.
 
    Else if any operands of STMT are constants, then return CONSTANT.
 
@@ -516,7 +517,7 @@ set_lattice_value (tree var, prop_value_t new_val)
 static ccp_lattice_t
 likely_value (tree stmt)
 {
-  bool has_constant_operand;
+  bool has_constant_operand, has_undefined_operand, all_undefined_operands;
   stmt_ann_t ann;
   tree use;
   ssa_op_iter iter;
@@ -552,17 +553,72 @@ likely_value (tree stmt)
     return CONSTANT;
 
   has_constant_operand = false;
+  has_undefined_operand = false;
+  all_undefined_operands = true;
   FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
     {
       prop_value_t *val = get_value (use);
 
       if (val->lattice_val == UNDEFINED)
-       return UNDEFINED;
+       has_undefined_operand = true;
+      else
+       all_undefined_operands = false;
 
       if (val->lattice_val == CONSTANT)
        has_constant_operand = true;
     }
 
+  /* If the operation combines operands like COMPLEX_EXPR make sure to
+     not mark the result UNDEFINED if only one part of the result is
+     undefined.  */
+  if (has_undefined_operand
+      && all_undefined_operands)
+    return UNDEFINED;
+  else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
+          && has_undefined_operand)
+    {
+      switch (TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 1)))
+       {
+       /* Unary operators are handled with all_undefined_operands.  */
+       case PLUS_EXPR:
+       case MINUS_EXPR:
+       case MULT_EXPR:
+       case POINTER_PLUS_EXPR:
+       case TRUNC_DIV_EXPR:
+       case CEIL_DIV_EXPR:
+       case FLOOR_DIV_EXPR:
+       case ROUND_DIV_EXPR:
+       case TRUNC_MOD_EXPR:
+       case CEIL_MOD_EXPR:
+       case FLOOR_MOD_EXPR:
+       case ROUND_MOD_EXPR:
+       case RDIV_EXPR:
+       case EXACT_DIV_EXPR:
+       case LSHIFT_EXPR:
+       case RSHIFT_EXPR:
+       case LROTATE_EXPR:
+       case RROTATE_EXPR:
+       case EQ_EXPR:
+       case NE_EXPR:
+       case LT_EXPR:
+       case GT_EXPR:
+         /* Not MIN_EXPR, MAX_EXPR.  One VARYING operand may be selected.
+            Not bitwise operators, one VARYING operand may specify the
+            result completely.  Not logical operators for the same reason.
+            Not LE/GE comparisons or unordered comparisons.  Not
+            COMPLEX_EXPR as one VARYING operand makes the result partly
+            not UNDEFINED.  */
+         return UNDEFINED;
+
+       default:
+         ;
+       }
+    }
+  /* If there was an UNDEFINED operand but the result may be not UNDEFINED
+     fall back to VARYING even if there were CONSTANT operands.  */
+  if (has_undefined_operand)
+    return VARYING;
+
   if (has_constant_operand
       /* We do not consider virtual operands here -- load from read-only
         memory may have only VARYING virtual operands, but still be