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]

[PATCH] Unordered SPARC fixes


Hi!

The unordered changes broke SPARC, this patch tries to fix at least the
TFmode !TARGET_HARD_QUAD issues.
For non-common comparisons the ABI define _Qp_cmp resp. _Q_cmp functions
which return value:
0 A == B
1 A < B
2 A > B
3 A ? B (unordered)

so I have hacked up sparc_emit_float_lib_cmp so that it is able to use that.
I had to switch sparc32 to use sparc_emit_float_lib_cmp again because
otherwise it would wind up in optabs generic code which would use __unordtf2
etc. which is really not desired on SPARC.
This patch also fixes an abort() on sparc64 when comparing doubles
(print_operand did not handle the new comparisons).
But double/float compares are still broken (no matter if this patch is in or
not).
gcc aborts e.g. on:
double a, b;
int lt(void) { return a < b; }
int le(void) { return a <= b; }
int gt(void) { return a > b; }
int ge(void) { return a >= b; }
int o(void) { return !__builtin_isunordered(a, b); }
int un(void) { return __builtin_isunordered(a, b); }
int lt2(void) { return __builtin_isless(a, b); }
int le2(void) { return __builtin_islessequal(a, b); }
int gt2(void) { return __builtin_isgreater(a, b); }
int ge2(void) { return __builtin_isgreaterequal(a, b); }
int ltgt2(void) { return __builtin_islessgreater(a, b); }

It dies in simplify_binary_operation called from simplify_if_then_else.
I don't know what's the best fix for that, maybe change arguments of
reverse_condition, so that one does not pass only the code, but also the cc
register and kill reverse_condition_maybe_unordered.


2000-01-26  Jakub Jelinek  <jakub@redhat.com>

	* config/sparc/sparc.c (sparc_emit_float_lib_cmp): Handle
	TARGET_ARCH32 again. Handle ORDERED, UN* and LTGT comparisons
	using _Qp_cmp/_Q_cmp and testing the return value.
	(print_operand): Call reverse_condition_maybe_unordered if
	we are handling CCFPmode or CCFPEmode.
	Handle ORDERED, UN* and LTGT comparisons.
	* config/sparc/sparc.md (cmptf): Use even on TARGET_ARCH32
	if not TARGET_HARD_QUAD.
	(seq, sne, sgt, slt, sge, sle, beq, bne, bgt, blt, bge, ble,
	bunordered, bordered, bungt, bunlt, buneq, bunge, bunle, bltgt):
	Call sparc_emit_float_lib_cmp even on TARGET_ARCH32.
	Adjust gen_b* calls so that they reflect return comparison of
	sparc_emit_float_lib_cmp.

--- gcc/config/sparc/sparc.c.jj	Wed Jan 26 08:38:26 2000
+++ gcc/config/sparc/sparc.c	Wed Jan 26 16:41:07 2000
@@ -4822,33 +4822,46 @@ sparc_emit_float_lib_cmp (x, y, comparis
      rtx x, y;
      enum rtx_code comparison;
 {
-  const char *qpfunc;
-  rtx slot0, slot1, result;
+  char *qpfunc;
+  rtx cmp = const0_rtx;
+  rtx slot0, slot1, result, tem, tem2;
+  enum machine_mode mode;
 
   switch (comparison)
     {
     case EQ:
-      qpfunc = "_Qp_feq";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_feq" : "_Q_feq";
       break;
 
     case NE:
-      qpfunc = "_Qp_fne";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_fne" : "_Q_fne";
       break;
 
     case GT:
-      qpfunc = "_Qp_fgt";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_fgt" : "_Q_fgt";
       break;
 
     case GE:
-      qpfunc = "_Qp_fge";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_fge" : "_Q_fge";
       break;
 
     case LT:
-      qpfunc = "_Qp_flt";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_flt" : "_Q_flt";
       break;
 
     case LE:
-      qpfunc = "_Qp_fle";
+      qpfunc = (TARGET_ARCH64) ? "_Qp_fle" : "_Q_fle";
+      break;
+
+    case ORDERED:
+    case UNORDERED:
+    case UNGT:
+    case UNLT:
+    case UNEQ:
+    case UNGE:
+    case UNLE:
+    case LTGT:
+      qpfunc = (TARGET_ARCH64) ? "_Qp_cmp" : "_Q_cmp";
       break;
 
     default:
@@ -4856,33 +4869,94 @@ sparc_emit_float_lib_cmp (x, y, comparis
       break;
     }
 
-  if (GET_CODE (x) != MEM)
+  if (TARGET_ARCH64)
     {
-      slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
-    }
+      if (GET_CODE (x) != MEM)
+	{
+	  slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+	  emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
+	}
+      else
+	slot0 = x;
 
-  if (GET_CODE (y) != MEM)
+      if (GET_CODE (y) != MEM)
+	{
+	  slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
+	  emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+	}
+      else
+	slot1 = y;
+
+      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+			 DImode, 2,
+			 XEXP (slot0, 0), Pmode,
+			 XEXP (slot1, 0), Pmode);
+
+      mode = DImode;
+    }
+  else
     {
-      slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
-      emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+      emit_library_call (gen_rtx_SYMBOL_REF (Pmode, qpfunc), 1,
+			 SImode, 2,
+			 x, TFmode, y, TFmode);
+
+      mode = SImode;
     }
 
-  emit_library_call (gen_rtx (SYMBOL_REF, Pmode, qpfunc), 1,
-                     DImode, 2,
-                     XEXP (slot0, 0), Pmode,
-                     XEXP (slot1, 0), Pmode);
 
   /* Immediately move the result of the libcall into a pseudo
      register so reload doesn't clobber the value if it needs
      the return register for a spill reg.  */
-  result = gen_reg_rtx (DImode);
-  emit_move_insn (result, hard_libcall_value (DImode));
+  result = gen_reg_rtx (mode);
+  emit_move_insn (result, hard_libcall_value (mode));
 
-  emit_cmp_insn (result, const0_rtx, comparison,
-                 NULL_RTX, DImode, 0, 0);
+  switch (comparison)
+    {
+    default:
+      emit_cmp_insn (result, const0_rtx, NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    case ORDERED:
+    case UNORDERED:
+      emit_cmp_insn (result, GEN_INT(3), NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    case UNGT:
+    case UNGE:
+      emit_cmp_insn (result, const1_rtx, NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    case UNLE:
+      emit_cmp_insn (result, const2_rtx, NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    case UNLT:
+      tem = gen_reg_rtx (mode);
+      if (TARGET_ARCH32)
+	emit_insn (gen_andsi3 (tem, result, const1_rtx));
+      else
+	emit_insn (gen_anddi3 (tem, result, const1_rtx));
+      emit_cmp_insn (tem, const0_rtx, NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    case UNEQ:
+    case LTGT:
+      tem = gen_reg_rtx (mode);
+      if (TARGET_ARCH32)
+	emit_insn (gen_addsi3 (tem, result, const1_rtx));
+      else
+	emit_insn (gen_adddi3 (tem, result, const1_rtx));
+      tem2 = gen_reg_rtx (mode);
+      if (TARGET_ARCH32)
+	emit_insn (gen_andsi3 (tem2, tem, const2_rtx));
+      else
+	emit_insn (gen_anddi3 (tem2, tem, const2_rtx));
+      emit_cmp_insn (tem2, const0_rtx, NE,
+		     NULL_RTX, mode, 0, 0);
+      break;
+    }
 }
-          
+
 /* Return the string to output a conditional branch to LABEL, testing
    register REG.  LABEL is the operand number of the label; REG is the
    operand number of the reg.  OP is the conditional expression.  The mode
@@ -5449,9 +5523,16 @@ print_operand (file, x, code)
     case 'c' :
     case 'C':
       {
-	enum rtx_code rc = (code == 'c'
-			    ? reverse_condition (GET_CODE (x))
-			    : GET_CODE (x));
+	enum rtx_code rc = GET_CODE (x);
+	
+	if (code == 'c')
+	  {
+	    enum machine_mode mode = GET_MODE (XEXP (x, 0));
+	    if (mode == CCFPmode || mode == CCFPEmode)
+	      rc = reverse_condition_maybe_unordered (GET_CODE (x));
+	    else
+	      rc = reverse_condition (GET_CODE (x));
+	  }
 	switch (rc)
 	  {
 	  case NE: fputs ("ne", file); break;
@@ -5464,6 +5545,14 @@ print_operand (file, x, code)
 	  case GTU: fputs ("gu", file); break;
 	  case LEU: fputs ("leu", file); break;
 	  case LTU: fputs ("lu", file); break;
+	  case LTGT: fputs ("lg", file); break;
+	  case UNORDERED: fputs ("u", file); break;
+	  case ORDERED: fputs ("o", file); break;
+	  case UNLT: fputs ("ul", file); break;
+	  case UNLE: fputs ("ule", file); break;
+	  case UNGT: fputs ("ug", file); break;
+	  case UNGE: fputs ("uge", file); break;
+	  case UNEQ: fputs ("ue", file); break;
 	  default: output_operand_lossage (code == 'c'
 					   ? "Invalid %%c operand"
 					   : "Invalid %%C operand");
--- gcc/config/sparc/sparc.md.jj	Wed Jan 26 08:38:26 2000
+++ gcc/config/sparc/sparc.md	Wed Jan 26 16:41:07 2000
@@ -627,7 +627,7 @@
   [(set (reg:CCFP 96)
 	(compare:CCFP (match_operand:TF 0 "register_operand" "")
 		      (match_operand:TF 1 "register_operand" "")))]
-  "TARGET_FPU && (TARGET_HARD_QUAD || TARGET_ARCH64)"
+  "TARGET_FPU"
   "
 {
   sparc_compare_op0 = operands[0];
@@ -855,7 +855,7 @@
       emit_insn (pat);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
       emit_jump_insn (gen_sne (operands[0]));
@@ -908,7 +908,7 @@
       emit_insn (pat);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
       emit_jump_insn (gen_sne (operands[0]));
@@ -929,7 +929,7 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
       emit_jump_insn (gen_sne (operands[0]));
@@ -950,7 +950,7 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
       emit_jump_insn (gen_sne (operands[0]));
@@ -971,7 +971,7 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
       emit_jump_insn (gen_sne (operands[0]));
@@ -992,7 +992,7 @@
   "! TARGET_LIVE_G0"
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
       emit_jump_insn (gen_sne (operands[0]));
@@ -1626,7 +1626,7 @@
       emit_v9_brxx_insn (EQ, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, EQ);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1650,7 +1650,7 @@
       emit_v9_brxx_insn (NE, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, NE);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1674,7 +1674,7 @@
       emit_v9_brxx_insn (GT, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GT);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1708,7 +1708,7 @@
       emit_v9_brxx_insn (LT, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LT);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1742,7 +1742,7 @@
       emit_v9_brxx_insn (GE, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, GE);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1776,7 +1776,7 @@
       emit_v9_brxx_insn (LE, sparc_compare_op0, operands[0]);
       DONE;
     }
-  else if (GET_MODE (sparc_compare_op0) == TFmode && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  else if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LE);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1803,12 +1803,11 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1,
 				UNORDERED);
-      emit_jump_insn (gen_bne (operands[0]));
+      emit_jump_insn (gen_beq (operands[0]));
       DONE;
     }
   operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
@@ -1823,8 +1822,7 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, ORDERED);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1842,11 +1840,10 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGT);
-      emit_jump_insn (gen_bne (operands[0]));
+      emit_jump_insn (gen_bgt (operands[0]));
       DONE;
     }
   operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
@@ -1860,8 +1857,7 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLT);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1878,11 +1874,10 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNEQ);
-      emit_jump_insn (gen_bne (operands[0]));
+      emit_jump_insn (gen_beq (operands[0]));
       DONE;
     }
   operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
@@ -1896,8 +1891,7 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNGE);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1914,8 +1908,7 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, UNLE);
       emit_jump_insn (gen_bne (operands[0]));
@@ -1932,8 +1925,7 @@
   ""
   "
 {
-  if (GET_MODE (sparc_compare_op0) == TFmode
-      && TARGET_ARCH64 && ! TARGET_HARD_QUAD)
+  if (GET_MODE (sparc_compare_op0) == TFmode && ! TARGET_HARD_QUAD)
     {
       sparc_emit_float_lib_cmp (sparc_compare_op0, sparc_compare_op1, LTGT);
       emit_jump_insn (gen_bne (operands[0]));

Cheers,
    Jakub
___________________________________________________________________
Jakub Jelinek | jakub@redhat.com | http://sunsite.mff.cuni.cz/~jj
Linux version 2.3.41 on a sparc64 machine (1343.49 BogoMips)
___________________________________________________________________

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