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/fold-const.c | |
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/fold-const.c')
-rw-r--r-- | gcc/fold-const.c | 15 |
1 files changed, 10 insertions, 5 deletions
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) |