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]

Re: A new patch for floating point conditional mov on PPo


> 
> 
> 
>   In message <199806100253.WAA14356@jwlab.FEITH.COM>you write:
>   > 1) What prevents gcc from accidently matching the fcmov test / compare
>   >    insns by adding a clobber to an existing compare insn?  There's a note
>   >    in md.texi about the combiner adding / deleting clobber expressions
>   >    as necessary.
> Yes, the compiler will add clobbers if doing so makes a pattern
> match.  Thus we can not depend on the existance of a clobber to
> distinguish between two patterns that can be created by combine.

How aboutt this new output_int_test_compare_fcmov? It checks for
fcmov. If it doesn't find fcmov, it treats the pattern as the
normal test/compare.

BTW, does that mean we have to check it in the normal normal
test/compare patterns since the compiler may delete clobbers.
But why does the compiler delete clobbers? They are in patterns
because they are used in the code generation. Is that a compiler
bug?

> 
> 
>   > 2) In output_int_test_compare_fcmov you have:
>   > 
>   >      if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
>   >        output = reverse;
>   >      else
>   >        output = normal;
>   > 
>   >   a) I believe that the patterns require operand 0 to be a
>   >      nonimmediate_operand in which case how can CONSTANT_P
>   >      ever be true?
> I've run into a couple cases where reload doesn't check predicates
> and blindly allows invalid RTL for a predicate.
> 
> However, I think these cases are internal to reload and are fixed
> up before reload finishes.
> 
> One thought would be to abort for these cases that we think can
> not happen.  That way if they do happen we'll know about them
> intead of silently generating incorrect code.

I will leave it alone since the same code is in the normal test/compare
patterns. We should fix all of them, not some of them.



-- 
H.J. Lu (hjl@gnu.org)
-----
/* For floating point conditional move, output integer test/comparison
   code for INSN to compare OPERANDS. If TEST is 1, output for test;
   otherwise for comparison. We also check if the pattern is generated
   by accident. If true, treat it as the normal test/compare. */

char *
output_int_test_compare_for_fcmov (insn, operands, test)
     rtx insn;
     rtx *operands;
     int test;
{
  enum machine_mode mode = GET_MODE (operands [0]);
  rtx cc0_user;
  int fcmov;
  enum {gen_test, reverse, normal} output;

  cc0_user = next_cc0_user (insn);
  if (cc0_user
      && GET_CODE (PATTERN (cc0_user)) == SET
      && SET_DEST (PATTERN (cc0_user)) != pc_rtx
      && GET_CODE (SET_SRC (PATTERN (cc0_user))) == IF_THEN_ELSE
      && (GET_MODE_CLASS (GET_MODE (SET_DEST (PATTERN (cc0_user))))
	  == MODE_FLOAT))
    fcmov = 1;
  else
    fcmov = 0;

  if (test)
    {
      operands[2] = operands [1];
      if (REG_P (operands[0]))
	{
	  output = gen_test;
	}
      else
	{
	  output = normal;
	  operands[1] = const0_rtx;
	}
    }
  else
    {
      if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
	{
	  output = reverse;
	  /* Check if we get here by accident. */
	  if (!fcmov)
	    cc_status.flags |= CC_REVERSED;
	}
      else
	{
	  output = normal;
	}
    }

  switch (mode)
    {
    case SImode:
      switch (output)
	{
	case gen_test:
	  output_asm_insn (AS2 (test%L0,%0,%0), operands);
	  break;
	case normal:
	  output_asm_insn (AS2 (cmp%L0,%1,%0), operands);
	  break;
	case reverse:
	  output_asm_insn (AS2 (cmp%L0,%0,%1), operands);
	  break;
	}
      break;

    case HImode:
      switch (output)
	{
	case gen_test:
	  output_asm_insn (AS2 (test%W0,%0,%0), operands);
	  break;
	case normal:
	  output_asm_insn (AS2 (cmp%W0,%1,%0), operands);
	  break;
	case reverse:
	  output_asm_insn (AS2 (cmp%W0,%0,%1), operands);
	  break;
	}
      break;

    case QImode:
      switch (output)
	{
	case gen_test:
	  output_asm_insn (AS2 (test%B0,%0,%0), operands);
	  break;
	case normal:
	  output_asm_insn (AS2 (cmp%B0,%1,%0), operands);
	  break;
	case reverse:
	  output_asm_insn (AS2 (cmp%B0,%0,%1), operands);
	  break;
	}
      break;

    default:
      abort ();
  }

  /* The next CC user should be the floating point conditional move.
     We have to be very careful since the the floating point
     conditional move doesn't support signed integer comparison.
     We have to fake it. */
  if (fcmov)
    {
      /* We have to convert it to something fcmovxx can handle. */
      switch (GET_CODE (XEXP (SET_SRC (PATTERN (cc0_user)), 0)))
	{
	case GE:
	  if (output == reverse)
	    output_asm_insn (AS1 (setl,%b2), operands);
	  else
	    output_asm_insn (AS1 (setge,%b2), operands);
	  output_asm_insn (AS2 (test%B2,%b2,%b2), operands);
	  break;

	case GT:
	  if (output == reverse)
	    output_asm_insn (AS1 (setle,%b2), operands);
	  else
	    output_asm_insn (AS1 (setg,%b2), operands);
	  output_asm_insn (AS2 (test%B2,%b2,%b2), operands);
	  break;

	case LE:
	  if (output == reverse)
	    output_asm_insn (AS1 (setg,%b2), operands);
	  else
	    output_asm_insn (AS1 (setle,%b2), operands);
	  output_asm_insn (AS2 (test%B2,%b2,%b2), operands);
	  break;

	case LT:
	  if (output == reverse)
	    output_asm_insn (AS1 (setge,%b2), operands);
	  else
	    output_asm_insn (AS1 (setl,%b2), operands);
	  output_asm_insn (AS2 (test%B2,%b2,%b2), operands);
	  break;

	default:
	  break;
	}
    }

  return "";
}


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