diff options
author | Richard Guenther <rguenther@suse.de> | 2008-02-27 09:50:04 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2008-02-27 09:50:04 +0000 |
commit | 70582b3afe47248d2b70c5731fb7cf44fa17dc16 (patch) | |
tree | ef16ed7af638323b496055d922dbdc8e19ef42aa /gcc | |
parent | a15f0fd02870fef9742d517d0894e02bdd0bbdb3 (diff) | |
download | gcc-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/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/expr.c | 10 | ||||
-rw-r--r-- | gcc/fold-const.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/execute/pr34971.c | 22 |
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 @@ -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; +} |