From 881b2a9652748adad442a2d634eb2970a476fe42 Mon Sep 17 00:00:00 2001 From: Roger Sayle Date: Sun, 16 Feb 2003 01:35:38 +0000 Subject: [PATCH] i386.c (x86_ext_80387_constants): Use 80387 insns to load mathematical constants on K6, Athlon, Pentium 4 and PPro. 2003-02-15 Roger Sayle * config/i386/i386.c (x86_ext_80387_constants): Use 80387 insns to load mathematical constants on K6, Athlon, Pentium 4 and PPro. (ext_80387_constants_table): Global table of 80387 special constants guarded by ext_80387_constants_init flag when not initialized. (init_ext_80387_constants): New function to initialize this table. (standard_80387_constant_p): Extend to recognize extra 80387 constants, in XFmode, on processors where this is a win. (standard_80387_constant_opcode): New function to return the opcode associated with standard_80387_constant_p. (standard_80387_constant_rtx): New function to return the XFmode CONST_DOUBLE associated with standard_80387_constant_p. (ix86_rtx_costs): Give the new constants the same cost as 1.0. * config/i386/i386-protos.h (standard_80387_constant_opcode): Prototype here. (standard_80387_constant_rtx): Likewise. * config/i386/i386.md (*movsf1, *movsf1_nointerunit, *movdf_nointeger, *movdf_integer, *movxf_nointeger, *movtf_nointeger, *movxf_integer, *movtf_integer): Simplify using new standard_80387_constant_opcode. * gcc.dg/i386-387-3.c: New test case. From-SVN: r62958 --- gcc/ChangeLog | 23 ++++++++ gcc/config/i386/i386-protos.h | 2 + gcc/config/i386/i386.c | 119 +++++++++++++++++++++++++++++++++++--- gcc/config/i386/i386.md | 72 +++-------------------- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/i386-387-3.c | 10 ++++ 6 files changed, 159 insertions(+), 71 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/i386-387-3.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 152ba52..bbd38c3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2003-02-15 Roger Sayle + + * config/i386/i386.c (x86_ext_80387_constants): Use 80387 insns + to load mathematical constants on K6, Athlon, Pentium 4 and PPro. + (ext_80387_constants_table): Global table of 80387 special constants + guarded by ext_80387_constants_init flag when not initialized. + (init_ext_80387_constants): New function to initialize this table. + (standard_80387_constant_p): Extend to recognize extra 80387 + constants, in XFmode, on processors where this is a win. + (standard_80387_constant_opcode): New function to return the + opcode associated with standard_80387_constant_p. + (standard_80387_constant_rtx): New function to return the XFmode + CONST_DOUBLE associated with standard_80387_constant_p. + (ix86_rtx_costs): Give the new constants the same cost as 1.0. + + * config/i386/i386-protos.h (standard_80387_constant_opcode): + Prototype here. + (standard_80387_constant_rtx): Likewise. + + * config/i386/i386.md (*movsf1, *movsf1_nointerunit, *movdf_nointeger, + *movdf_integer, *movxf_nointeger, *movtf_nointeger, *movxf_integer, + *movtf_integer): Simplify using new standard_80387_constant_opcode. + 2003-02-15 Geoffrey Keating * doc/invoke.texi (Optimize Options): Correct @option syntax. diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index c920985..b83aae7 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -39,6 +39,8 @@ extern void ix86_output_addr_diff_elt PARAMS ((FILE *, int, int)); extern int ix86_aligned_p PARAMS ((rtx)); extern int standard_80387_constant_p PARAMS ((rtx)); +extern const char *standard_80387_constant_opcode PARAMS ((rtx)); +extern rtx standard_80387_constant_rtx PARAMS ((int)); extern int standard_sse_constant_p PARAMS ((rtx)); extern int symbolic_reference_mentioned_p PARAMS ((rtx)); extern bool extended_reg_mentioned_p PARAMS ((rtx)); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index c627e3d..fd7a9c7 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -522,6 +522,7 @@ const int x86_sse_load0_by_pxor = m_PPRO | m_PENT4; const int x86_use_ffreep = m_ATHLON_K8; const int x86_rep_movl_optimal = m_386 | m_PENT | m_PPRO | m_K6; const int x86_inter_unit_moves = ~(m_ATHLON_K8); +const int x86_ext_80387_constants = m_K6 | m_ATHLON | m_PENT4 | m_PPRO; /* In case the average insn count for single function invocation is lower than this constant, emit fast (but longer) prologue and @@ -934,6 +935,11 @@ static rtx construct_container PARAMS ((enum machine_mode, tree, int, int, int, const int *, int)); static enum x86_64_reg_class merge_classes PARAMS ((enum x86_64_reg_class, enum x86_64_reg_class)); + +/* Table of constants used by fldpi, fldln2, etc... */ +static REAL_VALUE_TYPE ext_80387_constants_table [5]; +static bool ext_80387_constants_init = 0; +static void init_ext_80387_constants PARAMS ((void)); /* Initialize the GCC target structure. */ #undef TARGET_ATTRIBUTE_TABLE @@ -4214,9 +4220,34 @@ aligned_operand (op, mode) return 1; } +/* Initialize the table of extra 80387 mathematical constants. */ + +static void +init_ext_80387_constants () +{ + static const char * cst[5] = + { + "0.3010299956639811952256464283594894482", /* 0: fldlg2 */ + "0.6931471805599453094286904741849753009", /* 1: fldln2 */ + "1.4426950408889634073876517827983434472", /* 2: fldl2e */ + "3.3219280948873623478083405569094566090", /* 3: fldl2t */ + "3.1415926535897932385128089594061862044", /* 4: fldpi */ + }; + int i; + + for (i = 0; i < 5; i++) + { + real_from_string (&ext_80387_constants_table[i], cst[i]); + /* Ensure each constant is rounded to XFmode precision. */ + real_convert (&ext_80387_constants_table[i], XFmode, + &ext_80387_constants_table[i]); + } + + ext_80387_constants_init = 1; +} + /* Return true if the constant is something that can be loaded with - a special instruction. Only handle 0.0 and 1.0; others are less - worthwhile. */ + a special instruction. */ int standard_80387_constant_p (x) @@ -4224,16 +4255,89 @@ standard_80387_constant_p (x) { if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x))) return -1; - /* Note that on the 80387, other constants, such as pi, that we should support - too. On some machines, these are much slower to load as standard constant, - than to load from doubles in memory. */ + if (x == CONST0_RTX (GET_MODE (x))) return 1; if (x == CONST1_RTX (GET_MODE (x))) return 2; + + /* For XFmode constants, try to find a special 80387 instruction on + those CPUs that benefit from them. */ + if (GET_MODE (x) == XFmode + && x86_ext_80387_constants & CPUMASK) + { + REAL_VALUE_TYPE r; + int i; + + if (! ext_80387_constants_init) + init_ext_80387_constants (); + + REAL_VALUE_FROM_CONST_DOUBLE (r, x); + for (i = 0; i < 5; i++) + if (real_identical (&r, &ext_80387_constants_table[i])) + return i + 3; + } + return 0; } +/* Return the opcode of the special instruction to be used to load + the constant X. */ + +const char * +standard_80387_constant_opcode (x) + rtx x; +{ + switch (standard_80387_constant_p (x)) + { + case 1: + return "fldz"; + case 2: + return "fld1"; + case 3: + return "fldlg2"; + case 4: + return "fldln2"; + case 5: + return "fldl2e"; + case 6: + return "fldl2t"; + case 7: + return "fldpi"; + } + abort (); +} + +/* Return the CONST_DOUBLE representing the 80387 constant that is + loaded by the specified special instruction. The argument IDX + matches the return value from standard_80387_constant_p. */ + +rtx +standard_80387_constant_rtx (idx) + int idx; +{ + int i; + + if (! ext_80387_constants_init) + init_ext_80387_constants (); + + switch (idx) + { + case 3: + case 4: + case 5: + case 6: + case 7: + i = idx - 3; + break; + + default: + abort (); + } + + return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i], XFmode); +} + /* Return 1 if X is FP constant we can load to SSE register w/o using memory. */ int @@ -14737,10 +14841,11 @@ ix86_rtx_costs (x, code, outer_code, total) case 1: /* 0.0 */ *total = 1; break; - case 2: /* 1.0 */ + default: /* Other constants */ *total = 2; break; - default: + case 0: + case -1: /* Start with (MEM (SYMBOL_REF)), since that's where it'll probably end up. Add a penalty for size. */ *total = (COSTS_N_INSNS (1) diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 34905f8..94206fa 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -2248,14 +2248,7 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: @@ -2354,14 +2347,7 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: @@ -2536,14 +2522,7 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: @@ -2655,14 +2634,7 @@ return "fst%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - abort(); + return standard_80387_constant_opcode (operands[1]); case 3: case 4: @@ -2902,14 +2874,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; @@ -2954,14 +2919,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; @@ -3006,14 +2964,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; @@ -3058,14 +3009,7 @@ return "fstp%z0\t%y0"; case 2: - switch (standard_80387_constant_p (operands[1])) - { - case 1: - return "fldz"; - case 2: - return "fld1"; - } - break; + return standard_80387_constant_opcode (operands[1]); case 3: case 4: return "#"; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dc0b5db..18044bb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2003-02-15 Roger Sayle + + * gcc.dg/i386-387-3.c: New test case. + 2003-02-14 Josef Zlomek * gcc.dg/20030213-1.c: Expect warning for unsupported -fpic on diff --git a/gcc/testsuite/gcc.dg/i386-387-3.c b/gcc/testsuite/gcc.dg/i386-387-3.c new file mode 100644 index 0000000..f61cd61 --- /dev/null +++ b/gcc/testsuite/gcc.dg/i386-387-3.c @@ -0,0 +1,10 @@ +/* Verify that 387 mathematical constants are recognized. */ +/* { dg-do compile { target "i?86-*-*" } } */ +/* { dg-options "-O2 -march=i686" } */ +/* { dg-final { scan-assembler "fldpi" } } */ + +long double add_pi(long double x) +{ + return x + 3.1415926535897932385128089594061862044L; +} + -- 2.7.4