OSDN Git Service

2008-02-27 Richard Guenther <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 27 Feb 2008 09:50:04 +0000 (09:50 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 27 Feb 2008 09:50:04 +0000 (09:50 +0000)
PR middle-end/34971
* expr.c (expand_expr_real_1): Assert on rotates that operate
on partial modes.
* fold-const.c (fold_binary): Use the types precision, not the
bitsize of the mode if folding rotate expressions.  Build rotates
only for full modes.

* gcc.c-torture/execute/pr34971.c: New testcase.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@132706 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr34971.c [new file with mode: 0644]

index a972001..c8e74f5 100644 (file)
@@ -1,3 +1,12 @@
+2008-02-27  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/34971
+       * expr.c (expand_expr_real_1): Assert on rotates that operate
+       on partial modes.
+       * fold-const.c (fold_binary): Use the types precision, not the
+       bitsize of the mode if folding rotate expressions.  Build rotates
+       only for full modes.
+
 2008-02-27  Jakub Jelinek  <jakub@redhat.com>
 
        * c-ppoutput.c (scan_translation_unit): Handle CPP_PRAGMA
index 3674191..79a039a 100644 (file)
@@ -8898,10 +8898,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     case BIT_XOR_EXPR:
       goto binop;
 
-    case LSHIFT_EXPR:
-    case RSHIFT_EXPR:
     case LROTATE_EXPR:
     case RROTATE_EXPR:
+      /* The expansion code only handles expansion of mode precision
+        rotates.  */
+      gcc_assert (GET_MODE_PRECISION (TYPE_MODE (type))
+                 == TYPE_PRECISION (type));
+
+      /* Falltrough.  */
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
       /* If this is a fixed-point operation, then we cannot use the code
         below because "expand_shift" doesn't support sat/no-sat fixed-point
          shifts.   */
index 1ecd225..f6a73ef 100644 (file)
@@ -9886,13 +9886,18 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
         is a rotate of A by B bits.  */
       {
        enum tree_code code0, code1;
+       tree rtype;
        code0 = TREE_CODE (arg0);
        code1 = TREE_CODE (arg1);
        if (((code0 == RSHIFT_EXPR && code1 == LSHIFT_EXPR)
             || (code1 == RSHIFT_EXPR && code0 == LSHIFT_EXPR))
            && operand_equal_p (TREE_OPERAND (arg0, 0),
                                TREE_OPERAND (arg1, 0), 0)
-           && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (arg0, 0))))
+           && (rtype = TREE_TYPE (TREE_OPERAND (arg0, 0)),
+               TYPE_UNSIGNED (rtype))
+           /* Only create rotates in complete modes.  Other cases are not
+              expanded properly.  */
+           && TYPE_PRECISION (rtype) == GET_MODE_PRECISION (TYPE_MODE (rtype)))
          {
            tree tree01, tree11;
            enum tree_code code01, code11;
@@ -11636,7 +11641,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
       if (code == LROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST)
        {
          tree tem = build_int_cst (TREE_TYPE (arg1),
-                                   GET_MODE_BITSIZE (TYPE_MODE (type)));
+                                   TYPE_PRECISION (type));
          tem = const_binop (MINUS_EXPR, tem, arg1, 0);
          return fold_build2 (RROTATE_EXPR, type, op0, tem);
        }
@@ -11655,8 +11660,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
                            fold_build2 (code, type,
                                         TREE_OPERAND (arg0, 1), arg1));
 
-      /* Two consecutive rotates adding up to the width of the mode can
-        be ignored.  */
+      /* Two consecutive rotates adding up to the precision of the
+        type can be ignored.  */
       if (code == RROTATE_EXPR && TREE_CODE (arg1) == INTEGER_CST
          && TREE_CODE (arg0) == RROTATE_EXPR
          && TREE_CODE (TREE_OPERAND (arg0, 1)) == INTEGER_CST
@@ -11664,7 +11669,7 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
          && TREE_INT_CST_HIGH (TREE_OPERAND (arg0, 1)) == 0
          && ((TREE_INT_CST_LOW (arg1)
               + TREE_INT_CST_LOW (TREE_OPERAND (arg0, 1)))
-             == (unsigned int) GET_MODE_BITSIZE (TYPE_MODE (type))))
+             == (unsigned int) TYPE_PRECISION (type)))
        return TREE_OPERAND (arg0, 0);
 
       /* Fold (X & C2) << C1 into (X << C1) & (C2 << C1)
index 8f652d2..3435b5b 100644 (file)
@@ -1,3 +1,8 @@
+2008-02-27  Richard Guenther  <rguenther@suse.de>
+
+       PR middle-end/34971
+       * gcc.c-torture/execute/pr34971.c: New testcase.
+
 2008-02-27  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/gomp/preprocess-1.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr34971.c b/gcc/testsuite/gcc.c-torture/execute/pr34971.c
new file mode 100644 (file)
index 0000000..3299aee
--- /dev/null
@@ -0,0 +1,22 @@
+struct foo
+{
+  unsigned long long b:40;
+} x;
+
+extern void abort (void);
+
+void test1(unsigned long long res)
+{
+  /* Build a rotate expression on a 40 bit argument.  */
+  if ((x.b<<8) + (x.b>>32) != res)
+    abort ();
+}
+
+int main()
+{
+  x.b = 0x0100000001;
+  test1(0x0000000101);
+  x.b = 0x0100000000;
+  test1(0x0000000001);
+  return 0;
+}