This is the mail archive of the gcc-patches@gcc.gnu.org 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/19874: Tweak STRIP_USELESS_TYPE_CONVERSION


The following patch is my proposed change to resolve PR middle-end/19874
which is an ICE-on-valid regression on mainline caused by emit_move_insn
being passed incompatible modes for source and destination.  The problem,
analaysed by Jakub Jelinek was that STRIP_USELESS_TYPE_CONVERSION was
stripping a mode changing conversion due to lang_hooks.types_compatible_p
for the C/C++ front-ends claiming that two types were compatible as they
have the same TYPE_MAIN_VARIANT.

Jakub's suggested fix, described in the bugzilla PR, was to tweak the
handle_mode_attribute function in c-common.c and comptypes function in
c-typeck.c, to change "types_compatible_p", which unfortunately breaks
the C++ front-end.

The alternate solution below is to tweak tree_ssa_useless_type_conversion
such that no conversion that changes the mode of it's operand is
considered "useless".  This intuitive approach also simplifies the code
in that function, which guarantees the modes match in every case except
for the front-end's notion of type compatability.  Indeed, I'm not sure
the front-end's type system should be affecting the optimizations
performed at this point in tree-ssa.

This approach is probably contentious, so I'll check with folks whether
they feel this fix is too conservative and potentially misses useful
optimizations.


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.  Jakub's testcase passes with this
patch but fails without it.

Ok for mainline?



2005-02-24  Roger Sayle  <roger@eyesopen.com>

	PR middle-end/19874
	* tree-ssa.c (tree_ssa_useless_type_conversion_1): A conversion
	between different machine modes is never a "useless" conversion.

2005-02-24  Jakub Jelinek  <jakub@redhat.com>

	* gcc.c-torture/execute/20050119-2.c: New test case.


Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa.c,v
retrieving revision 2.78
diff -c -3 -p -r2.78 tree-ssa.c
*** tree-ssa.c	23 Feb 2005 05:08:24 -0000	2.78
--- tree-ssa.c	24 Feb 2005 00:06:13 -0000
*************** delete_tree_ssa (void)
*** 778,788 ****
  bool
  tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
  {
    /* If the inner and outer types are effectively the same, then
       strip the type conversion and enter the equivalence into
       the table.  */
!   if (inner_type == outer_type
!      || (lang_hooks.types_compatible_p (inner_type, outer_type)))
      return true;

    /* If both types are pointers and the outer type is a (void *), then
--- 778,794 ----
  bool
  tree_ssa_useless_type_conversion_1 (tree outer_type, tree inner_type)
  {
+   if (inner_type == outer_type)
+     return true;
+
+   /* Changes in machine mode are never useless conversions.  */
+   if (TYPE_MODE (inner_type) != TYPE_MODE (outer_type))
+     return false;
+
    /* If the inner and outer types are effectively the same, then
       strip the type conversion and enter the equivalence into
       the table.  */
!   if (lang_hooks.types_compatible_p (inner_type, outer_type))
      return true;

    /* If both types are pointers and the outer type is a (void *), then
*************** tree_ssa_useless_type_conversion_1 (tree
*** 793,799 ****
       implement the ABI.  */
    else if (POINTER_TYPE_P (inner_type)
             && POINTER_TYPE_P (outer_type)
- 	   && TYPE_MODE (inner_type) == TYPE_MODE (outer_type)
  	   && TYPE_REF_CAN_ALIAS_ALL (inner_type)
  	      == TYPE_REF_CAN_ALIAS_ALL (outer_type)
  	   && TREE_CODE (TREE_TYPE (outer_type)) == VOID_TYPE)
--- 799,804 ----
*************** tree_ssa_useless_type_conversion_1 (tree
*** 803,809 ****
       so strip conversions that just switch between them.  */
    else if (POINTER_TYPE_P (inner_type)
             && POINTER_TYPE_P (outer_type)
- 	   && TYPE_MODE (inner_type) == TYPE_MODE (outer_type)
  	   && TYPE_REF_CAN_ALIAS_ALL (inner_type)
  	      == TYPE_REF_CAN_ALIAS_ALL (outer_type)
             && lang_hooks.types_compatible_p (TREE_TYPE (inner_type),
--- 808,813 ----
*************** tree_ssa_useless_type_conversion_1 (tree
*** 819,825 ****
       mean that testing of precision is necessary.  */
    else if (INTEGRAL_TYPE_P (inner_type)
             && INTEGRAL_TYPE_P (outer_type)
- 	   && TYPE_MODE (inner_type) == TYPE_MODE (outer_type)
  	   && TYPE_UNSIGNED (inner_type) == TYPE_UNSIGNED (outer_type)
  	   && TYPE_PRECISION (inner_type) == TYPE_PRECISION (outer_type))
      {
--- 823,828 ----

/* PR middle-end/19874 */
typedef enum { A, B, C, D } E;

struct S {
  E __attribute__ ((mode (__byte__))) a;
  E __attribute__ ((mode (__byte__))) b;
  E __attribute__ ((mode (__byte__))) c;
  E __attribute__ ((mode (__byte__))) d;
};

extern void abort (void);
extern void exit (int);

E
foo (struct S *s)
{
  if (s->a != s->b)
    abort ();
  if (s->c != C)
    abort ();
  return s->d;
}

int
main (void)
{
  struct S s[2];
  s[0].a = B;
  s[0].b = B;
  s[0].c = C;
  s[0].d = D;
  s[1].a = D;
  s[1].b = C;
  s[1].c = B;
  s[1].d = A;
  if (foo (s) != D)
    abort ();
  exit (0);
}


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


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