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]

alpha fp setcc tweeks


On ev6, with fp->integer move instructions, we can do a
bit better with setcc.


r~

        * config/alpha/alpha.c (alpha_emit_conditional_branch): Handle
        TFmode unordered compares properly.  Revalidate integer compare
        operands.
        (alpha_emit_setcc): New.
        (alpha_emit_conditional_move): Revalidate integer compare operands.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/alpha.md (cmpdi): Allow general operands.
        (sne): Use alpha_emit_setcc.
        (seq, slt, sle, sgt, sge, sltu, sleu, sgtu, sgeu): Likewise.
        (sunordered, sordered): New.

Index: alpha-protos.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.12
diff -c -p -d -r1.12 alpha-protos.h
*** alpha-protos.h	2000/05/29 07:52:26	1.12
--- alpha-protos.h	2000/09/25 03:57:45
*************** extern rtx alpha_emit_set_long_const PAR
*** 83,88 ****
--- 83,89 ----
  					     HOST_WIDE_INT));
  extern void alpha_emit_floatuns PARAMS ((rtx[]));
  extern rtx alpha_emit_conditional_branch PARAMS ((enum rtx_code));
+ extern rtx alpha_emit_setcc PARAMS ((enum rtx_code));
  extern rtx alpha_emit_conditional_move PARAMS ((rtx, enum machine_mode));
  extern int alpha_split_conditional_move PARAMS ((enum rtx_code, rtx, rtx,
  						 rtx, rtx));
Index: alpha.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha.c,v
retrieving revision 1.143
diff -c -p -d -r1.143 alpha.c
*** alpha.c	2000/09/15 19:02:22	1.143
--- alpha.c	2000/09/25 03:57:45
*************** alpha_emit_conditional_branch (code)
*** 1620,1629 ****
  	    1  true
  	 Convert the compare against the raw return value.  */
  
!       op0 = alpha_emit_xfloating_compare (code, op0, op1);
        op1 = const0_rtx;
        alpha_compare.fp_p = 0;
!       code = GT;
      }
  
    /* The general case: fold the comparison code to the types of compares
--- 1620,1640 ----
  	    1  true
  	 Convert the compare against the raw return value.  */
  
!       if (code == UNORDERED || code == ORDERED)
! 	cmp_code = EQ;
!       else
! 	cmp_code = code;
! 
!       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
        op1 = const0_rtx;
        alpha_compare.fp_p = 0;
! 
!       if (code == UNORDERED)
! 	code = LT;
!       else if (code == ORDERED)
! 	code = GE;
!       else
!         code = GT;
      }
  
    /* The general case: fold the comparison code to the types of compares
*************** alpha_emit_conditional_branch (code)
*** 1713,1723 ****
  		}
  	    }
  	}
-     }
  
!   /* Force op0 into a register.  */
!   if (GET_CODE (op0) != REG)
!     op0 = force_reg (cmp_mode, op0);
  
    /* Emit an initial compare instruction, if necessary.  */
    tem = op0;
--- 1724,1735 ----
  		}
  	    }
  	}
  
!       if (!reg_or_0_operand (op0, DImode))
! 	op0 = force_reg (DImode, op0);
!       if (cmp_code != PLUS && !reg_or_8bit_operand (op1, DImode))
! 	op1 = force_reg (DImode, op1);
!     }
  
    /* Emit an initial compare instruction, if necessary.  */
    tem = op0;
*************** alpha_emit_conditional_branch (code)
*** 1734,1740 ****
--- 1746,1857 ----
    return gen_rtx_fmt_ee (branch_code, branch_mode, tem, CONST0_RTX (cmp_mode));
  }
  
+ /* Certain simplifications can be done to make invalid setcc operations
+    valid.  Return the final comparison, or NULL if we can't work.  */
+ 
+ rtx
+ alpha_emit_setcc (code)
+      enum rtx_code code;
+ {
+   enum rtx_code cmp_code;
+   rtx op0 = alpha_compare.op0, op1 = alpha_compare.op1;
+   int fp_p = alpha_compare.fp_p;
+   rtx tmp;
  
+   /* Zero the operands.  */
+   memset (&alpha_compare, 0, sizeof (alpha_compare));
+ 
+   if (fp_p && GET_MODE (op0) == TFmode)
+     {
+       if (! TARGET_HAS_XFLOATING_LIBS)
+ 	abort ();
+ 
+       /* X_floating library comparison functions return
+ 	   -1  unordered
+ 	    0  false
+ 	    1  true
+ 	 Convert the compare against the raw return value.  */
+ 
+       if (code == UNORDERED || code == ORDERED)
+ 	cmp_code = EQ;
+       else
+ 	cmp_code = code;
+ 
+       op0 = alpha_emit_xfloating_compare (cmp_code, op0, op1);
+       op1 = const0_rtx;
+       fp_p = 0;
+ 
+       if (code == UNORDERED)
+ 	code = LT;
+       else if (code == ORDERED)
+ 	code = GE;
+       else
+         code = GT;
+     }
+ 
+   if (fp_p && !TARGET_FIX)
+     return NULL_RTX;
+ 
+   /* The general case: fold the comparison code to the types of compares
+      that we have, choosing the branch as necessary.  */
+ 
+   cmp_code = NIL;
+   switch (code)
+     {
+     case EQ:  case LE:  case LT:  case LEU:  case LTU:
+     case UNORDERED:
+       /* We have these compares.  */
+       if (fp_p)
+ 	cmp_code = code, code = NE;
+       break;
+ 
+     case NE:
+       if (!fp_p && op1 == const0_rtx)
+ 	break;
+       /* FALLTHRU */
+ 
+     case ORDERED:
+       cmp_code = reverse_condition (code);
+       code = EQ;
+       break;
+ 
+     case GE:  case GT: case GEU:  case GTU:
+       code = swap_condition (code);
+       if (fp_p)
+ 	cmp_code = code, code = NE;
+       tmp = op0, op0 = op1, op1 = tmp;
+       break;
+ 
+     default:
+       abort ();
+     }
+ 
+   if (!fp_p)
+     {
+       if (!reg_or_0_operand (op0, DImode))
+ 	op0 = force_reg (DImode, op0);
+       if (!reg_or_8bit_operand (op1, DImode))
+ 	op1 = force_reg (DImode, op1);
+     }
+ 
+   /* Emit an initial compare instruction, if necessary.  */
+   if (cmp_code != NIL)
+     {
+       enum machine_mode mode = fp_p ? DFmode : DImode;
+ 
+       tmp = gen_reg_rtx (mode);
+       emit_insn (gen_rtx_SET (VOIDmode, tmp,
+ 			      gen_rtx_fmt_ee (cmp_code, mode, op0, op1)));
+ 
+       op0 = fp_p ? gen_lowpart (DImode, tmp) : tmp;
+       op1 = const0_rtx;
+     }
+ 
+   /* Return the setcc comparison.  */
+   return gen_rtx_fmt_ee (code, DImode, op0, op1);
+ }
+ 
+ 
  /* Rewrite a comparison against zero CMP of the form
     (CODE (cc0) (const_int 0)) so it can be written validly in
     a conditional move (if_then_else CMP ...).
*************** alpha_emit_conditional_move (cmp, mode)
*** 1836,1850 ****
        break;
  
      case GE:  case GT:  case GEU:  case GTU:
!       /* These must be swapped.  Make sure the new first operand is in
! 	 a register.  */
        code = swap_condition (code);
        tem = op0, op0 = op1, op1 = tem;
-       op0 = force_reg (cmp_mode, op0);
        break;
  
      default:
        abort ();
      }
  
    /* ??? We mark the branch mode to be CCmode to prevent the compare
--- 1953,1973 ----
        break;
  
      case GE:  case GT:  case GEU:  case GTU:
!       /* These must be swapped.  */
        code = swap_condition (code);
        tem = op0, op0 = op1, op1 = tem;
        break;
  
      default:
        abort ();
+     }
+ 
+   if (!fp_p)
+     {
+       if (!reg_or_0_operand (op0, DImode))
+ 	op0 = force_reg (DImode, op0);
+       if (!reg_or_8bit_operand (op1, DImode))
+ 	op1 = force_reg (DImode, op1);
      }
  
    /* ??? We mark the branch mode to be CCmode to prevent the compare
Index: alpha.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/alpha/alpha.md,v
retrieving revision 1.127
diff -c -p -d -r1.127 alpha.md
*** alpha.md	2000/08/29 03:59:00	1.127
--- alpha.md	2000/09/25 03:57:45
***************
*** 3349,3356 ****
  }")
  
  (define_expand "cmpdi"
!   [(set (cc0) (compare (match_operand:DI 0 "reg_or_0_operand" "")
! 		       (match_operand:DI 1 "reg_or_8bit_operand" "")))]
    ""
    "
  {
--- 3349,3356 ----
  }")
  
  (define_expand "cmpdi"
!   [(set (cc0) (compare (match_operand:DI 0 "general_operand" "")
! 		       (match_operand:DI 1 "general_operand" "")))]
    ""
    "
  {
***************
*** 3460,3603 ****
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_EQ (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sne"
    [(set (match_operand:DI 0 "register_operand" "")
! 	(match_dup 1))
!    (set (match_dup 0) (xor:DI (match_dup 0) (const_int 1)))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   if (alpha_compare.op1 == const0_rtx)
!     {
!       operands[1] = gen_rtx_NE (DImode, alpha_compare.op0, alpha_compare.op1);
!       alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
!       emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1]));
!       DONE;
!     }
! 
!   operands[1] = gen_rtx_EQ (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "slt"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LT (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sle"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LE (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sgt"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LT (DImode, force_reg (DImode, alpha_compare.op1),
! 			    alpha_compare.op0);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sge"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LE (DImode, force_reg (DImode, alpha_compare.op1),
! 			    alpha_compare.op0);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sltu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LTU (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sleu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LEU (DImode, alpha_compare.op0, alpha_compare.op1);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sgtu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
! 
!   operands[1] = gen_rtx_LTU (DImode, force_reg (DImode, alpha_compare.op1),
! 			     alpha_compare.op0);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  (define_expand "sgeu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "
! {
!   if (alpha_compare.fp_p)
!     FAIL;
  
!   operands[1] = gen_rtx_LEU (DImode, force_reg (DImode, alpha_compare.op1),
! 			     alpha_compare.op0);
!   alpha_compare.op0 = alpha_compare.op1 = NULL_RTX;
! }")
  
  ;; These are the main define_expand's used to make conditional moves.
  
--- 3460,3532 ----
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (EQ)) == NULL_RTX) FAIL; }")
  
  (define_expand "sne"
    [(set (match_operand:DI 0 "register_operand" "")
! 	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (NE)) == NULL_RTX) FAIL; }")
  
  (define_expand "slt"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (LT)) == NULL_RTX) FAIL; }")
  
  (define_expand "sle"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (LE)) == NULL_RTX) FAIL; }")
  
  (define_expand "sgt"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (GT)) == NULL_RTX) FAIL; }")
  
  (define_expand "sge"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (GE)) == NULL_RTX) FAIL; }")
  
  (define_expand "sltu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (LTU)) == NULL_RTX) FAIL; }")
  
  (define_expand "sleu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (LEU)) == NULL_RTX) FAIL; }")
  
  (define_expand "sgtu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (GTU)) == NULL_RTX) FAIL; }")
  
  (define_expand "sgeu"
    [(set (match_operand:DI 0 "register_operand" "")
  	(match_dup 1))]
    ""
!   "{ if ((operands[1] = alpha_emit_setcc (GEU)) == NULL_RTX) FAIL; }")
  
! (define_expand "sunordered"
!   [(set (match_operand:DI 0 "register_operand" "")
! 	(match_dup 1))]
!   ""
!   "{ if ((operands[1] = alpha_emit_setcc (UNORDERED)) == NULL_RTX) FAIL; }")
! 
! (define_expand "sordered"
!   [(set (match_operand:DI 0 "register_operand" "")
! 	(match_dup 1))]
!   ""
!   "{ if ((operands[1] = alpha_emit_setcc (ORDERED)) == NULL_RTX) FAIL; }")
  
  ;; These are the main define_expand's used to make conditional moves.
  

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