]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR tree-optimization/34651 (ICE in set_value_range, at tree-vrp.c:321)
authorRichard Guenther <rguenther@suse.de>
Thu, 10 Jan 2008 14:28:40 +0000 (14:28 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 10 Jan 2008 14:28:40 +0000 (14:28 +0000)
2008-01-10  Richard Guenther  <rguenther@suse.de>

PR tree-optimization/34651
* tree-sra.c (sra_build_assignment): Sanitize.  Use the correct
types and ordering for masking and converting.

* g++.dg/torture/pr34651.C: New testcase.

From-SVN: r131442

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr34651.C [new file with mode: 0644]
gcc/tree-sra.c

index 0748d1575a2aef1bcafd9f1643a84604cecb8111..cc61c7050ba3d424572b185cf8f6ceeeeefa933b 100644 (file)
@@ -1,3 +1,9 @@
+2008-01-10  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/34651
+       * tree-sra.c (sra_build_assignment): Sanitize.  Use the correct
+       types and ordering for masking and converting.
+
 2008-01-09  Sebastian Pop  <sebastian.pop@amd.com>
 
        PR tree-optimization/34017
index 8730974a7a782dd7ab46317499d57df5dc3ac373..496ef45a8f0ae53406d30f22a39573d631e0629b 100644 (file)
@@ -1,3 +1,8 @@
+2008-01-10  Richard Guenther  <rguenther@suse.de>
+
+       PR tree-optimization/34651
+       * g++.dg/torture/pr34651.C: New testcase.
+
 2008-01-09  Sebastian Pop  <sebastian.pop@amd.com>
 
        PR tree-optimization/34017
diff --git a/gcc/testsuite/g++.dg/torture/pr34651.C b/gcc/testsuite/g++.dg/torture/pr34651.C
new file mode 100644 (file)
index 0000000..2fce4d7
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+
+typedef bool Bool;
+struct CString {
+    CString (const char * =__null);
+    CString & operator += (const CString &);
+};
+struct THotKey {
+   short Key;
+   Bool Control;
+   Bool Shift;
+   Bool Alt;
+};
+THotKey m_HotKey;
+THotKey GetHotKey () { return m_HotKey; }
+void Serialize ()
+{
+   THotKey inHotKey (GetHotKey());
+   CString outCombinaison (inHotKey.Control
+                          ? ((inHotKey.Alt || inHotKey.Shift)
+                             ? "ctrl+" : "ctrl")
+                          : __null);
+   outCombinaison += inHotKey.Alt ? inHotKey.Shift ? "alt+" : "alt" : "";
+   outCombinaison += inHotKey.Shift ? "shift" : "";
+}
index 9128677dde0493a21fed8c72791f0110d9bf7a63..df6c6dc7be651497810c3800e96f333f6ccf8cb6 100644 (file)
@@ -2127,30 +2127,37 @@ static tree
 sra_build_assignment (tree dst, tree src)
 {
   /* Turning BIT_FIELD_REFs into bit operations enables other passes
-     to do a much better job at optimizing the code.  */
+     to do a much better job at optimizing the code.
+     From dst = BIT_FIELD_REF <var, sz, off> we produce
+
+       SR.1 = (scalar type) var;
+       SR.2 = SR.1 >> off;
+       SR.3 = SR.2 & ((1 << sz) - 1);
+       ... possible sign extension of SR.3 ...
+       dst = (destination type) SR.3;
+   */
   if (scalar_bitfield_p (src))
     {
-      tree cst, cst2, mask, minshift, maxshift;
-      tree tmp, var, utype, stype;
+      tree var, shift, width;
+      tree utype, stype, stmp, utmp;
       tree list, stmt;
       bool unsignedp = BIT_FIELD_REF_UNSIGNED (src);
 
       var = TREE_OPERAND (src, 0);
-      cst = TREE_OPERAND (src, 2);
-      cst2 = size_binop (PLUS_EXPR, TREE_OPERAND (src, 1),
-                        TREE_OPERAND (src, 2));
-
+      width = TREE_OPERAND (src, 1);
+      /* The offset needs to be adjusted to a right shift quantity
+        depending on the endianess.  */
       if (BYTES_BIG_ENDIAN)
        {
-         maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
-         minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
+         tree tmp = size_binop (PLUS_EXPR, width, TREE_OPERAND (src, 2));
+         shift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), tmp);
        }
       else
-       {
-         maxshift = cst2;
-         minshift = cst;
-       }
+       shift = TREE_OPERAND (src, 2);
 
+      /* In weird cases we have non-integral types for the source or
+        destination object.
+        ???  For unknown reasons we also want an unsigned scalar type.  */
       stype = TREE_TYPE (var);
       if (!INTEGRAL_TYPE_P (stype))
        stype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW
@@ -2166,117 +2173,92 @@ sra_build_assignment (tree dst, tree src)
        utype = unsigned_type_for (utype);
 
       list = NULL;
+      stmp = make_rename_temp (stype, "SR");
 
-      cst2 = size_binop (MINUS_EXPR, maxshift, minshift);
-      if (TREE_INT_CST_LOW (cst2) == TYPE_PRECISION (utype))
-       {
-         unsignedp = true;
-         mask = NULL_TREE;
-       }
-      else
-       {
-         mask = build_int_cst_wide (utype, 1, 0);
-         cst = int_const_binop (LSHIFT_EXPR, mask, cst2, true);
-         mask = int_const_binop (MINUS_EXPR, cst, mask, true);
-       }
-
-      tmp = make_rename_temp (stype, "SR");
-      if (TYPE_MAIN_VARIANT (TREE_TYPE (var)) != TYPE_MAIN_VARIANT (stype))
+      /* Convert the base var of the BIT_FIELD_REF to the scalar type
+        we use for computation if we cannot use it directly.  */
+      if (!useless_type_conversion_p (stype, TREE_TYPE (var)))
        {
          if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
-           stmt = build_gimple_modify_stmt (tmp,
+           stmt = build_gimple_modify_stmt (stmp,
                                             fold_convert (stype, var));
          else
-           stmt = build_gimple_modify_stmt (tmp,
+           stmt = build_gimple_modify_stmt (stmp,
                                             fold_build1 (VIEW_CONVERT_EXPR,
                                                          stype, var));
          append_to_statement_list (stmt, &list);
-
-         var = tmp;
+         var = stmp;
        }
 
-      if (!integer_zerop (minshift))
+      if (!integer_zerop (shift))
        {
-         tmp = make_rename_temp (stype, "SR");
-         stmt = build_gimple_modify_stmt (tmp,
+         stmt = build_gimple_modify_stmt (stmp,
                                           fold_build2 (RSHIFT_EXPR, stype,
-                                                       var, minshift));
+                                                       var, shift));
          append_to_statement_list (stmt, &list);
-
-         var = tmp;
+         var = stmp;
        }
 
-      if (TYPE_MAIN_VARIANT (utype) != TYPE_MAIN_VARIANT (stype))
+      /* If we need a masking operation, produce one.  */
+      if (TREE_INT_CST_LOW (width) == TYPE_PRECISION (stype))
+       unsignedp = true;
+      else
        {
-         if (!mask && unsignedp
-             && (TYPE_MAIN_VARIANT (utype)
-                 == TYPE_MAIN_VARIANT (TREE_TYPE (dst))))
-           tmp = dst;
-         else
-           tmp = make_rename_temp (utype, "SR");
+         tree one = build_int_cst_wide (stype, 1, 0);
+         tree mask = int_const_binop (LSHIFT_EXPR, one, width, 0);
+         mask = int_const_binop (MINUS_EXPR, mask, one, 0);
 
-         stmt = build_gimple_modify_stmt (tmp, fold_convert (utype, var));
+         stmt = build_gimple_modify_stmt (stmp,
+                                          fold_build2 (BIT_AND_EXPR, stype,
+                                                       var, mask));
          append_to_statement_list (stmt, &list);
-
-         var = tmp;
+         var = stmp;
        }
 
-      if (mask)
+      /* After shifting and masking, convert to the target type.  */
+      utmp = stmp;
+      if (!useless_type_conversion_p (utype, stype))
        {
-         if (!unsignedp
-             || (TYPE_MAIN_VARIANT (TREE_TYPE (dst))
-                 != TYPE_MAIN_VARIANT (utype)))
-           tmp = make_rename_temp (utype, "SR");
-         else
-           tmp = dst;
+         utmp = make_rename_temp (utype, "SR");
 
-         stmt = build_gimple_modify_stmt (tmp,
-                                          fold_build2 (BIT_AND_EXPR, utype,
-                                                       var, mask));
+         stmt = build_gimple_modify_stmt (utmp, fold_convert (utype, var));
          append_to_statement_list (stmt, &list);
 
-         var = tmp;
+         var = utmp;
        }
 
+      /* Perform sign extension, if required.
+        ???  This should never be necessary.  */
       if (!unsignedp)
        {
          tree signbit = int_const_binop (LSHIFT_EXPR,
                                          build_int_cst_wide (utype, 1, 0),
-                                         size_binop (MINUS_EXPR, cst2,
-                                                     bitsize_int (1)),
-                                         true);
+                                         size_binop (MINUS_EXPR, width,
+                                                     bitsize_int (1)), 0);
 
-         tmp = make_rename_temp (utype, "SR");
-         stmt = build_gimple_modify_stmt (tmp,
+         stmt = build_gimple_modify_stmt (utmp,
                                           fold_build2 (BIT_XOR_EXPR, utype,
                                                        var, signbit));
          append_to_statement_list (stmt, &list);
 
-         var = tmp;
-
-         if (TYPE_MAIN_VARIANT (TREE_TYPE (dst)) != TYPE_MAIN_VARIANT (utype))
-           tmp = make_rename_temp (utype, "SR");
-         else
-           tmp = dst;
-
-         stmt = build_gimple_modify_stmt (tmp,
+         stmt = build_gimple_modify_stmt (utmp,
                                           fold_build2 (MINUS_EXPR, utype,
-                                                       var, signbit));
+                                                       utmp, signbit));
          append_to_statement_list (stmt, &list);
 
-         var = tmp;
+         var = utmp;
        }
 
-      if (var != dst)
+      /* Finally, move and convert to the destination.  */
+      if (!useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (var)))
        {
          if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
            var = fold_convert (TREE_TYPE (dst), var);
          else
            var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
-
-         stmt = build_gimple_modify_stmt (dst, var);
-         append_to_statement_list (stmt, &list);
        }
+      stmt = build_gimple_modify_stmt (dst, var);
+      append_to_statement_list (stmt, &list);
 
       return list;
     }