This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR middle-end/15069: Partial mode type conversions

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.

The issue revolves around support for integer types that are partial
machine modes. In the PR, an enumerated type that is three bits wide.
In theory, GCC internally should be able to handle these types,
but being as rare as they are they seem to uncover numerous latent

The first bug is that given an "unsigned" type that was three bits
wide, the C++ front-end's "signed_type" lang hook didn't return a
type of the same precision.  However as revealed by Mark, fixing
this doesn't resolve the failure but just exposes another bug
further down stream.

This second (potentially of many) is that tree-ssa's .t21.dom1 pass
strips away the conversion from "unsigned three-bit type" to "signed
three-bit type", which then misoptimizes the test case.

I haven't begun investigating DOM's failure yet, but a quick inspection
of convert and fold_convert reveals that interconversion between these
unsigned/signed types are represented with NOP_EXPRs (as they both have
the same TYPE_MAIN_VARIANT) even though they always need code generated
to perform the conversions.

	3-bit signed -> unsigned:	X = Y & 7;
	3-bit unsigned -> signed:	X = ((Y & 7) ^ 4) - 4;

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.

All of these issues need to be resolved.  However, for the time being
I propose the solution below, of disabling the problematic constant
folding transformation when the type is a partial mode/submode.  It
turns out that this transformation probably isn't a win in these cases,
avoids all of the latent downstream bugs, and most importantly its
suitable for gcc 3.4.1.

I'd still like to see Mark's patch applied to mainline (once the
TREE_UNSIGNED -> TYPE_UNSIGNED typos are corrected :) so that
the tree-ssa guru's and I can investigate the problems with DOM
and/or CONVERT_EXPR/NOP_EXPR issues, etc...

The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.

Ok for mainline and 3.4.1?

2004-05-30  Roger Sayle  <>

	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 Sayle,                         E-mail:
OpenEye Scientific Software,         WWW:
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]