OSDN Git Service

PR target/50310
authoruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 12:17:35 +0000 (12:17 +0000)
committeruweigand <uweigand@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 12:17:35 +0000 (12:17 +0000)
* config/spu/spu.c (spu_emit_vector_compare): Support unordered
floating-point comparisons.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180184 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/spu/spu.c

index edaa4b7..115c5d9 100644 (file)
@@ -1,3 +1,9 @@
+2011-10-19  Ulrich Weigand  <Ulrich.Weigand@de.ibm.com>
+
+       PR target/50310
+       * config/spu/spu.c (spu_emit_vector_compare): Support unordered
+       floating-point comparisons.
+
 2011-10-19  Jan Hubicka  <jh@suse.cz>
 
        * cgraphunit.c (handle_alias_pairs): Also handle wekref with destination
index 3baa2eb..734c2be 100644 (file)
@@ -6415,13 +6415,24 @@ spu_emit_vector_compare (enum rtx_code rcode,
           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 eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
+           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, eq_rtx));
+            emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
             if (dmode != dest_mode)
               {
                 rtx temp = gen_reg_rtx (dest_mode);
@@ -6466,6 +6477,48 @@ spu_emit_vector_compare (enum rtx_code rcode,
             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 ();
         }