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]

[commit, spu] Fix PR target/50310 (unordered vector compares)


Hello,

the pr50310 test cases are failing on SPU with internal compiler errors.
It seems that if the back-end provides a vcond pattern, it must support
all comparison operations, including unordered ones which are missing
in the SPU implementation.

Since we don't actually have any specific instruction support for those
operations on SPU, the following patch open-codes their semantics.

Tested on spu-elf, fixes the pr50310 test cases.
Committed to mainline.

Bye,
Ulrich


ChangeLog:

	PR target/50310
	* config/spu/spu.c (spu_emit_vector_compare): Support unordered
	floating-point comparisons.


Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c	(revision 180156)
--- gcc/config/spu/spu.c	(working copy)
*************** spu_emit_vector_compare (enum rtx_code r
*** 6415,6427 ****
            try_again = true;
            break;
          case NE:
            /* Treat A != B as ~(A==B).  */
            {
              enum insn_code nor_code;
!             rtx eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
              nor_code = optab_handler (one_cmpl_optab, dest_mode);
              gcc_assert (nor_code != CODE_FOR_nothing);
!             emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
              if (dmode != dest_mode)
                {
                  rtx temp = gen_reg_rtx (dest_mode);
--- 6415,6438 ----
            try_again = true;
            break;
          case NE:
+ 	case UNEQ:
+ 	case UNLE:
+ 	case UNLT:
+ 	case UNGE:
+ 	case UNGT:
+ 	case UNORDERED:
            /* Treat A != B as ~(A==B).  */
            {
+ 	    enum rtx_code rev_code;
              enum insn_code nor_code;
! 	    rtx rev_mask;
! 
! 	    rev_code = reverse_condition_maybe_unordered (rcode);
!             rev_mask = spu_emit_vector_compare (rev_code, op0, op1, dest_mode);
! 
              nor_code = optab_handler (one_cmpl_optab, dest_mode);
              gcc_assert (nor_code != CODE_FOR_nothing);
!             emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
              if (dmode != dest_mode)
                {
                  rtx temp = gen_reg_rtx (dest_mode);
*************** spu_emit_vector_compare (enum rtx_code r
*** 6466,6471 ****
--- 6477,6524 ----
              return mask;
            }
            break;
+         case LTGT:
+           /* Try LT OR GT */
+           {
+             rtx lt_rtx, gt_rtx;
+             enum insn_code ior_code;
+ 
+             lt_rtx = spu_emit_vector_compare (LT, op0, op1, dest_mode);
+             gt_rtx = spu_emit_vector_compare (GT, op0, op1, dest_mode);
+ 
+             ior_code = optab_handler (ior_optab, dest_mode);
+             gcc_assert (ior_code != CODE_FOR_nothing);
+             emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
+             if (dmode != dest_mode)
+               {
+                 rtx temp = gen_reg_rtx (dest_mode);
+                 convert_move (temp, mask, 0);
+                 return temp;
+               }
+             return mask;
+           }
+           break;
+         case ORDERED:
+           /* Implement as (A==A) & (B==B) */
+           {
+             rtx a_rtx, b_rtx;
+             enum insn_code and_code;
+ 
+             a_rtx = spu_emit_vector_compare (EQ, op0, op0, dest_mode);
+             b_rtx = spu_emit_vector_compare (EQ, op1, op1, dest_mode);
+ 
+             and_code = optab_handler (and_optab, dest_mode);
+             gcc_assert (and_code != CODE_FOR_nothing);
+             emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
+             if (dmode != dest_mode)
+               {
+                 rtx temp = gen_reg_rtx (dest_mode);
+                 convert_move (temp, mask, 0);
+                 return temp;
+               }
+             return mask;
+           }
+           break;
          default:
            gcc_unreachable ();
          }
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


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