public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* A patch for PPro
       [not found] <199805131005.KAA00076@iron.rcp.co.uk>
@ 1998-05-15  1:48 ` H.J. Lu
  0 siblings, 0 replies; 4+ messages in thread
From: H.J. Lu @ 1998-05-15  1:48 UTC (permalink / raw)
  To: grahams; +Cc: wilson, egcs

> I reported a couple of bugs concerning bootstraping
> egcs-19980428 using "-O6 -march=pentiumpro
>  -mcpu=pentiumpro -fexpensive-optimizations".
> 
> The bootstrap failed due to diffs in all the object files
> between stage2 and stage3.
> 
> I managed to identify that its the compilation of
> init_reg_sets_1() in gcc/regclass.c that results in the
> differences.
> 

Hi,

This patch seems to fix all the PPro bugs I have known. Please
give a try and let me know what you get.

Jim, can you take a look at it? Thanks.

BTW, it is against egcs in CVS on 980509. I will send in some test
cases tomorrow.


H.J.
---
Wed May 13 17:36:28 1998  H.J. Lu  (hjl@gnu.org)

	* reg-stack.c (subst_stack_regs_pat): Make sure the top of
	stack is the destination for conditional move insn.

	* config/i386/i386.c (expand_fp_conditional_move): New function
	to expand fp conditional move.
	(expand_int_conditional_move): New function to expand integer
	conditional move.
	(output_fp_conditional_move): New function to output fp
	conditional move.
	(output_int_conditional_move): New function to output integer
	conditional move.

	* config/i386/i386.md (movsicc, movhicc): Call
	expand_int_conditional_move () to expand int conditional move.
	(movsicc_1, movhicc_1): Use "nonimmediate_operand" as predicate
	for input, call output_int_conditional_move () to output int
	conditional move.
	(movsfcc, movdfcc, movxfcc): Use "t" as constraint for output,
	use "register_operand" as predicate for input and call
	expand_fp_conditional_move () to expand fp conditional move.
	(movxfcc_1, movdfcc_1, movxfcc_1): Use "nonimmediate_operand"
	as predicate for input, use "register_operand" as predicate for
	output and call output_fp_conditional_move () to output fp
	conditional move.
	(movsicc, movhicc, movsicc_1, movhicc_1, movsfcc, movdfcc,
	movxfcc, movxfcc_1, movdfcc_1, movxfcc_1): Enable.

Mon May 11 08:04:17 1998  H.J. Lu  (hjl@gnu.org)

	* config/i386/i386.c (output_float_compare): Fix the unordered
	comparison for IEEE math and CC_FCOMI.

Fri May  8 07:53:43 1998  H.J. Lu  (hjl@gnu.org)

	* config/i386/i386.c (put_condition_code): In INT mode, check
	cc_prev_status.flags & CC_NO_OVERFLOW for GE and LT.
	(output_int_conditional_move): Likewise for GT and LE.

Index: config/i386/i386.md
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.1.1.15
diff -u -r1.1.1.15 i386.md
--- i386.md	1998/05/09 20:34:36	1.1.1.15
+++ i386.md	1998/05/14 18:22:56
@@ -7225,260 +7226,120 @@
 
 /* Conditional move define_insns.  */
 
-;; These are all disabled, because they are buggy.  They are all susceptible
-;; to problems with input reloads clobbering the condition code registers.
-;; It appears the only safe way to write a integer/FP conditional move pattern
-;; is to write one which emits both the compare and the cmov, and which can be
-;; split only after reload.
-
 (define_expand "movsicc"
   [(match_dup 4)
-   (parallel [(set (match_operand 0 "register_operand" "")
+   (set (match_operand 0 "register_operand" "")
 	(if_then_else:SI (match_operand 1 "comparison_operator" "")
 			 (match_operand:SI 2 "general_operand" "")
-			 (match_operand:SI 3 "general_operand" "")))
-   (clobber (match_scratch:SI 4 "=&r"))])]
-  "0 && TARGET_CMOVE"
+			 (match_operand:SI 3 "general_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
-  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+  expand_int_conditional_move (operands);
 }")
 
 (define_expand "movhicc"
   [(match_dup 4)
-   (parallel [(set (match_operand 0 "register_operand" "")
+   (set (match_operand 0 "register_operand" "")
 	(if_then_else:HI (match_operand 1 "comparison_operator" "")
 			 (match_operand:HI 2 "general_operand" "")
-			 (match_operand:HI 3 "general_operand" "")))
-   (clobber (match_scratch:SI 4 "=&r"))])]
-  "0 && TARGET_CMOVE"
+			 (match_operand:HI 3 "general_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
-  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+  expand_int_conditional_move (operands);
 }")
 
 (define_insn "movsicc_1"
-  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,&r,rm")
+  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,&r")
 	(if_then_else:SI (match_operator 1 "comparison_operator" 
 				[(cc0) (const_int 0)])
-		      (match_operand:SI 2 "general_operand" "rm,0,rm,g")
-		      (match_operand:SI 3 "general_operand" "0,rm,rm,g")))
-   (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
-  "0 && TARGET_CMOVE"
-  "*
-{
-  if (which_alternative == 0)
-    {
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-    }
-  else if (which_alternative == 1)
-    {
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 2)
-    {
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 3)
-    {
-      /* r <- cond ? arg1 : arg2 */
-    rtx xops[3];
-
-    xops[0] = gen_label_rtx ();
-    xops[1] = gen_label_rtx ();
-    xops[2] = operands[1];
-
-    output_asm_insn (\"j%c2 %l0\", xops);
-    if (! rtx_equal_p (operands[0], operands[2]))
-       if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
-         {
-           output_asm_insn (AS2 (mov%z2,%2,%4), operands);
-           output_asm_insn (AS2 (mov%z2,%4,%0), operands);
-         }
-       else
-      output_asm_insn (AS2 (mov%z0,%2,%0), operands);
-    output_asm_insn (\"jmp %l1\", xops);
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
-    if (! rtx_equal_p (operands[0], operands[3]))
-      {
-        if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
-          {
-            output_asm_insn (AS2 (mov%z3,%3,%4), operands);
-            output_asm_insn (AS2 (mov%z3,%4,%0), operands);
-          }
-        else
-      output_asm_insn (AS2 (mov%z0,%3,%0), operands);
-      }
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
-    }  
-  RET;
-}")
+		      (match_operand:SI 2 "nonimmediate_operand" "rm,0,rm")
+		      (match_operand:SI 3 "nonimmediate_operand" "0,rm,rm")))]
+  "TARGET_CMOVE"
+  "* return output_int_conditional_move (which_alternative, operands);")
 
 (define_insn "movhicc_1"
-  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm")
+  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r")
 	(if_then_else:HI (match_operator 1 "comparison_operator" 
 				[(cc0) (const_int 0)])
-		      (match_operand:HI 2 "general_operand" "rm,0,rm,g")
-		      (match_operand:HI 3 "general_operand" "0,rm,rm,g")))
-   (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
-  "0 && TARGET_CMOVE"
-  "*
-{
-  if (which_alternative == 0)
-    {
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-    }
-  else if (which_alternative == 1)
-    {
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 2)
-    {
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 3)
-    {
-      /* r <- cond ? arg1 : arg2 */
-    rtx xops[3];
-
-    xops[0] = gen_label_rtx ();
-    xops[1] = gen_label_rtx ();
-    xops[2] = operands[1];
-
-    output_asm_insn (\"j%c2 %l0\", xops);
-    if (! rtx_equal_p (operands[0], operands[2]))
-       if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
-         {
-           output_asm_insn (AS2 (mov%z2,%2,%4), operands);
-           output_asm_insn (AS2 (mov%z2,%4,%0), operands);
-         }
-       else
-      output_asm_insn (AS2 (mov%z0,%2,%0), operands);
-    output_asm_insn (\"jmp %l1\", xops);
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
-    if (! rtx_equal_p (operands[0], operands[3]))
-      {
-        if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
-          {
-            output_asm_insn (AS2 (mov%z3,%3,%4), operands);
-            output_asm_insn (AS2 (mov%z3,%4,%0), operands);
-          }
-        else
-      output_asm_insn (AS2 (mov%z0,%3,%0), operands);
-      }
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
-    }  
-  RET;
-}")
+		      (match_operand:HI 2 "nonimmediate_operand" "rm,0,rm")
+		      (match_operand:HI 3 "nonimmediate_operand" "0,rm,rm")))]
+  "TARGET_CMOVE"
+  "* return output_int_conditional_move (which_alternative, operands);")
+
 ;; We need to disable the FP forms of these since they do not support
 ;; memory as written, but no input reloads are permitted for insns
 ;; that use cc0.  Also, movxfcc is not present.
 
+;; These are all disabled, because they are buggy.  They are all susceptible
+;; to problems with input reloads clobbering the condition code registers.
+;; It appears the only safe way to write a FP conditional move pattern
+;; is to write one which emits both the compare and the cmov, and which can be
+;; split only after reload.
+
 (define_expand "movsfcc"
   [(match_dup 4)
-   (set (match_operand 0 "register_operand" "")
+   (set (match_operand 0 "register_operand" "t")
 	(if_then_else:SF (match_operand 1 "comparison_operator" "")
-			 (match_operand:SF 2 "register_operand" "")
-			 (match_operand:SF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:SF 2 "general_operand" "")
+			 (match_operand:SF 3 "general_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
-  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+  expand_fp_conditional_move (operands);
 }")
 
 (define_expand "movdfcc"
   [(match_dup 4)
    (set (match_operand 0 "register_operand" "t")
 	(if_then_else:DF (match_operand 1 "comparison_operator" "")
-			 (match_operand:DF 2 "register_operand" "")
-			 (match_operand:DF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:DF 2 "general_operand" "")
+			 (match_operand:DF 3 "general_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
-  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+  expand_fp_conditional_move (operands);
 }")
 
 (define_expand "movxfcc"
   [(match_dup 4)
-   (set (match_operand 0 "register_operand" "")
+   (set (match_operand 0 "register_operand" "t")
 	(if_then_else:XF (match_operand 1 "comparison_operator" "")
-			 (match_operand:XF 2 "register_operand" "")
-			 (match_operand:XF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:XF 2 "general_operand" "")
+			 (match_operand:XF 3 "general_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
-  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+  expand_fp_conditional_move (operands);
 }")
 
 (define_insn "movsfcc_1"
-  [(set (match_operand:SF 0 "general_operand" "=f,f,&f")
+  [(set (match_operand:SF 0 "register_operand" "=f,=f,=f,=f")
 	(if_then_else:SF (match_operator 1 "comparison_operator" 
 					 [(cc0) (const_int 0)])
-			 (match_operand:SF 2 "register_operand" "0,f,f")
-			 (match_operand:SF 3 "register_operand" "f,0,f")))]
-  "0 && TARGET_CMOVE"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-    }
-
-  RET;
-}")
+			 (match_operand:SF 2 "nonimmediate_operand" "0,f,f,fFm")
+			 (match_operand:SF 3 "nonimmediate_operand" "f,0,f,fFm")))]
+  "TARGET_CMOVE"
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_insn "movdfcc_1"
-  [(set (match_operand:DF 0 "general_operand" "=f,f,&f")
+  [(set (match_operand:DF 0 "register_operand" "=f,=f,=f,=f")
 	(if_then_else:DF (match_operator 1 "comparison_operator" 
 					 [(cc0) (const_int 0)])
-			 (match_operand:DF 2 "register_operand" "0,f,f")
-			 (match_operand:DF 3 "register_operand" "f,0,f")))]
-  "0 && TARGET_CMOVE"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-    }
-
-  RET;
-}")
+			 (match_operand:DF 2 "nonimmediate_operand" "0,f,f,fFm")
+			 (match_operand:DF 3 "nonimmediate_operand" "f,0,f,fFm")))]
+  "TARGET_CMOVE"
+  "* return output_fp_conditional_move (which_alternative, operands);")
+
+(define_insn "movxfcc_1"
+  [(set (match_operand:XF 0 "register_operand" "=f,=f,=f,=f")
+	(if_then_else:XF (match_operator 1 "comparison_operator" 
+				[(cc0) (const_int 0)])
+		      (match_operand:XF 2 "nonimmediate_operand" "0,f,f,fFm")
+		      (match_operand:XF 3 "nonimmediate_operand" "f,0,f,fFm")))]
+  "TARGET_CMOVE"
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_insn "strlensi_unroll"
   [(set (match_operand:SI 0 "register_operand" "=&r,&r")
Index: config/i386/i386.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.1.1.15
diff -u -p -r1.1.1.15 i386.c
--- i386.c	1998/05/07 15:46:40	1.1.1.15
+++ i386.c	1998/05/14 19:51:14
@@ -3089,7 +3098,10 @@ put_condition_code (code, reverse_cc, mo
 	return;
 
       case GE:
-	fputs ("ge", file);
+	if (cc_prev_status.flags & CC_NO_OVERFLOW)
+	  fputs ("ns", file);
+	else
+	  fputs ("ge", file);
 	return;
 
       case GT:
@@ -3101,7 +3113,10 @@ put_condition_code (code, reverse_cc, mo
 	return;
 
       case LT:
-	fputs ("l", file);
+	if (cc_prev_status.flags & CC_NO_OVERFLOW)
+	  fputs ("s", file);
+	else
+	  fputs ("l", file);
 	return;
 
       case GEU:
@@ -4047,6 +4062,18 @@ output_float_compare (insn, operands)
 	    {
 	      output_asm_insn (AS2 (fucomip,%y1,%0), operands);
 	      output_asm_insn (AS1 (fstp, %y0), operands);
+
+	      if (TARGET_IEEE_FP)
+		{
+		  /* It is very tricky. We have to do it right. */
+		  rtx xops [1];
+
+		  xops [0] = gen_rtx_REG (QImode, 0);
+		  output_asm_insn (AS1 (setne,%b0), xops);
+		  output_asm_insn (AS1 (setp,%h0), xops);
+		  output_asm_insn (AS2 (or%B0,%h0,%b0), xops);
+		}
+
 	      return "";
 	    }
 	  else
@@ -4088,6 +4115,17 @@ output_float_compare (insn, operands)
       else if (cc_status.flags & CC_FCOMI) 
 	{
 	  output_asm_insn (strcat (buf, AS2 (%z1,%y1,%0)), operands);
+	  if (unordered_compare && TARGET_IEEE_FP)
+	    {
+	      /* It is very tricky. We have to do it right. */
+	      rtx xops [1];
+
+	      xops [0] = gen_rtx_REG (QImode, 0);
+	      output_asm_insn (AS1 (setne,%b0), xops);
+	      output_asm_insn (AS1 (setp,%h0), xops);
+	      output_asm_insn (AS2 (or%B0,%h0,%b0), xops);
+	    }
+
 	  return "";
 	}
       else
@@ -5123,4 +5161,290 @@ output_strlen_unroll (operands)
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
 
   return "";
+}
+
+char *
+output_fp_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  if (which_alternative == 0)
+    {
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+    }
+  else if (which_alternative == 1)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+    }
+  else if (which_alternative == 2)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+    }
+  else if (which_alternative == 3)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      rtx xops[3];
+
+      xops[0] = gen_label_rtx ();
+      xops[1] = gen_label_rtx ();
+      xops[2] = operands[1];
+
+      output_asm_insn ("j%f2 %l0", xops);
+      if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+	output_asm_insn (AS1 (fld%z2,%y2), operands);
+      else
+        {
+	  int conval = standard_80387_constant_p (operands[2]);
+    
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, "\tfldz\n");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, "\tfld1\n");
+	      break;
+	    default:
+#if 1
+	      abort ();
+#else
+	      operands[2] = CONST_DOUBLE_MEM (operands[2]);
+	      if (GET_CODE (operands[2]) != MEM)
+		abort ();
+	      output_asm_insn (AS1 (fld%z2,%y2), operands);
+#endif
+	      break;
+	    }
+	}
+      output_asm_insn ("jmp %l1", xops);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+      if (STACK_REG_P (operands[3]) || GET_CODE (operands[3]) == MEM)
+	  output_asm_insn (AS1 (fld%z3,%y3), operands);
+      else
+	{
+	  int conval = standard_80387_constant_p (operands[2]);
+    
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, "\tfldz\n");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, "\tfld1\n");
+	      break;
+	    default:
+#if 1
+	      abort ();
+#else
+	      operands[3] = CONST_DOUBLE_MEM (operands[3]);
+	      if (GET_CODE (operands[3]) != MEM)
+		abort ();
+	      output_asm_insn (AS1 (fld%z3,%y3), operands);
+#endif
+	      break;
+	    }
+	}
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+    }
+
+  return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  int code = GET_CODE (operands[1]);
+
+  if ((code == GT || code == LE)
+      && (cc_prev_status.flags & CC_NO_OVERFLOW))
+  return NULL_PTR;
+
+  if (which_alternative == 0)
+    {
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+    }
+  else if (which_alternative == 1)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+    }
+  else if (which_alternative == 2)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+    }
+  else if (which_alternative == 3)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      rtx xops[3];
+
+      xops[0] = gen_label_rtx ();
+      xops[1] = gen_label_rtx ();
+      xops[2] = operands[1];
+
+      output_asm_insn ("j%c2 %l0", xops);
+      if (! rtx_equal_p (operands[0], operands[2]))
+	{
+	  if (GET_CODE (operands[0]) == MEM
+	      && GET_CODE (operands[2]) == MEM)
+	    {
+	      output_asm_insn (AS2 (mov%z2,%2,%4), operands);
+	      output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+	    }
+	  else
+	    output_asm_insn (AS2 (mov%z0,%2,%0), operands);
+	}
+      output_asm_insn ("jmp %l1", xops);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+      if (! rtx_equal_p (operands[0], operands[3]))
+	{
+	  if (GET_CODE (operands[0]) == MEM
+	      && GET_CODE (operands[3]) == MEM)
+	    {
+	      output_asm_insn (AS2 (mov%z3,%3,%4), operands);
+	      output_asm_insn (AS2 (mov%z3,%4,%0), operands);
+	    }
+	  else
+	    output_asm_insn (AS2 (mov%z0,%3,%0), operands);
+	}
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+    }
+
+  return "";
+}
+
+void
+expand_fp_conditional_move (operands)
+     rtx operands[];
+{
+#undef CONSTANT_DOUBLE_P
+#define CONSTANT_DOUBLE_P(X) (GET_CODE ((X)) == CONST_DOUBLE)
+
+  /* We have 4 cases:
+
+     1. operand 2 is immediate and operand 3 is immediate.
+     2. operand 2 is immediate and operand 3 is non-immediate.
+     3. operand 3 is non-immediate and operand 3 is immediate.
+     4. operand 3 is non-immediate and operand 3 is non-immediate.
+   */
+  if ((reload_in_progress | reload_completed) == 0
+      && ((CONSTANT_DOUBLE_P (operands [2])
+	   && CONSTANT_DOUBLE_P (operands [3]))
+	  || (CONSTANT_DOUBLE_P (operands [2])
+	      && !CONSTANT_DOUBLE_P (operands [3]))
+ 	  || (!CONSTANT_DOUBLE_P (operands [2])
+	      && CONSTANT_DOUBLE_P (operands [3]))))
+    {
+      /* Case 1, 2 and 3. */
+      rtx fp_const, reg, insn, note;
+      int i, start, end;
+      enum machine_mode mode = GET_MODE (operands [0]);
+
+      if (flag_pic)
+	current_function_uses_pic_offset_table = 1;
+
+      /* Case 1. */
+      if (CONSTANT_DOUBLE_P (operands [2])
+	  && CONSTANT_DOUBLE_P (operands [3]))
+	{
+	  start = 2;
+	  end = 3;
+	}
+      else
+	{
+	   /* Case 2 and 3. */
+	   start = CONSTANT_DOUBLE_P (operands [2]) ? 2 : 3;
+	   end = start;
+	}
+
+	for (i = start; i <= end; i++)
+	  {
+	    fp_const = force_const_mem (mode, operands [i]);
+	    reg = gen_reg_rtx (mode);
+
+	    insn = emit_insn (gen_rtx_SET (mode, reg, fp_const));
+	    note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+	    if (note)
+	      XEXP (note, 0) = operands[i];
+	    else
+	      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+						    operands[i],
+						    REG_NOTES (insn));
+
+	    operands[i] = reg;
+	  }
+    }
+  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
+}
+
+void
+expand_int_conditional_move (operands)
+     rtx operands[];
+{
+#undef CONSTANT_INT_P(X)
+#define CONSTANT_INT_P(X) CONSTANT_P(X)
+
+  /* We have 4 cases:
+
+     1. operand 2 is immediate and operand 3 is immediate.
+     2. operand 2 is immediate and operand 3 is non-immediate.
+     3. operand 3 is non-immediate and operand 3 is immediate.
+     4. operand 3 is non-immediate and operand 3 is non-immediate.
+   */
+  if ((reload_in_progress | reload_completed) == 0
+      && ((CONSTANT_INT_P (operands [2])
+	   && CONSTANT_INT_P (operands [3]))
+	  || (CONSTANT_INT_P (operands [2])
+	      && !CONSTANT_INT_P (operands [3]))
+ 	  || (!CONSTANT_INT_P (operands [2])
+	      && CONSTANT_INT_P (operands [3]))))
+    {
+      /* Case 1, 2 and 3. */
+      rtx int_const, reg, insn, note;
+      int i, start, end;
+      enum machine_mode mode = GET_MODE (operands [0]);
+
+      if (flag_pic)
+	current_function_uses_pic_offset_table = 1;
+
+      /* Case 1. */
+      if (CONSTANT_INT_P (operands [2])
+	  && CONSTANT_INT_P (operands [3]))
+	{
+	  start = 2;
+	  end = 3;
+	}
+      else
+	{
+	   /* Case 2 and 3. */
+	   start = CONSTANT_INT_P (operands [2]) ? 2 : 3;
+	   end = start;
+	}
+
+	for (i = start; i <= end; i++)
+	  {
+	    int_const = force_const_mem (mode, operands [i]);
+	    reg = gen_reg_rtx (mode);
+
+	    insn = emit_insn (gen_rtx_SET (mode, reg, int_const));
+	    note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
+	    if (note)
+	      XEXP (note, 0) = operands[i];
+	    else
+	      REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL,
+						    operands[i],
+						    REG_NOTES (insn));
+
+	    operands[i] = reg;
+	  }
+    }
+  operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
 }
Index: reg-stack.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/reg-stack.c,v
retrieving revision 1.1.1.15
diff -u -r1.1.1.15 reg-stack.c
--- reg-stack.c	1998/05/06 20:59:12	1.1.1.15
+++ reg-stack.c	1998/05/14 00:34:48
@@ -2344,6 +2345,13 @@
       case IF_THEN_ELSE:
 	/* This insn requires the top of stack to be the destination. */
 
+	/* The comparison operator may not be FP comparison operator,
+	   which is handled correctly in compare_for_stack_reg ().
+	   We do a sanity check here. */
+	if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
+	    && REGNO (*dest) != regstack->reg[regstack->top])
+	  emit_swap_insn (insn, regstack, *dest);	
+
 	src1 = get_true_reg (&XEXP (SET_SRC (pat), 1));
 	src2 = get_true_reg (&XEXP (SET_SRC (pat), 2));
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: A patch for PPro
  1998-05-06 17:12 ` A patch for PPro H.J. Lu
  1998-05-06 18:14   ` Jeffrey A Law
@ 1998-05-07 15:31   ` Jim Wilson
  1 sibling, 0 replies; 4+ messages in thread
From: Jim Wilson @ 1998-05-07 15:31 UTC (permalink / raw)
  To: H.J. Lu; +Cc: law, scox, crux, egcs

I believe this patch is the wrong approach, because back-end files should
not be trying to use private data which is used in varasm.c internals.
That destroys modularity, and makes it harder to maintain gcc.  If we
really want to take this route, then we need to make this data public rather
than private, instead of adding hooks to allow other code to use varasm.c's
private data.  This situation is a little confusing because this private
data is not stored in static variables inside varasm.c, but rather in
the global RTL, but it is still private data.

In any case, I don't believe that this really fixes the problem.
There is a general problem that we can't support input reloads with an
insn using cc0, and there is no safe way to prevent generation of input
reloads.

I think the only safe fix is to modify the conditional move patterns to
emit both the compare and the conditional move, and split them after reload.

Jim

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: A patch for PPro
  1998-05-06 17:12 ` A patch for PPro H.J. Lu
@ 1998-05-06 18:14   ` Jeffrey A Law
  1998-05-07 15:31   ` Jim Wilson
  1 sibling, 0 replies; 4+ messages in thread
From: Jeffrey A Law @ 1998-05-06 18:14 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Jim Wilson, scox, crux, egcs

  In message < m0yX9fY-000268C@ocean.lucon.org >you write:
  > The current egcs in CVS disables fp conditional move for PPro. The
  > problem is mark_constants has to search inside a CONST_DOUBLE when it
  > is enabled. I understand it is not safe to do so. I am enclosing a
  > patch which will search inside a CONST_DOUBLE only for those PPro fp
  > conditional moves. It won't affect any other CPUs, even other x86
  > instructions.
The problem with conditional moves is much worse.  Jim outlined the
problems yesterday I believe.

You can also read the short comment before the floating point
conditional moves.

jeff

^ permalink raw reply	[flat|nested] 4+ messages in thread

* A patch for PPro
  1998-04-30 20:03 More fp bug in egcs Jim Wilson
@ 1998-05-06 17:12 ` H.J. Lu
  1998-05-06 18:14   ` Jeffrey A Law
  1998-05-07 15:31   ` Jim Wilson
  0 siblings, 2 replies; 4+ messages in thread
From: H.J. Lu @ 1998-05-06 17:12 UTC (permalink / raw)
  To: Jim Wilson; +Cc: law, scox, crux, egcs

Hi,

The current egcs in CVS disables fp conditional move for PPro. The
problem is mark_constants has to search inside a CONST_DOUBLE when it
is enabled. I understand it is not safe to do so. I am enclosing a
patch which will search inside a CONST_DOUBLE only for those PPro fp
conditional moves. It won't affect any other CPUs, even other x86
instructions.


H.J.
---
Wed May  6 07:35:26 1998  H.J. Lu  (hjl@gnu.org)

	* config/i386/i386.md (movsicc_1, movhicc_1): Use
	output_int_conditional_move ().
	(movxfcc_1, movdfcc_1, movxfcc_1): Fix typos, use
	output_fp_conditional_move () and allow constants for reload.

	* config/i386/i386.h (IS_SEARCH_CONST_DOUBLE_OK): New, defined
	as is_search_const_double_ok (insn).

	* config/i386/i386.c (output_fp_conditional_move): New function
	to hanld fp conditional move.
	(output_int_conditional_move): New function to handle integer
	conditional move.
	(is_search_const_double_ok): New function to check if it is ok
	search inside a CONST_DOUBLE used by INSN.

	* varasm.c (IS_SEARCH_CONST_DOUBLE_OK): New. True if it is ok
	to search inside a CONST_DOUBLE used by INSN. Default to false.
	(mark_constant_pool): Call mark_constants with a new arg,
	IS_SEARCH_CONST_DOUBLE_OK (insn).
	(mark_constants): Add a new arg to indicate if the instruction
	is ok to search inside a CONST_DOUBLE. Look inside CONST_DOUBLE
	if it is in memory and it is ok to do so.

	* print-rtl.c (get_insn_name): New. Return the insn name string
	if there is one, otherwise NULL.

	* rtl.h (get_insn_name): New declaration.

Index: config/i386/i386.md
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.md,v
retrieving revision 1.1.1.14
diff -u -r1.1.1.14 i386.md
--- config/i386/i386.md	1998/04/21 15:42:54	1.1.1.14
+++ config/i386/i386.md	1998/04/21 15:48:12
@@ -7259,58 +7260,7 @@
 		      (match_operand:SI 3 "general_operand" "0,rm,rm,g")))
    (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
   "TARGET_CMOVE"
-  "*
-{
-  if (which_alternative == 0)
-    {
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-    }
-  else if (which_alternative == 1)
-    {
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 2)
-    {
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 3)
-    {
-      /* r <- cond ? arg1 : arg2 */
-    rtx xops[3];
-
-    xops[0] = gen_label_rtx ();
-    xops[1] = gen_label_rtx ();
-    xops[2] = operands[1];
-
-    output_asm_insn (\"j%c2 %l0\", xops);
-    if (! rtx_equal_p (operands[0], operands[2]))
-       if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
-         {
-           output_asm_insn (AS2 (mov%z2,%2,%4), operands);
-           output_asm_insn (AS2 (mov%z2,%4,%0), operands);
-         }
-       else
-      output_asm_insn (AS2 (mov%z0,%2,%0), operands);
-    output_asm_insn (\"jmp %l1\", xops);
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
-    if (! rtx_equal_p (operands[0], operands[3]))
-      {
-        if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
-          {
-            output_asm_insn (AS2 (mov%z3,%3,%4), operands);
-            output_asm_insn (AS2 (mov%z3,%4,%0), operands);
-          }
-        else
-      output_asm_insn (AS2 (mov%z0,%3,%0), operands);
-      }
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
-    }  
-  RET;
-}")
+  "* return output_int_conditional_move (which_alternative, operands);")
 
 (define_insn "movhicc_1"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,&r,rm")
@@ -7320,69 +7270,26 @@
 		      (match_operand:HI 3 "general_operand" "0,rm,rm,g")))
    (clobber (match_scratch:SI 4 "X,X,X,=&r"))]
   "TARGET_CMOVE"
-  "*
-{
-  if (which_alternative == 0)
-    {
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-    }
-  else if (which_alternative == 1)
-    {
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 2)
-    {
-      /* r <- cond ? arg1 : arg2 */
-      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
-      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
-    }
-  else if (which_alternative == 3)
-    {
-      /* r <- cond ? arg1 : arg2 */
-    rtx xops[3];
-
-    xops[0] = gen_label_rtx ();
-    xops[1] = gen_label_rtx ();
-    xops[2] = operands[1];
-
-    output_asm_insn (\"j%c2 %l0\", xops);
-    if (! rtx_equal_p (operands[0], operands[2]))
-       if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[2]) == MEM)
-         {
-           output_asm_insn (AS2 (mov%z2,%2,%4), operands);
-           output_asm_insn (AS2 (mov%z2,%4,%0), operands);
-         }
-       else
-      output_asm_insn (AS2 (mov%z0,%2,%0), operands);
-    output_asm_insn (\"jmp %l1\", xops);
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[0]));
-    if (! rtx_equal_p (operands[0], operands[3]))
-      {
-        if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[3]) == MEM)
-          {
-            output_asm_insn (AS2 (mov%z3,%3,%4), operands);
-            output_asm_insn (AS2 (mov%z3,%4,%0), operands);
-          }
-        else
-      output_asm_insn (AS2 (mov%z0,%3,%0), operands);
-      }
-    ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (xops[1]));
-    }  
-  RET;
-}")
+  "* return output_int_conditional_move (which_alternative, operands);")
+
 ;; We need to disable the FP forms of these since they do not support
 ;; memory as written, but no input reloads are permitted for insns
 ;; that use cc0.  Also, movxfcc is not present.
 
+;; ??? We should add support for constant values to each of the mov*fcc
+;; patterns.  Apparently only values accepted by standard_80387_constant_p
+;; are valid.  We need to create a new predicate that accepts all
+;; nonimmediate_operand values plus those constants accepts by s_8_c_p.
+;; We need to add 'G' to the constraints where appropriate.  We need to
+;; add code to the alternative 3 cases that knows how to load such constants.
+
 (define_expand "movsfcc"
   [(match_dup 4)
-   (set (match_operand 0 "register_operand" "")
+   (set (match_operand 0 "register_operand" "t")
 	(if_then_else:SF (match_operand 1 "comparison_operator" "")
-			 (match_operand:SF 2 "register_operand" "")
-			 (match_operand:SF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:SF 2 "nonimmediate_operand" "")
+			 (match_operand:SF 3 "nonimmediate_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
   operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
@@ -7392,9 +7299,9 @@
   [(match_dup 4)
    (set (match_operand 0 "register_operand" "t")
 	(if_then_else:DF (match_operand 1 "comparison_operator" "")
-			 (match_operand:DF 2 "register_operand" "")
-			 (match_operand:DF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:DF 2 "nonimmediate_operand" "")
+			 (match_operand:DF 3 "nonimmediate_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
   operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
@@ -7404,75 +7311,40 @@
   [(match_dup 4)
    (set (match_operand 0 "register_operand" "")
 	(if_then_else:XF (match_operand 1 "comparison_operator" "")
-			 (match_operand:XF 2 "register_operand" "")
-			 (match_operand:XF 3 "register_operand" "")))]
-  "0 && TARGET_CMOVE"
+			 (match_operand:XF 2 "nonimmediate_operand" "")
+			 (match_operand:XF 3 "nonimmediate_operand" "")))]
+  "TARGET_CMOVE"
   "
 {
   operands[4] = i386_compare_gen (i386_compare_op0, i386_compare_op1);
 }")
 
 (define_insn "movsfcc_1"
-  [(set (match_operand:SF 0 "general_operand" "=f,f,&f")
+  [(set (match_operand:SF 0 "register_operand" "=f,=f,=f,=f")
 	(if_then_else:SF (match_operator 1 "comparison_operator" 
 					 [(cc0) (const_int 0)])
-			 (match_operand:SF 2 "register_operand" "0,f,f")
-			 (match_operand:SF 3 "register_operand" "f,0,f")))]
+			 (match_operand:SF 2 "nonimmediate_operand" "0,f,f,fFm")
+			 (match_operand:SF 3 "nonimmediate_operand" "f,0,f,fFm")))]
   "TARGET_CMOVE"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
-
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-    }
-
-  RET;
-}")
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_insn "movdfcc_1"
-  [(set (match_operand:DF 0 "general_operand" "=f,f,&f")
+  [(set (match_operand:DF 0 "register_operand" "=f,=f,=f,=f")
 	(if_then_else:DF (match_operator 1 "comparison_operator" 
 					 [(cc0) (const_int 0)])
-			 (match_operand:DF 2 "register_operand" "0,f,f")
-			 (match_operand:DF 3 "register_operand" "f,0,f")))]
+			 (match_operand:DF 2 "nonimmediate_operand" "0,f,f,fFm")
+			 (match_operand:DF 3 "nonimmediate_operand" "f,0,f,fFm")))]
   "TARGET_CMOVE"
-  "*
-{
-  switch (which_alternative)
-    {
-    case 0:
-      /* r <- cond ? arg : r */
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-
-    case 1:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      break;
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
-    case 2:
-      /* r <- cond ? r : arg */
-      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
-      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
-      break;
-    }
-
-  RET;
-}")
+(define_insn "movxfcc_1"
+  [(set (match_operand:XF 0 "register_operand" "=f,=f,=f,=f")
+	(if_then_else:XF (match_operator 1 "comparison_operator" 
+				[(cc0) (const_int 0)])
+		      (match_operand:XF 2 "nonimmediate_operand" "0,f,f,fFm")
+		      (match_operand:XF 3 "nonimmediate_operand" "f,0,f,fFm")))]
+  "TARGET_CMOVE"
+  "* return output_fp_conditional_move (which_alternative, operands);")
 
 (define_insn "strlensi_unroll"
   [(set (match_operand:SI 0 "register_operand" "=&r,&r")
Index: config/i386/i386.h
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.h,v
retrieving revision 1.1.1.15
diff -u -r1.1.1.15 i386.h
--- config/i386/i386.h	1998/04/21 15:42:51	1.1.1.15
+++ config/i386/i386.h	1998/05/06 18:08:55
@@ -817,6 +817,10 @@
 #define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C)  \
   ((C) == 'G' ? standard_80387_constant_p (VALUE) : 0)
 
+/* Is ok to search inside a CONST_DOUBLE? */
+#define IS_SEARCH_CONST_DOUBLE_OK(insn) \
+  is_search_const_double_ok (insn)
+
 /* Place additional restrictions on the register class to use when it
    is necessary to be able to hold a value of mode MODE in a reload
    register for which class CLASS would ordinarily be used. */
Index: config/i386/i386.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/config/i386/i386.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 i386.c
--- config/i386/i386.c	1998/05/05 22:04:03	1.1.1.13
+++ config/i386/i386.c	1998/05/06 18:07:22
@@ -5107,4 +5116,158 @@
   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[12]));
 
   return "";
+}
+
+char *
+output_fp_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  if (which_alternative == 0)
+    {
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+    }
+  else if (which_alternative == 1)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+    }
+  else if (which_alternative == 2)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (fcmov%F1,%2,%0), operands);
+      output_asm_insn (AS2 (fcmov%f1,%3,%0), operands);
+    }
+  else if (which_alternative == 3)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      rtx xops[3];
+
+      xops[0] = gen_label_rtx ();
+      xops[1] = gen_label_rtx ();
+      xops[2] = operands[1];
+
+      output_asm_insn ("j%f2 %l0", xops);
+      if (STACK_REG_P (operands[2]) || GET_CODE (operands[2]) == MEM)
+	output_asm_insn (AS1 (fld%z2,%y2), operands);
+      else
+        {
+	  int conval = standard_80387_constant_p (operands[2]);
+    
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, "\tfldz\n");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, "\tfld1\n");
+	      break;
+	    default:
+	      operands[2] = CONST_DOUBLE_MEM (operands[2]);
+	      if (GET_CODE (operands[2]) != MEM)
+		abort ();
+	      output_asm_insn (AS1 (fld%z2,%y2), operands);
+	      break;
+	    }
+	}
+      output_asm_insn ("jmp %l1", xops);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+      if (STACK_REG_P (operands[3]) || GET_CODE (operands[3]) == MEM)
+	  output_asm_insn (AS1 (fld%z3,%y3), operands);
+      else
+	{
+	  int conval = standard_80387_constant_p (operands[2]);
+    
+	  switch (conval)
+	    {
+	    case 1:
+	      fprintf (asm_out_file, "\tfldz\n");
+	      break;
+	    case 2:
+	      fprintf (asm_out_file, "\tfld1\n");
+	      break;
+	    default:
+	      operands[3] = CONST_DOUBLE_MEM (operands[3]);
+	      if (GET_CODE (operands[3]) != MEM)
+		abort ();
+	      output_asm_insn (AS1 (fld%z3,%y3), operands);
+	      break;
+	    }
+	}
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+    }
+
+  return "";
+}
+
+char *
+output_int_conditional_move (which_alternative, operands)
+     int which_alternative;
+     rtx operands[];
+{
+  if (which_alternative == 0)
+    {
+      /* r <- cond ? arg : r */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+    }
+  else if (which_alternative == 1)
+    {
+      /* r <- cond ? r : arg */
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+    }
+  else if (which_alternative == 2)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      output_asm_insn (AS2 (cmov%C1,%2,%0), operands);
+      output_asm_insn (AS2 (cmov%c1,%3,%0), operands);
+    }
+  else if (which_alternative == 3)
+    {
+      /* r <- cond ? arg1 : arg2 */
+      rtx xops[3];
+
+      xops[0] = gen_label_rtx ();
+      xops[1] = gen_label_rtx ();
+      xops[2] = operands[1];
+
+      output_asm_insn ("j%c2 %l0", xops);
+      if (! rtx_equal_p (operands[0], operands[2]))
+	{
+	  if (GET_CODE (operands[0]) == MEM
+	      && GET_CODE (operands[2]) == MEM)
+	    {
+	      output_asm_insn (AS2 (mov%z2,%2,%4), operands);
+	      output_asm_insn (AS2 (mov%z2,%4,%0), operands);
+	    }
+	  else
+	    output_asm_insn (AS2 (mov%z0,%2,%0), operands);
+	}
+      output_asm_insn ("jmp %l1", xops);
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[0]));
+      if (! rtx_equal_p (operands[0], operands[3]))
+	{
+	  if (GET_CODE (operands[0]) == MEM
+	      && GET_CODE (operands[3]) == MEM)
+	    {
+	      output_asm_insn (AS2 (mov%z3,%3,%4), operands);
+	      output_asm_insn (AS2 (mov%z3,%4,%0), operands);
+	    }
+	  else
+	    output_asm_insn (AS2 (mov%z0,%3,%0), operands);
+	}
+      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (xops[1]));
+    }
+
+  return "";
+}
+
+int
+is_search_const_double_ok (insn)
+     rtx insn;
+{
+  const char * name = get_insn_name (insn);
+  return name && (strcmp (name, "movsfcc_1") == 0
+		  || strcmp (name, "movdfcc_1") == 0
+		  || strcmp (name, "movxfcc_1") == 0);
 }
Index: varasm.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/varasm.c,v
retrieving revision 1.1.1.15
diff -u -r1.1.1.15 varasm.c
--- varasm.c	1998/04/17 15:01:32	1.1.1.15
+++ varasm.c	1998/05/06 18:09:07
@@ -155,7 +155,7 @@
 							      rtx));
 static struct pool_constant *find_pool_constant PROTO((rtx));
 static void mark_constant_pool		PROTO((void));
-static void mark_constants		PROTO((rtx));
+static void mark_constants		PROTO((rtx, int));
 static int output_addressed_constants	PROTO((tree));
 static void output_after_function_constants PROTO((void));
 static void output_constructor		PROTO((tree, int));
@@ -3651,6 +3652,11 @@
   first_pool = last_pool = 0;
 }
 
+/* Is ok to search inside a CONST_DOUBLE? Default to NO. */
+#ifndef IS_SEARCH_CONST_DOUBLE_OK
+#define IS_SEARCH_CONST_DOUBLE_OK(insn) (0)
+#endif
+
 /* Look through the instructions for this function, and mark all the
    entries in the constant pool which are actually being used.  */
 
@@ -3668,18 +3674,19 @@
 
   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-      mark_constants (PATTERN (insn));
+      mark_constants (PATTERN (insn), IS_SEARCH_CONST_DOUBLE_OK (insn));
 
   for (insn = current_function_epilogue_delay_list;
        insn;
        insn = XEXP (insn, 1))
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
-      mark_constants (PATTERN (insn));
+      mark_constants (PATTERN (insn), IS_SEARCH_CONST_DOUBLE_OK (insn));
 }
 
 static void
-mark_constants (x)
+mark_constants (x, fp_mem_ok)
      register rtx x;
+     int fp_mem_ok;
 {
   register int i;
   register char *format_ptr;
@@ -3697,8 +3704,16 @@
      a MEM, but does not constitute a use of that MEM.  This is particularly
      important inside a nested function, because CONST_DOUBLE_MEM may be
      a reference to a MEM in the parent's constant pool.  See the comment
-     in force_const_mem.  */
-  else if (GET_CODE (x) == CONST_DOUBLE)
+     in force_const_mem.
+
+     For a special case on x86 with FP conditional move, reload may
+     generate patterns containing CONST_DOUBLE such that the x86
+     backend will generate load memory instuctions behind the back. To
+     cover this, we check if the instruction in which the CONST_DOUBLE
+     is used is a SET. If the instruction is a SET and CONST_DOUBLE is
+     in memory, we will look inside the CONST_DOUBLE. */
+  else if (GET_CODE (x) == CONST_DOUBLE
+	   && (!fp_mem_ok || GET_CODE (CONST_DOUBLE_MEM (x)) != MEM))
     return;
 
   /* Insns may appear inside a SEQUENCE.  Only check the patterns of
@@ -3706,7 +3721,7 @@
      a constant just because it happens to appear in a REG_EQUIV note.  */
   if (GET_RTX_CLASS (GET_CODE (x)) == 'i')
     {
-      mark_constants (PATTERN (x));
+      mark_constants (PATTERN (x), fp_mem_ok);
       return;
     }
 
@@ -3717,7 +3732,7 @@
       switch (*format_ptr++)
 	{
 	case 'e':
-	  mark_constants (XEXP (x, i));
+	  mark_constants (XEXP (x, i), fp_mem_ok);
 	  break;
 
 	case 'E':
@@ -3726,7 +3741,7 @@
 	      register int j;
 
 	      for (j = 0; j < XVECLEN (x, i); j++)
-		mark_constants (XVECEXP (x, i, j));
+		mark_constants (XVECEXP (x, i, j), fp_mem_ok);
 	    }
 	  break;
 
Index: rtl.h
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/rtl.h,v
retrieving revision 1.1.1.17
diff -u -r1.1.1.17 rtl.h
--- rtl.h	1998/04/28 22:45:33	1.1.1.17
+++ rtl.h	1998/05/06 17:57:54
@@ -1207,6 +1196,7 @@
 extern void print_rtl			PROTO ((FILE *, rtx));
 extern void print_inline_rtx		PROTO ((FILE *, rtx, int));
 #endif
+extern const char *get_insn_name	PROTO ((rtx));
 
 /* In loop.c */
 extern void init_loop			PROTO ((void));
Index: print-rtl.c
===================================================================
RCS file: /home/work/cvs/gnu/egcs/gcc/print-rtl.c,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 print-rtl.c
--- print-rtl.c	1998/03/21 01:48:28	1.1.1.5
+++ print-rtl.c	1998/05/06 19:08:37
@@ -52,6 +52,8 @@
 
 extern char **insn_name_ptr;
 
+static void print_rtx PROTO ((rtx));
+
 /* Print IN_RTX onto OUTFILE.  This is the recursive part of printing.  */
 
 static void
@@ -362,4 +364,24 @@
   sawclose = 0;
   print_rtx (x);
   putc ('\n', outf);
+}
+
+const char *
+get_insn_name (in_rtx)
+     register rtx in_rtx;
+{
+  if (GET_RTX_CLASS (GET_CODE (in_rtx)) == 'i' && insn_name_ptr)
+    {
+      register int i;
+      register char *format_ptr;
+
+      format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
+      for (i = 0; i < GET_RTX_LENGTH (GET_CODE (in_rtx)); i++)
+	if (*format_ptr++ == 'i'
+	    && &INSN_CODE (in_rtx) == &XINT (in_rtx, i)
+	    && XINT (in_rtx, i) >= 0)
+	  return insn_name_ptr[XINT (in_rtx, i)];
+    }
+
+  return NULL;
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~1998-05-15  1:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <199805131005.KAA00076@iron.rcp.co.uk>
1998-05-15  1:48 ` A patch for PPro H.J. Lu
1998-04-30 20:03 More fp bug in egcs Jim Wilson
1998-05-06 17:12 ` A patch for PPro H.J. Lu
1998-05-06 18:14   ` Jeffrey A Law
1998-05-07 15:31   ` Jim Wilson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).