[PATCH] PR 15825: emit_move_insn problems in ifcvt.c

Roger Sayle roger@eyesopen.com
Mon Jun 7 16:54:00 GMT 2004


The following patch is my proposed solution to PR middle-end/15825
which is an unrecognizable insn ICE from valid code on
powerpc-apple-darwin7.4.0.

The problem is that we try applying if-conversion, noce_try_sign_mask,
to a basic block whose single instruction is a complex store_flag insn.

Hence if_info->insn_a contains

(insn 61 60 32 2 (parallel [
            (set (reg:SI 118 [ iftmp.0 ])
                (eq:SI (reg/v:SI 121 [ unsigned_p ])
                    (const_int 0 [0x0])))
            (clobber (scratch:SI))
        ]) 413 {*rs6000.md:11584} (nil)
    (expr_list:REG_DEAD (reg/v:SI 121 [ unsigned_p ])
        (expr_list:REG_UNUSED (scratch:SI)
            (nil))))

and whose if_info->a contains

	(eq:SI (reg/v:SI 121 [ unsigned_p ])
                    (const_int 0 [0x0]))


The trouble is that noce_emit_move_insn (and indeed emit_move_insn)
are unable to generate a suitable move instruction for the contents
of if_info->a.  The rs6000 backend only recognizes these instructions
when the contain the additional necessary clobbers.


It's unclear if this is just a problem to noce_try_sign_mask or a
more generic problem that noce_process_if_block should reject attempting
to ifcvt such complex basic blocks.  Currently noce_process_if_block
just uses single_set which ignores any prerequisite clobbers.

In this patch I assume that there is some advantage to processing these
blocks.  Conditional execution optimizations that don't attempt to
synthesize instructions to manipulate these complex operands should be
fine.  In which case, it is for the optimizations that do need to
generate moves to store these values in pseudos, to each check that
they can.

I'm not sure if there's a predicate function, such as emit_move_operand_p,
that can be portably used to detect that an operand may be stored in a
new pseudo using emit_move_insn.  Instead, I use the heuristics that
emit_move_insn is safe, if the original instruction was a naked SET,
or we're moving a pseudo register or a constant integer, that I believe
are required to be supported by the backend.  Perhaps someone more
familiar with this part of GCC could tell me a better way to do this?


The following patch has been tested against mainline on both
i686-pc-linux-gnu and powerpc-apple-darwin7.4.0 with a complete "make
bootstrap", all default languages, and regression tested with a top-level
"make -k check" with no new failures.  [Actually there were some extra
Thread related failures in libjava on darwin, but I'm unsure if these
are expected and/or whether the machine was loaded during my testing].

Ok for mainline?



2004-06-07  Roger Sayle  <roger@eyesopen.com>

	PR middle-end/15825
	* ifcvt.c (noce_try_sign_mask): Check that "t" is either a simple
	operand, or came from a naked SET instruction.

	* gcc.dg/pr15825-1.c: New test case.


Index: ifcvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ifcvt.c,v
retrieving revision 1.145
diff -c -3 -p -r1.145 ifcvt.c
*** ifcvt.c	13 May 2004 06:39:43 -0000	1.145
--- ifcvt.c	7 Jun 2004 04:36:13 -0000
*************** noce_try_sign_mask (struct noce_if_info
*** 1725,1737 ****
      {
        if ((code == LT && c == const0_rtx)
  	  || (code == LE && c == constm1_rtx))
! 	t = if_info->b;
      }
    else if (if_info->b == const0_rtx)
      {
        if ((code == GE && c == const0_rtx)
  	  || (code == GT && c == constm1_rtx))
! 	t = if_info->a;
      }

    if (! t || side_effects_p (t))
--- 1725,1757 ----
      {
        if ((code == LT && c == const0_rtx)
  	  || (code == LE && c == constm1_rtx))
! 	{
! 	  t = if_info->b;
!
! 	  /* If insn_b isn't a simple set insn and t isn't a simple operand
! 	     we may not be able to generate the necessary clobbers required
! 	     by the backend to store "t" in a new pseudo.  */
! 	  if (GET_CODE (PATTERN (if_info->insn_b)) != SET
! 	      && !(REG_P (t) && REGNO (t) >= FIRST_PSEUDO_REGISTER)
! 	      && GET_CODE (t) != CONST_INT)
! 	    return FALSE;
! 	}
      }
    else if (if_info->b == const0_rtx)
      {
        if ((code == GE && c == const0_rtx)
  	  || (code == GT && c == constm1_rtx))
! 	{
! 	  t = if_info->a;
!
! 	  /* If insn_a isn't a simple set insn and t isn't a simple operand
! 	     we may not be able to generate the necessary clobbers required
! 	     by the backend to store "t" in a new pseudo.  */
! 	  if (GET_CODE (PATTERN (if_info->insn_a)) != SET
! 	      && !(REG_P (t) && REGNO (t) >= FIRST_PSEUDO_REGISTER)
! 	      && GET_CODE (t) != CONST_INT)
! 	    return FALSE;
! 	}
      }

    if (! t || side_effects_p (t))

/* PR middle-end/15825 */
/* { dg-do compile } */
/* { dg-options "-O2" } */

unsigned int foo(long long high, int unsigned_p)
{
  int i;
  if (high < 0)
    if (!unsigned_p)
    {
      i = 1;
      goto t;
    }
  i = 0;
t:
  return i;
}


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



More information about the Gcc-patches mailing list