diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a9720018fae..c8e74f5c58a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2008-02-27 Richard Guenther + + 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 * c-ppoutput.c (scan_translation_unit): Handle CPP_PRAGMA diff --git a/gcc/expr.c b/gcc/expr.c index 36741918fb3..79a039a529f 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 1ecd2255e4a..f6a73efe9ad 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 8f652d21218..3435b5bfb42 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-02-27 Richard Guenther + + PR middle-end/34971 + * gcc.c-torture/execute/pr34971.c: New testcase. + 2008-02-27 Jakub Jelinek * 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 00000000000..3299aee22c9 --- /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; +}