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: rs6000 fsel bug fix


My previous patch to rs6000_emit_cmove didn't address the entire
problem of mode mismatching.  Here's a case that still ICEs:

float els, azs;
void x(void)
{
   if ( fabs(els) > fabs(azs))
     azs = fabs(els) * ((azs > 0 ) ? 1 : -1);
}

The following patch separates compare_mode and result_mode, propagates
them correctly, and makes sure everything matches as expected.
Bootstrapping on Darwin.  (Patch also supplied as an attachment,
in anticipation that my mailer may screw up the line breaks.)

Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.305
diff -u -d -b -w -c -3 -p -r1.305 rs6000.c
cvs server: conflicting specifications of output style
*** rs6000.c    12 Apr 2002 16:57:47 -0000      1.305
--- rs6000.c    12 Apr 2002 18:13:24 -0000
*************** rs6000_emit_cmove (dest, op, true_cond,
*** 7239,7247 ****
     rtx op0 = rs6000_compare_op0;
     rtx op1 = rs6000_compare_op1;
     REAL_VALUE_TYPE c1;
!   enum machine_mode mode = GET_MODE (op0);
     rtx temp;

     /* First, work out if the hardware can do this at all, or
        if it's too slow...  */
     /* If the comparison is an integer one, since we only have fsel
--- 7239,7256 ----
     rtx op0 = rs6000_compare_op0;
     rtx op1 = rs6000_compare_op1;
     REAL_VALUE_TYPE c1;
!   enum machine_mode compare_mode = GET_MODE (op0);
!   enum machine_mode result_mode = GET_MODE (dest);
     rtx temp;

+   /* These modes should always match. */
+   if ( GET_MODE (op1) != compare_mode )
+     return 0;
+   if ( GET_MODE (true_cond) != result_mode )
+     return 0;
+   if ( GET_MODE (false_cond) != result_mode )
+     return 0;
+
     /* First, work out if the hardware can do this at all, or
        if it's too slow...  */
     /* If the comparison is an integer one, since we only have fsel
*************** rs6000_emit_cmove (dest, op, true_cond,
*** 7284,7294 ****
     /* At this point we know we can use fsel.  */

     /* Reduce the comparison to a comparison against zero.  */
!   temp = gen_reg_rtx (mode);
     emit_insn (gen_rtx_SET (VOIDmode, temp,
!                         gen_rtx_MINUS (mode, op0, op1)));
     op0 = temp;
!   op1 = CONST0_RTX (mode);

     /* If we don't care about NaNs we can reduce some of the comparisons
        down to faster ones.  */
--- 7293,7303 ----
     /* At this point we know we can use fsel.  */

     /* Reduce the comparison to a comparison against zero.  */
!   temp = gen_reg_rtx (compare_mode);
     emit_insn (gen_rtx_SET (VOIDmode, temp,
!                         gen_rtx_MINUS (compare_mode, op0, op1)));
     op0 = temp;
!   op1 = CONST0_RTX (compare_mode);

     /* If we don't care about NaNs we can reduce some of the comparisons
        down to faster ones.  */
*************** rs6000_emit_cmove (dest, op, true_cond,
*** 7318,7369 ****
         break;

       case LE:
!       temp = gen_reg_rtx (mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
         op0 = temp;
         break;

       case ORDERED:
!       temp = gen_reg_rtx (mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (mode, op0)));
         op0 = temp;
         break;

       case EQ:
!       temp = gen_reg_rtx (mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_NEG (mode,
!                                          gen_rtx_ABS (mode, op0))));
         op0 = temp;
         break;

       case UNGE:
!       temp = gen_reg_rtx (mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_IF_THEN_ELSE (mode,
                                                     gen_rtx_GE (VOIDmode,
                                                                 op0, op1),
                                                     true_cond, false_cond)
));
         false_cond = temp;
         true_cond = false_cond;

!       temp = gen_reg_rtx (mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
         op0 = temp;
         break;

       case GT:
!       temp = gen_reg_rtx (mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_IF_THEN_ELSE (mode,
                                                     gen_rtx_GE (VOIDmode,
                                                                 op0, op1),
                                                     true_cond, false_cond)
));
         true_cond = temp;
         false_cond = true_cond;

!       temp = gen_reg_rtx (mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (mode, op0)));
         op0 = temp;
         break;

--- 7327,7378 ----
         break;

       case LE:
!       temp = gen_reg_rtx (compare_mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode,
  op0)));
         op0 = temp;
         break;

       case ORDERED:
!       temp = gen_reg_rtx (compare_mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_ABS (compare_mode,
  op0)));
         op0 = temp;
         break;

       case EQ:
!       temp = gen_reg_rtx (compare_mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_NEG (compare_mode,
!                                          gen_rtx_ABS (compare_mode, op0)
)));
         op0 = temp;
         break;

       case UNGE:
!       temp = gen_reg_rtx (result_mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_IF_THEN_ELSE (result_mode,
                                                     gen_rtx_GE (VOIDmode,
                                                                 op0, op1),
                                                     true_cond, false_cond)
));
         false_cond = temp;
         true_cond = false_cond;

!       temp = gen_reg_rtx (compare_mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode,
  op0)));
         op0 = temp;
         break;

       case GT:
!       temp = gen_reg_rtx (result_mode);
         emit_insn (gen_rtx_SET (VOIDmode, temp,
!                             gen_rtx_IF_THEN_ELSE (result_mode,
                                                     gen_rtx_GE (VOIDmode,
                                                                 op0, op1),
                                                     true_cond, false_cond)
));
         true_cond = temp;
         false_cond = true_cond;

!       temp = gen_reg_rtx (compare_mode);
!       emit_insn (gen_rtx_SET (VOIDmode, temp, gen_rtx_NEG (compare_mode,
  op0)));
         op0 = temp;
         break;

*************** rs6000_emit_cmove (dest, op, true_cond,
*** 7372,7378 ****
       }

     emit_insn (gen_rtx_SET (VOIDmode, dest,
!                         gen_rtx_IF_THEN_ELSE (GET_MODE (dest),
                                                 gen_rtx_GE (VOIDmode,
                                                             op0, op1),
                                                 true_cond, false_cond)));
--- 7381,7387 ----
       }

     emit_insn (gen_rtx_SET (VOIDmode, dest,
!                         gen_rtx_IF_THEN_ELSE (result_mode,
                                                 gen_rtx_GE (VOIDmode,
                                                             op0, op1),
                                                 true_cond, false_cond)));

Attachment: patch1
Description: Binary data



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