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
This commit is contained in:
Richard Guenther 2008-02-27 09:50:04 +00:00 committed by Richard Biener
parent a15f0fd028
commit 70582b3afe
5 changed files with 54 additions and 7 deletions

View File

@ -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

View File

@ -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. */

View File

@ -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)

View File

@ -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.

View File

@ -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;
}