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