aboutsummaryrefslogtreecommitdiff
path: root/gcc/fold-const.c
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/fold-const.c
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/fold-const.c')
-rw-r--r--gcc/fold-const.c15
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)