improve alpha long double libcalls

Richard Henderson rth@redhat.com
Fri Mar 12 07:18:00 GMT 2004


Some things I noticed while looking into why builtin-18.c fails.

The libcalls should have been marked const.  Silly to build more
than one copy of the symbol_rtx.  Using general_operand for the
extend expanders makes compress_float_constant think we can 
directly extend from SFmode to TFmode.


r~


        * config/alpha/alpha.c (xfloating_ops, vax_cvt_ops): New.
        (alpha_lookup_xfloating_lib_func): Use them, return rtx.
        (alpha_emit_xfloating_arith): Update to match.
        (alpha_emit_xfloating_compare): Likewise.
        (alpha_emit_xfloating_cvt): Likewise.
        (alpha_emit_xfloating_libcall): Take already built symbol,
        mark call const.
        * config/alpha/alpha.md (extendsftf2, extenddftf2): Take
        op1 in a register.

Index: config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.357
diff -c -p -d -r1.357 alpha.c
*** config/alpha/alpha.c	7 Mar 2004 06:30:06 -0000	1.357
--- config/alpha/alpha.c	12 Mar 2004 07:09:51 -0000
*************** alpha_split_conditional_move (enum rtx_c
*** 3564,3648 ****
  /* Look up the function X_floating library function name for the
     given operation.  */
  
! static const char *
! alpha_lookup_xfloating_lib_func (enum rtx_code code)
  {
!   struct xfloating_op
!     {
!       const enum rtx_code code;
!       const char *const func;
!     };
  
!   static const struct xfloating_op vms_xfloating_ops[] = 
!     {
!       { PLUS,		"OTS$ADD_X" },
!       { MINUS,		"OTS$SUB_X" },
!       { MULT,		"OTS$MUL_X" },
!       { DIV,		"OTS$DIV_X" },
!       { EQ,		"OTS$EQL_X" },
!       { NE,		"OTS$NEQ_X" },
!       { LT,		"OTS$LSS_X" },
!       { LE,		"OTS$LEQ_X" },
!       { GT,		"OTS$GTR_X" },
!       { GE,		"OTS$GEQ_X" },
!       { FIX,		"OTS$CVTXQ" },
!       { FLOAT,		"OTS$CVTQX" },
!       { UNSIGNED_FLOAT,	"OTS$CVTQUX" },
!       { FLOAT_EXTEND,	"OTS$CVT_FLOAT_T_X" },
!       { FLOAT_TRUNCATE,	"OTS$CVT_FLOAT_X_T" },
!     };
  
!   static const struct xfloating_op osf_xfloating_ops[] = 
!     {
!       { PLUS,		"_OtsAddX" },
!       { MINUS,		"_OtsSubX" },
!       { MULT,		"_OtsMulX" },
!       { DIV,		"_OtsDivX" },
!       { EQ,		"_OtsEqlX" },
!       { NE,		"_OtsNeqX" },
!       { LT,		"_OtsLssX" },
!       { LE,		"_OtsLeqX" },
!       { GT,		"_OtsGtrX" },
!       { GE,		"_OtsGeqX" },
!       { FIX,		"_OtsCvtXQ" },
!       { FLOAT,		"_OtsCvtQX" },
!       { UNSIGNED_FLOAT,	"_OtsCvtQUX" },
!       { FLOAT_EXTEND,	"_OtsConvertFloatTX" },
!       { FLOAT_TRUNCATE,	"_OtsConvertFloatXT" },
!     };
  
!   const struct xfloating_op *ops;
!   const long n = ARRAY_SIZE (osf_xfloating_ops);
    long i;
  
!   /* How irritating.  Nothing to key off for the table.  Hardcode
!      knowledge of the G_floating routines.  */
!   if (TARGET_FLOAT_VAX)
      {
!       if (TARGET_ABI_OPEN_VMS)
! 	{
! 	  if (code == FLOAT_EXTEND)
! 	    return "OTS$CVT_FLOAT_G_X";
! 	  if (code == FLOAT_TRUNCATE)
! 	    return "OTS$CVT_FLOAT_X_G";
! 	}
!       else
! 	{
! 	  if (code == FLOAT_EXTEND)
! 	    return "_OtsConvertFloatGX";
! 	  if (code == FLOAT_TRUNCATE)
! 	    return "_OtsConvertFloatXG";
! 	}
      }
  
!   if (TARGET_ABI_OPEN_VMS)
!     ops = vms_xfloating_ops;
!   else
!     ops = osf_xfloating_ops;
! 
!   for (i = 0; i < n; ++i)
!     if (ops[i].code == code)
!       return ops[i].func;
  
    abort();
  }
--- 3564,3628 ----
  /* Look up the function X_floating library function name for the
     given operation.  */
  
! struct xfloating_op GTY(())
  {
!   const enum rtx_code code;
!   const char *const GTY((skip(""))) osf_func;
!   const char *const GTY((skip(""))) vms_func;
!   rtx libcall;
! };
  
! static GTY(()) struct xfloating_op xfloating_ops[] = 
! {
!   { PLUS,		"_OtsAddX", "OTS$ADD_X", 0 },
!   { MINUS,		"_OtsSubX", "OTS$SUB_X", 0 },
!   { MULT,		"_OtsMulX", "OTS$MUL_X", 0 },
!   { DIV,		"_OtsDivX", "OTS$DIV_X", 0 },
!   { EQ,			"_OtsEqlX", "OTS$EQL_X", 0 },
!   { NE,			"_OtsNeqX", "OTS$NEQ_X", 0 },
!   { LT,			"_OtsLssX", "OTS$LSS_X", 0 },
!   { LE,			"_OtsLeqX", "OTS$LEQ_X", 0 },
!   { GT,			"_OtsGtrX", "OTS$GTR_X", 0 },
!   { GE,			"_OtsGeqX", "OTS$GEQ_X", 0 },
!   { FIX,		"_OtsCvtXQ", "OTS$CVTXQ", 0 },
!   { FLOAT,		"_OtsCvtQX", "OTS$CVTQX", 0 },
!   { UNSIGNED_FLOAT,	"_OtsCvtQUX", "OTS$CVTQUX", 0 },
!   { FLOAT_EXTEND,	"_OtsConvertFloatTX", "OTS$CVT_FLOAT_T_X", 0 },
!   { FLOAT_TRUNCATE,	"_OtsConvertFloatXT", "OTS$CVT_FLOAT_X_T", 0 }
! };
  
! static GTY(()) struct xfloating_op vax_cvt_ops[] =
! {
!   { FLOAT_EXTEND,	"_OtsConvertFloatGX", "OTS$CVT_FLOAT_G_X", 0 },
!   { FLOAT_TRUNCATE,	"_OtsConvertFloatXG", "OTS$CVT_FLOAT_X_G", 0 }
! };
  
! static rtx
! alpha_lookup_xfloating_lib_func (enum rtx_code code)
! {
!   struct xfloating_op *ops = xfloating_ops;
!   long n = ARRAY_SIZE (xfloating_ops);
    long i;
  
!   /* How irritating.  Nothing to key off for the main table.  */
!   if (TARGET_FLOAT_VAX && (code == FLOAT_EXTEND || code == FLOAT_TRUNCATE))
      {
!       ops = vax_cvt_ops;
!       n = ARRAY_SIZE (vax_cvt_ops);
      }
  
!   for (i = 0; i < n; ++i, ++ops)
!     if (ops->code == code)
!       {
! 	rtx func = ops->libcall;
! 	if (!func)
! 	  {
! 	    func = init_one_libfunc (TARGET_ABI_OPEN_VMS
! 				     ? ops->vms_func : ops->osf_func);
! 	    ops->libcall = func;
! 	  }
!         return func;
!       }
  
    abort();
  }
*************** alpha_compute_xfloating_mode_arg (enum r
*** 3688,3694 ****
     TFmode arguments are passed in two integer registers (as opposed to
     indirect); TFmode return values appear in R16+R17. 
  
!    FUNC is the function name to call.
     TARGET is where the output belongs.
     OPERANDS are the inputs.
     NOPERANDS is the count of inputs.
--- 3668,3674 ----
     TFmode arguments are passed in two integer registers (as opposed to
     indirect); TFmode return values appear in R16+R17. 
  
!    FUNC is the function to call.
     TARGET is where the output belongs.
     OPERANDS are the inputs.
     NOPERANDS is the count of inputs.
*************** alpha_compute_xfloating_mode_arg (enum r
*** 3696,3702 ****
  */
  
  static void
! alpha_emit_xfloating_libcall (const char *func, rtx target, rtx operands[],
  			      int noperands, rtx equiv)
  {
    rtx usage = NULL_RTX, tmp, reg;
--- 3676,3682 ----
  */
  
  static void
! alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
  			      int noperands, rtx equiv)
  {
    rtx usage = NULL_RTX, tmp, reg;
*************** alpha_emit_xfloating_libcall (const char
*** 3750,3759 ****
        abort ();
      }
  
!   tmp = gen_rtx_MEM (QImode, init_one_libfunc (func));
    tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
  					const0_rtx, const0_rtx));
    CALL_INSN_FUNCTION_USAGE (tmp) = usage;
  
    tmp = get_insns ();
    end_sequence ();
--- 3730,3740 ----
        abort ();
      }
  
!   tmp = gen_rtx_MEM (QImode, func);
    tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx,
  					const0_rtx, const0_rtx));
    CALL_INSN_FUNCTION_USAGE (tmp) = usage;
+   CONST_OR_PURE_CALL_P (tmp) = 1;
  
    tmp = get_insns ();
    end_sequence ();
*************** alpha_emit_xfloating_libcall (const char
*** 3766,3772 ****
  void
  alpha_emit_xfloating_arith (enum rtx_code code, rtx operands[])
  {
!   const char *func;
    int mode;
    rtx out_operands[3];
  
--- 3747,3753 ----
  void
  alpha_emit_xfloating_arith (enum rtx_code code, rtx operands[])
  {
!   rtx func;
    int mode;
    rtx out_operands[3];
  
*************** alpha_emit_xfloating_arith (enum rtx_cod
*** 3786,3792 ****
  static rtx
  alpha_emit_xfloating_compare (enum rtx_code code, rtx op0, rtx op1)
  {
!   const char *func;
    rtx out, operands[2];
  
    func = alpha_lookup_xfloating_lib_func (code);
--- 3767,3773 ----
  static rtx
  alpha_emit_xfloating_compare (enum rtx_code code, rtx op0, rtx op1)
  {
!   rtx func;
    rtx out, operands[2];
  
    func = alpha_lookup_xfloating_lib_func (code);
*************** alpha_emit_xfloating_cvt (enum rtx_code 
*** 3810,3816 ****
  {
    int noperands = 1, mode;
    rtx out_operands[2];
!   const char *func;
    enum rtx_code code = orig_code;
  
    if (code == UNSIGNED_FIX)
--- 3791,3797 ----
  {
    int noperands = 1, mode;
    rtx out_operands[2];
!   rtx func;
    enum rtx_code code = orig_code;
  
    if (code == UNSIGNED_FIX)
Index: config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.220
diff -c -p -d -r1.220 alpha.md
*** config/alpha/alpha.md	26 Feb 2004 01:45:32 -0000	1.220
--- config/alpha/alpha.md	12 Mar 2004 07:09:51 -0000
***************
*** 2630,2638 ****
     st%- %1,%0"
    [(set_attr "type" "fcpys,fld,fst")])
  
  (define_expand "extendsftf2"
    [(use (match_operand:TF 0 "register_operand" ""))
!    (use (match_operand:SF 1 "general_operand" ""))]
    "TARGET_HAS_XFLOATING_LIBS"
  {
    rtx tmp = gen_reg_rtx (DFmode);
--- 2630,2641 ----
     st%- %1,%0"
    [(set_attr "type" "fcpys,fld,fst")])
  
+ ;; Use register_operand for operand 1 to prevent compress_float_constant
+ ;; from doing something silly.  When optimizing we'll put things back 
+ ;; together anyway.
  (define_expand "extendsftf2"
    [(use (match_operand:TF 0 "register_operand" ""))
!    (use (match_operand:SF 1 "register_operand" ""))]
    "TARGET_HAS_XFLOATING_LIBS"
  {
    rtx tmp = gen_reg_rtx (DFmode);
***************
*** 2643,2649 ****
  
  (define_expand "extenddftf2"
    [(use (match_operand:TF 0 "register_operand" ""))
!    (use (match_operand:DF 1 "general_operand" ""))]
    "TARGET_HAS_XFLOATING_LIBS"
    "alpha_emit_xfloating_cvt (FLOAT_EXTEND, operands); DONE;")
  
--- 2646,2652 ----
  
  (define_expand "extenddftf2"
    [(use (match_operand:TF 0 "register_operand" ""))
!    (use (match_operand:DF 1 "register_operand" ""))]
    "TARGET_HAS_XFLOATING_LIBS"
    "alpha_emit_xfloating_cvt (FLOAT_EXTEND, operands); DONE;")
  



More information about the Gcc-patches mailing list