aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRoger Sayle <roger@eyesopen.com>2003-02-16 01:35:38 +0000
committerRoger Sayle <sayle@gcc.gnu.org>2003-02-16 01:35:38 +0000
commit881b2a9652748adad442a2d634eb2970a476fe42 (patch)
treec5992b263188c567bbeaa331e4c8c317af271e2c /gcc
parentd203738b3a8967e2f096288da68075154c81bcb2 (diff)
downloadgcc-881b2a9652748adad442a2d634eb2970a476fe42.zip
gcc-881b2a9652748adad442a2d634eb2970a476fe42.tar.gz
gcc-881b2a9652748adad442a2d634eb2970a476fe42.tar.bz2
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 <roger@eyesopen.com> * 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c119
-rw-r--r--gcc/config/i386/i386.md72
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/i386-387-3.c10
6 files changed, 159 insertions, 71 deletions
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 <roger@eyesopen.com>
+
+ * 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 <geoffk@apple.com>
* 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 <roger@eyesopen.com>
+
+ * gcc.dg/i386-387-3.c: New test case.
+
2003-02-14 Josef Zlomek <zlomekj@suse.cz>
* 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;
+}
+