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]

sCOND update for FP comparisons


This patch does the following:

1. Fix a bug where
   (set (reg:SI xxx) (unge:SI (reg:CCFP yyy) (const_int 0)))
   caused incorrect code generation.  The pattern actually doesn't
   exist in the machine, so the rewrite just prevents it from being
   generated & recognized.  This was a latent bug triggered by
   rs6000-iselslowmath.patch.
2. It makes the condition code complement operation a separate insn,
   rather than using %D, so it can be scheduled and in
   future combined with other condition code logical operations (this
   doesn't work now, because the required instructions aren't in the
   md file and possibly because combine doesn't know how to generate
   them if they did exist).
3. It makes the sCOND patterns actually work and actually be generated
   in all cases for FP operations.  I know this is not really the best
   thing in general, but I think a complete solution will want to
   generate CR moves or branches depending on the processor in use
   and the certainty of prediction of the branch, and you can't
   do that if CR moves don't work to start with.

Bootstrapped & tested on powerpc-darwin.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/rs6000-sccfp.patch========================
2003-05-03  Geoffrey Keating  <geoffk@apple.com>

	* config/rs6000/rs6000.c (scc_comparison_operator): Make equivalent
	to branch_positive_comparison_operator.
	(ccr_bit): Check that sCOND conditions are actually a positive bit.
	(print_operand): Remove %D substitution.
	(rs6000_emit_sCOND): Generate complement operation to ensure that
	sCOND input is a positive bit.
	* config/rs6000/rs6000.md: Rearrange sCOND templates to be in the
	same order as bCOND, and add the missing ones.  Remove the %D
	substitutions from the scc patterns.

Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.466
diff -u -p -u -p -r1.466 rs6000.c
--- config/rs6000/rs6000.c	2 May 2003 18:36:50 -0000	1.466
+++ config/rs6000/rs6000.c	3 May 2003 20:44:04 -0000
@@ -7049,34 +7049,15 @@ branch_positive_comparison_operator (op,
 	  || code == UNORDERED);
 }
 
-/* Return 1 if OP is a comparison operation that is valid for an scc insn.
-   We check the opcode against the mode of the CC value and disallow EQ or
-   NE comparisons for integers.  */
+/* Return 1 if OP is a comparison operation that is valid for an scc
+   insn: it must be a positive comparison.  */
 
 int
 scc_comparison_operator (op, mode)
      rtx op;
      enum machine_mode mode;
 {
-  enum rtx_code code = GET_CODE (op);
-  enum machine_mode cc_mode;
-
-  if (GET_MODE (op) != mode && mode != VOIDmode)
-    return 0;
-
-  if (GET_RTX_CLASS (code) != '<')
-    return 0;
-
-  cc_mode = GET_MODE (XEXP (op, 0));
-  if (GET_MODE_CLASS (cc_mode) != MODE_CC)
-    return 0;
-
-  validate_condition_mode (code, cc_mode);
-
-  if (code == NE && cc_mode != CCFPmode)
-    return 0;
-
-  return 1;
+  return branch_positive_comparison_operator (op, mode);
 }
 
 int
@@ -7501,6 +7482,12 @@ ccr_bit (op, scc_p)
 
   validate_condition_mode (code, cc_mode);
 
+  /* When generating a sCOND operation, only positive conditions are
+     allowed.  */
+  if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED
+      && code != GTU && code != LTU)
+    abort ();
+  
   switch (code)
     {
     case NE:
@@ -7697,42 +7684,6 @@ print_operand (file, x, code)
       /* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
 	 output_operand.  */
 
-    case 'D':
-      /* There used to be a comment for 'C' reading "This is an
-	   optional cror needed for certain floating-point
-	   comparisons.  Otherwise write nothing."  */
-
-      /* Similar, except that this is for an scc, so we must be able to
-	 encode the test in a single bit that is one.  We do the above
-	 for any LE, GE, GEU, or LEU and invert the bit for NE.  */
-      if (GET_CODE (x) == LE || GET_CODE (x) == GE
-	  || GET_CODE (x) == LEU || GET_CODE (x) == GEU)
-	{
-	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-	  fprintf (file, "cror %d,%d,%d\n\t", base_bit + 3,
-		   base_bit + 2,
-		   base_bit + (GET_CODE (x) == GE || GET_CODE (x) == GEU));
-	}
-
-      else if (GET_CODE (x) == NE)
-	{
-	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-	  fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 3,
-		   base_bit + 2, base_bit + 2);
-	}
-      else if (TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT
-	       && GET_CODE (x) == EQ
-	       && GET_MODE (XEXP (x, 0)) == CCFPmode)
-	{
-	  int base_bit = 4 * (REGNO (XEXP (x, 0)) - CR0_REGNO);
-
-	  fprintf (file, "crnor %d,%d,%d\n\t", base_bit + 1,
-		   base_bit + 1, base_bit + 1);
-	}
-      return;
-
     case 'E':
       /* X is a CR register.  Print the number of the EQ bit of the CR */
       if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
@@ -8686,8 +8637,28 @@ rs6000_emit_sCOND (code, result)
 {
   rtx condition_rtx;
   enum machine_mode op_mode;
+  enum rtx_code cond_code;
 
   condition_rtx = rs6000_generate_compare (code);
+  cond_code = GET_CODE (condition_rtx);
+
+  if (cond_code == NE
+      || cond_code == GE || cond_code == LE
+      || cond_code == GEU || cond_code == LEU
+      || cond_code == ORDERED || cond_code == UNGE || cond_code == UNLE)
+    {
+      rtx not_result = gen_reg_rtx (CCEQmode);
+      rtx not_op, rev_cond_rtx;
+      enum machine_mode cc_mode;
+      
+      cc_mode = GET_MODE (XEXP (condition_rtx, 0));
+
+      rev_cond_rtx = gen_rtx (rs6000_reverse_condition (cc_mode, cond_code),
+			      SImode, XEXP (condition_rtx, 0), const0_rtx);
+      not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
+      emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
+      condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
+    }
 
   op_mode = GET_MODE (rs6000_compare_op0);
   if (op_mode == VOIDmode)
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.251
diff -u -p -u -p -r1.251 rs6000.md
--- config/rs6000/rs6000.md	2 May 2003 14:49:51 -0000	1.251
+++ config/rs6000/rs6000.md	3 May 2003 20:44:05 -0000
@@ -10919,8 +10919,8 @@
   DONE;
 }")
 
-;; A > 0 is best done using the portable sequence, so fail in that case.
-(define_expand "sgt"
+;; A >= 0 is best done the portable way for A an integer.
+(define_expand "sge"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
@@ -10929,26 +10929,26 @@
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (GT, operands[0]); 
+  rs6000_emit_sCOND (GE, operands[0]);
   DONE;
 }")
 
-;; A < 0 is best done in the portable way for A an integer.
-(define_expand "slt"
+;; A > 0 is best done using the portable sequence, so fail in that case.
+(define_expand "sgt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
 {
-  if (! rs6000_compare_fp_p 
+  if (! rs6000_compare_fp_p
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (LT, operands[0]); 
+  rs6000_emit_sCOND (GT, operands[0]); 
   DONE;
 }")
 
-;; A >= 0 is best done the portable way for A an integer.
-(define_expand "sge"
+;; A <= 0 is best done the portable way for A an integer.
+(define_expand "sle"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
@@ -10957,43 +10957,84 @@
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (GE, operands[0]);
+  rs6000_emit_sCOND (LE, operands[0]); 
   DONE;
 }")
 
-;; A <= 0 is best done the portable way for A an integer.
-(define_expand "sle"
+;; A < 0 is best done in the portable way for A an integer.
+(define_expand "slt"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "
 {
-  if (! rs6000_compare_fp_p
+  if (! rs6000_compare_fp_p 
       && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
     FAIL;
 
-  rs6000_emit_sCOND (LE, operands[0]); 
+  rs6000_emit_sCOND (LT, operands[0]); 
   DONE;
 }")
 
+(define_expand "sgeu"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+
 (define_expand "sgtu"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "{ rs6000_emit_sCOND (GTU, operands[0]); DONE; }")
 
+(define_expand "sleu"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+
 (define_expand "sltu"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
   "{ rs6000_emit_sCOND (LTU, operands[0]); DONE; }")
 
-(define_expand "sgeu"
+(define_expand "sunordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
-  "{ rs6000_emit_sCOND (GEU, operands[0]); DONE; }")
+  "{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
 
-(define_expand "sleu"
+(define_expand "sordered"
   [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
   ""
-  "{ rs6000_emit_sCOND (LEU, operands[0]); DONE; }")
+  "{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
+
+(define_expand "suneq"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
+
+(define_expand "sunge"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
+
+(define_expand "sungt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
+
+(define_expand "sunle"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
+
+(define_expand "sunlt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
+
+(define_expand "sltgt"
+  [(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
+  ""
+  "{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
+
 
 ;; Here are the actual compare insns.
 (define_insn "*cmpsi_internal1"
@@ -11141,7 +11182,7 @@
 			   [(match_operand 2 "cc_reg_operand" "y")
 			    (const_int 0)]))]
   ""
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
@@ -11150,7 +11191,7 @@
   [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
 	(unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_OV))]
   "TARGET_ISEL"
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
@@ -11160,7 +11201,7 @@
 			   [(match_operand 2 "cc_reg_operand" "y")
 			    (const_int 0)]))]
   "TARGET_POWERPC64"
-  "%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
+  "mfcr %0\;{rlinm|rlwinm} %0,%0,%J1,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
 
@@ -11174,7 +11215,7 @@
 	(match_op_dup 1 [(match_dup 2) (const_int 0)]))]
   "! TARGET_POWERPC64"
   "@
-   %D1mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
+   mfcr %3\;{rlinm.|rlwinm.} %3,%3,%J1,1
    #"
   [(set_attr "type" "delayed_compare")
    (set_attr "length" "12,16")])
@@ -11216,7 +11257,7 @@
   operands[4] = GEN_INT (count);
   operands[5] = GEN_INT (put_bit);
 
-  return \"%D1mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
+  return \"mfcr %0\;{rlinm|rlwinm} %0,%0,%4,%5,%5\";
 }"
   [(set_attr "type" "mfcr")
    (set_attr "length" "12")])
@@ -11251,7 +11292,7 @@
   operands[5] = GEN_INT (count);
   operands[6] = GEN_INT (put_bit);
 
-  return \"%D1mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
+  return \"mfcr %4\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
 }"
   [(set_attr "type" "delayed_compare")
    (set_attr "length" "12,16")])
@@ -11289,7 +11330,7 @@
 			   [(match_operand 5 "cc_reg_operand" "y")
 			    (const_int 0)]))]
   "REGNO (operands[2]) != REGNO (operands[5])"
-  "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+  "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "20")])
 
@@ -11303,7 +11344,7 @@
 			   [(match_operand 5 "cc_reg_operand" "y")
 			    (const_int 0)]))]
   "TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
-  "%D1%D4mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
+  "mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
   [(set_attr "type" "mfcr")
    (set_attr "length" "20")])
 
============================================================


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