aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-02-27 09:50:04 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-02-27 09:50:04 +0000
commit70582b3afe47248d2b70c5731fb7cf44fa17dc16 (patch)
treeef16ed7af638323b496055d922dbdc8e19ef42aa /gcc
parenta15f0fd02870fef9742d517d0894e02bdd0bbdb3 (diff)
downloadgcc-70582b3afe47248d2b70c5731fb7cf44fa17dc16.zip
gcc-70582b3afe47248d2b70c5731fb7cf44fa17dc16.tar.gz
gcc-70582b3afe47248d2b70c5731fb7cf44fa17dc16.tar.bz2
re PR middle-end/34971 (bitfield rotates are folded and expanded wrong)
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. * gcc.c-torture/execute/pr34971.c: New testcase. From-SVN: r132706
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/expr.c10
-rw-r--r--gcc/fold-const.c15
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr34971.c22
5 files changed, 54 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a972001..c8e74f5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/expr.c b/gcc/expr.c
index 3674191..79a039a 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -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. */
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 1ecd225..f6a73ef 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8f652d2..3435b5b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..3299aee
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr34971.c
@@ -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;
+}