This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[experimental PATCH - ia64] distinguish __fpreg and __float80
- From: "Zack Weinberg" <zack at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: rth at redhat dot com, wilson at specifixinc dot com, mark at codesourcery dot com
- Date: Wed, 24 Sep 2003 16:25:20 -0700
- Subject: [experimental PATCH - ia64] distinguish __fpreg and __float80
This is an experimental patch which allows the ia64 back end to
distinguish __fpreg and __float80. The only difference between these
two types, for code generation purposes, is that the former is loaded
from memory with "ldf.fill" and stored back with "stf.spill", while
the former uses "ldfe" and "stfe" respectively.
The code works for simple cases like
extern __float80 a;
extern __fpreg b;
void foo(void) { a = b; }
void bar(void) { b = a; }
but it will probably not work for more complicated cases where the
*movxf_internal pattern winds up with an XFmode MEM that has no
MEM_EXPR. I am open to suggestions as to how to fix this, but
I really don't want to invent YFmode if we can possibly avoid it.
This patch is relative to my earlier patch to use XFmode for
__float80, which I am still waiting for comments on.
[http://gcc.gnu.org/ml/gcc-patches/2003-09/msg01525.html]
zw
* config/ia64/ia64.c (ia64_fpreg_type): New static.
(ia64_init_builtins): Initialize it.
(ia64_is_fpreg_type): New function.
* config/ia64/ia64-protos.h: Prototype it.
* config/ia64/ia64.md (*movxf_internal): When one operand is a
MEM, call ia64_is_fpreg_type and use ldf.fill/stf.spill if it
returns true.
=================================================
--- config/ia64/ia64-protos.h 2003-09-11 15:59:35 -0700
+++ config/ia64/ia64-protos.h 2003-09-24 15:48:46 -0700
@@ -155,3 +155,4 @@
extern void ia64_hpux_handle_builtin_pragma (struct cpp_reader *);
extern unsigned int ia64_round_type_align (tree, unsigned int, unsigned int);
+extern bool ia64_is_fpreg_type (rtx);
=================================================
--- config/ia64/ia64.c 2003-09-24 14:53:25 -0700
+++ config/ia64/ia64.c 2003-09-24 15:55:50 -0700
@@ -7752,6 +7752,25 @@
}
+static rtx GTY(()) ia64_fpreg_type;
+
+/* Returns true if the OPERAND (which will be a MEM) has a type which
+ is (ultimately) ia64_fpreg_type. Returns false if not, or if we
+ cannot tell. */
+bool
+ia64_is_fpreg_type (rtx operand)
+{
+ tree type;
+
+ if (!MEM_EXPR (operand))
+ return false;
+
+ type = TREE_TYPE (MEM_EXPR (operand));
+ while (TREE_TYPE (type))
+ type = TREE_TYPE (type);
+ return (TYPE_MAIN_VARIANT (type) == ia64_fpreg_type);
+}
+
void
ia64_init_builtins (void)
{
@@ -7807,6 +7826,7 @@
TYPE_PRECISION (fpreg_type) = 96;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
+ ia64_fpreg_type = fpreg_type;
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
=================================================
--- config/ia64/ia64.md 2003-09-11 15:59:35 -0700
+++ config/ia64/ia64.md 2003-09-24 16:06:21 -0700
@@ -825,13 +825,28 @@
;; ??? There's no easy way to mind volatile acquire/release semantics.
(define_insn "*movxf_internal"
- [(set (match_operand:XF 0 "destination_xfmode_operand" "=f,f, m")
- (match_operand:XF 1 "general_xfmode_operand" "fG,m,fG"))]
+ [(set (match_operand:XF 0 "destination_xfmode_operand" "=f, f,m")
+ (match_operand:XF 1 "general_xfmode_operand" " fG,m,fG"))]
"ia64_move_ok (operands[0], operands[1])"
- "@
- mov %0 = %F1
- ldfe %0 = %1%P1
- stfe %0 = %F1%P0"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return "mov %0 = %F1";
+
+ case 1:
+ if (ia64_is_fpreg_type (operands[1]))
+ return "ldf.fill %0 = %1%P1";
+ else
+ return "ldfe %0 = %1%P1";
+
+ case 2:
+ if (ia64_is_fpreg_type (operands[0]))
+ return "stf.spill %0 = %F1%P0";
+ else
+ return "stfe %0 = %F1%P0";
+ }
+}
[(set_attr "itanium_class" "fmisc,fld,stf")])