My apologies to Mark. It turns out that the constant folding
optimization in PR 15069 triggers latent problems throughout the
compiler, not only in the C++ front-end but also in the middle-end.
Clearly, the NOP_EXPR vs. CONVERT_EXPR distinction is being blurred,
even though this may be completely unrelated to the bug in DOM! There
may even be problems in RTL expansion and/or the RTL optimizers.
Conclusion: Can of worms.
2004-05-30 Roger Sayle <roger@eyesopen.com>
PR middle-end/15069
* fold-const.c (fold_single_bit_test): Only perform "(X & C) != 0"
into "X < 0" (where C is the signbit) if X's type is a full mode.
* g++.dg/opt/fold3.C: New test case.
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.383
diff -c -3 -p -r1.383 fold-const.c
*** fold-const.c 28 May 2004 16:37:00 -0000 1.383
--- fold-const.c 30 May 2004 03:53:59 -0000
*************** fold_single_bit_test (enum tree_code cod
*** 5433,5439 ****
/* If we have (A & C) != 0 where C is the sign bit of A, convert
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
! if (arg00 != NULL_TREE)
{
tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
--- 5433,5443 ----
/* If we have (A & C) != 0 where C is the sign bit of A, convert
this into A < 0. Similarly for (A & C) == 0 into A >= 0. */
arg00 = sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1));
! if (arg00 != NULL_TREE
! /* This is only a win if casting to a signed type is cheap,
! i.e. when arg00's type is not a partial mode. */
! && TYPE_PRECISION (TREE_TYPE (arg00))
! == GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg00))))
{
tree stype = lang_hooks.types.signed_type (TREE_TYPE (arg00));
return fold (build2 (code == EQ_EXPR ? GE_EXPR : LT_EXPR,
*************** fold_single_bit_test (enum tree_code cod
*** 5441,5450 ****
fold_convert (stype, integer_zero_node)));
}
- /* At this point, we know that arg0 is not testing the sign bit. */
- if (TYPE_PRECISION (type) - 1 == bitnum)
- abort ();
-
/* Otherwise we have (A & C) != 0 where C is a single bit,
convert that into ((A >> C2) & 1). Where C2 = log2(C).
Similarly for (A & C) == 0. */
--- 5445,5450 ----
// PR middle-end/15069
// { dg-do run }
// { dg-options "-O2" }
extern "C" void abort (void);
typedef enum {
FOUR = 4,
FIVE = 5
} direction_t;
int main ()
{
direction_t four = FOUR;
int flags = (four & 4L) ? (32L | 128L) : 0;
flags &= 32L;
if (flags == 0)
abort ();
}
Roger
--
Roger Sayle, E-mail: roger@eyesopen.com
OpenEye Scientific Software, WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road, Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507. Fax: (+1) 505-473-0833