This is the mail archive of the gcc@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]

MIPS: comparison modes in conditional branches


Hi,

I am trying to understand why the MIPS backend's handling of
comparison modes seems to be different from what rtl.texi says:

  The mode of the comparison operation is independent of the mode
  of the data being compared.  If the comparison operation is being tested
  (e.g., the first operand of an @code{if_then_else}), the mode must be
  @code{VOIDmode}.

In the MIPS backend conditional branches based on integer comparisons
are valid only if the mode of the comparison matches the mode of the
operands, e.g. in 64-bit mode (if_then_else (eq:DI (reg:DI 1)
(const_int 0)) ...).

This is relevant because combine could optimize this:

  (set (reg:DI 2) (and:DI (reg:DI 1) (const_int 1)))
  (set (reg:SI 3) (truncate:SI (reg:DI 2)))
  (set (pc) (if_then_else (eq:SI (reg:SI 3) (const_int 0)) ...))

into this:

  (set (reg:DI 2) (and:DI (regDI 1) (const_int 1)))
  (set (pc) (if_then_else (eq:SI (reg:DI 2) (const_int 0)) ...))

I think this is a valid transformation on MIPS64 too.  In fact I
believe that as long as we compare valid SImode or DImode values the
64-bit comparison should work fine.

If I remove the comparison modes from the conditional branch patterns
regression testing on mips64-elf does not show any problem (diff is
attached for reference).  When I however compare the assembly output
it is clear that some of the changes are incorrect.  This is
a simplified testcase illustrating the problem:

  f (long long a)
  {
    if ((a & 0xffffffff) != 0)
      abort ();
  }
  
  long long a = 0x1234567800000000LL;
  main ()
  {
    f (a);
  }

What happens is that combine.c:simplify_comparison <AND> noticing the
zero-extension transforms this:

  (ne:DI (and:DI (reg:DI 4) (const_int 0xffffffff)) (const_int 0))

into this:

  (ne:DI (reg:SI 4) (const_int 0))

And now we do allow comparison like this in conditional branches.

On targets where DI->SI mode-switch is not a nop I think the
transformation in simplify_comparison is incorrect.  We need an
explicit truncate here to enforce valid SI values:

  (ne:DI (truncate:SI (reg:DI 4)) (const_int 0)).

Now if I am correct and this last thing is really a bug then the
obvious question is whether it has anything to do with the more
restrictive form for conditional branches on MIPS64?  And of course if
I fix it then whether it would be OK to lift the mode restrictions in
the conditional branch patterns.

Thanks,
Adam

Attachment: cmpmodes.diff
Description: Text document


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