aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorZack Weinberg <zack@gcc.gnu.org>2004-01-16 01:27:38 +0000
committerZack Weinberg <zack@gcc.gnu.org>2004-01-16 01:27:38 +0000
commitf57fc998eeab27e8292de128b37c94ffa37d8409 (patch)
tree8c8acf6e85b0ef4b2cdeb4d1ce751bdf47265a9a /gcc
parent16a9a2803f9e25933a2ca2bc28590464b1f42c9f (diff)
downloadgcc-f57fc998eeab27e8292de128b37c94ffa37d8409.zip
gcc-f57fc998eeab27e8292de128b37c94ffa37d8409.tar.gz
gcc-f57fc998eeab27e8292de128b37c94ffa37d8409.tar.bz2
ia64.md (*movti_internal): C output template extracted to ia64.c.
* config/ia64/ia64.md (*movti_internal): C output template extracted to ia64.c. (*movti_internal_reg): Delete. (reload_inti, reload_outti): Use the correct mode on operand 2 in the first place, don't fix it up in the output template. (movtf, reload_ointf, reload_outtf): New expanders. (*movtf_internal): New define_insn_and_split. * config/ia64/ia64.c (ia64_split_timode): Rename to ia64_split_tmode; make static; do not hand TFmode CONST_DOUBLEs to split_double. (ia64_split_tmode_move): New function, body mostly pulled from ia64.md:*movti_internal. (ia64_function_arg_words): New function, extracted common logic from ia64_function_arg et seq. (ia64_function_arg_offset): Likewise. Handle correctly the case of a scalar quantity 16 bytes wide with only 8-byte alignment. (ia64_function_arg, ia64_function_arg_partial_nregs) (ia64_function_arg_advance): Use ia64_function_arg_words and ia64_function_arg_offset. (ia64_function_value): TCmode does not go in float regs. (ia64_secondary_reload_class): Also handle TFmode. * config/ia64/ia64-protos.h: Remove prototype for ia64_split_timode; add prototype for ia64_split_tmode_move. From-SVN: r75956
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog39
-rw-r--r--gcc/config/ia64/ia64-protos.h2
-rw-r--r--gcc/config/ia64/ia64.c175
-rw-r--r--gcc/config/ia64/ia64.md132
4 files changed, 211 insertions, 137 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2c95abb..4a2e9aa 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,28 @@
+2004-01-15 Zack Weinberg <zack@codesourcery.com>
+
+ * config/ia64/ia64.md (*movti_internal): C output template
+ extracted to ia64.c.
+ (*movti_internal_reg): Delete.
+ (reload_inti, reload_outti): Use the correct mode on operand 2
+ in the first place, don't fix it up in the output template.
+ (movtf, reload_ointf, reload_outtf): New expanders.
+ (*movtf_internal): New define_insn_and_split.
+ * config/ia64/ia64.c (ia64_split_timode): Rename to ia64_split_tmode;
+ make static; do not hand TFmode CONST_DOUBLEs to split_double.
+ (ia64_split_tmode_move): New function, body mostly pulled
+ from ia64.md:*movti_internal.
+ (ia64_function_arg_words): New function, extracted common
+ logic from ia64_function_arg et seq.
+ (ia64_function_arg_offset): Likewise. Handle correctly the
+ case of a scalar quantity 16 bytes wide with only 8-byte alignment.
+ (ia64_function_arg, ia64_function_arg_partial_nregs)
+ (ia64_function_arg_advance): Use ia64_function_arg_words and
+ ia64_function_arg_offset.
+ (ia64_function_value): TCmode does not go in float regs.
+ (ia64_secondary_reload_class): Also handle TFmode.
+ * config/ia64/ia64-protos.h: Remove prototype for
+ ia64_split_timode; add prototype for ia64_split_tmode_move.
+
2004-01-15 Kelley Cook <kcook@gcc.gnu.org>
* Makefile.in (MAINT): Make it an immediate assignment.
@@ -224,7 +249,7 @@
2004-01-14 Richard Earnshaw <rearnsha@arm.com>
- * regrename.c (find_oldest_value_reg): If the replacement uses
+ * regrename.c (find_oldest_value_reg): If the replacement uses
multiple hard registers, check that all of them are in CLASS.
2004-01-14 Jan Hubicka <jh@suse.cz>
@@ -301,14 +326,14 @@
2004-01-13 Bernardo Innocenti <bernie@develer.com>
* config/m68k/netbsd-elf.h (REGISTER_NAMES): Add missing "argptr"
- pseudo-register.
+ pseudo-register.
2004-01-13 Devang Patel <dpatel@apple.com
PR debug/7078
- * dbxout.c (dbxout_symbol_name): Emit mangled names for
+ * dbxout.c (dbxout_symbol_name): Emit mangled names for
NAMESPACE_DECL memebers.
-
+
2004-01-13 Andrew Pinski <pinskia@physics.uc.edu>
PR c++/12709
@@ -318,7 +343,7 @@
2004-01-13 Vladimir Makarov <vmakarov@redhat.com>
* rtl.def: Add comment about new option in automata_option.
-
+
* genautomata.c (PROGRESS_OPTION): New macro.
(progress_flag): New global variable.
(gen_automata_option): Process `progress'.
@@ -329,14 +354,14 @@
(initiate_automaton_gen): Process command line flag `-progress'.
* doc/md.texi: Describe the new option.
-
+
2004-01-13 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* cfg.c (dump_bb): Dump entry edges.
2004-01-13 Richard Earnshaw <rearnsha@arm.com>
- * arm.c (thumb_legitimate_address_p): Only allow constant pool
+ * arm.c (thumb_legitimate_address_p): Only allow constant pool
references from SImode.
* arm.md (thumb_movhi_insn): Don't allow minipool references.
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 01d6115..c6920fa 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -80,7 +80,7 @@ extern int ia64_move_ok (rtx, rtx);
extern int addp4_optimize_ok (rtx, rtx);
extern void ia64_emit_cond_move (rtx, rtx, rtx);
extern int ia64_depz_field_mask (rtx, rtx);
-extern rtx ia64_split_timode (rtx[], rtx, rtx);
+extern void ia64_split_tmode_move (rtx[]);
extern rtx spill_xfmode_operand (rtx, int);
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
extern void ia64_expand_call (rtx, rtx, rtx, int);
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 67df9cb..a0af1b4 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -1361,10 +1361,11 @@ ia64_emit_cond_move (rtx op0, rtx op1, rtx cond)
PATTERN (insn));
}
-/* Split a post-reload TImode reference into two DImode components. */
+/* Split a post-reload TImode or TFmode reference into two DImode
+ components. */
-rtx
-ia64_split_timode (rtx out[2], rtx in, rtx scratch)
+static rtx
+ia64_split_tmode (rtx out[2], rtx in, rtx scratch)
{
switch (GET_CODE (in))
{
@@ -1417,7 +1418,32 @@ ia64_split_timode (rtx out[2], rtx in, rtx scratch)
case CONST_INT:
case CONST_DOUBLE:
- split_double (in, &out[0], &out[1]);
+ if (GET_MODE (in) != TFmode)
+ split_double (in, &out[0], &out[1]);
+ else
+ /* split_double does not understand how to split a TFmode
+ quantity into a pair of DImode constants. */
+ {
+ REAL_VALUE_TYPE r;
+ unsigned HOST_WIDE_INT p[2];
+ long l[4]; /* TFmode is 128 bits */
+
+ REAL_VALUE_FROM_CONST_DOUBLE (r, in);
+ real_to_target (l, &r, TFmode);
+
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ {
+ p[0] = (((unsigned HOST_WIDE_INT) l[0]) << 32) + l[1];
+ p[1] = (((unsigned HOST_WIDE_INT) l[2]) << 32) + l[3];
+ }
+ else
+ {
+ p[0] = (((unsigned HOST_WIDE_INT) l[3]) << 32) + l[2];
+ p[1] = (((unsigned HOST_WIDE_INT) l[1]) << 32) + l[0];
+ }
+ out[0] = GEN_INT (p[0]);
+ out[1] = GEN_INT (p[1]);
+ }
return NULL_RTX;
default:
@@ -1425,6 +1451,46 @@ ia64_split_timode (rtx out[2], rtx in, rtx scratch)
}
}
+/* Split a TImode or TFmode move instruction after reload.
+ This is used by *movtf_internal and *movti_internal. */
+void
+ia64_split_tmode_move (rtx operands[])
+{
+ rtx adj1, adj2, in[2], out[2], insn;
+ int first;
+
+ adj1 = ia64_split_tmode (in, operands[1], operands[2]);
+ adj2 = ia64_split_tmode (out, operands[0], operands[2]);
+
+ first = 0;
+ if (reg_overlap_mentioned_p (out[0], in[1]))
+ {
+ if (reg_overlap_mentioned_p (out[1], in[0]))
+ abort ();
+ first = 1;
+ }
+
+ if (adj1 && adj2)
+ abort ();
+ if (adj1)
+ emit_insn (adj1);
+ if (adj2)
+ emit_insn (adj2);
+ insn = emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first]));
+ if (GET_CODE (out[first]) == MEM
+ && GET_CODE (XEXP (out[first], 0)) == POST_MODIFY)
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
+ XEXP (XEXP (out[first], 0), 0),
+ REG_NOTES (insn));
+ insn = emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first]));
+ if (GET_CODE (out[!first]) == MEM
+ && GET_CODE (XEXP (out[!first], 0)) == POST_MODIFY)
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
+ XEXP (XEXP (out[!first], 0), 0),
+ REG_NOTES (insn));
+
+}
+
/* ??? Fixing GR->FR XFmode moves during reload is hard. You need to go
through memory plus an extra GR scratch register. Except that you can
either get the first from SECONDARY_MEMORY_NEEDED or the second from
@@ -3407,9 +3473,50 @@ hfa_element_mode (tree type, int nested)
return VOIDmode;
}
+/* Return the number of words required to hold a quantity of TYPE and MODE
+ when passed as an argument. */
+static int
+ia64_function_arg_words (tree type, enum machine_mode mode)
+{
+ int words;
+
+ if (mode == BLKmode)
+ words = int_size_in_bytes (type);
+ else
+ words = GET_MODE_SIZE (mode);
+
+ return (words + UNITS_PER_WORD - 1) / UNITS_PER_WORD; /* round up */
+}
+
+/* Return the number of registers that should be skipped so the current
+ argument (described by TYPE and WORDS) will be properly aligned.
+
+ Integer and float arguments larger than 8 bytes start at the next
+ even boundary. Aggregates larger than 8 bytes start at the next
+ even boundary if the aggregate has 16 byte alignment. Note that
+ in the 32-bit ABI, TImode and TFmode have only 8-byte alignment
+ but are still to be aligned in registers.
+
+ ??? The ABI does not specify how to handle aggregates with
+ alignment from 9 to 15 bytes, or greater than 16. We handle them
+ all as if they had 16 byte alignment. Such aggregates can occur
+ only if gcc extensions are used. */
+static int
+ia64_function_arg_offset (CUMULATIVE_ARGS *cum, tree type, int words)
+{
+ if ((cum->words & 1) == 0)
+ return 0;
+
+ if (type
+ && TREE_CODE (type) != INTEGER_TYPE
+ && TREE_CODE (type) != REAL_TYPE)
+ return TYPE_ALIGN (type) > 8 * BITS_PER_UNIT;
+ else
+ return words > 1;
+}
+
/* Return rtx for register where argument is passed, or zero if it is passed
on the stack. */
-
/* ??? 128-bit quad-precision floats are always passed in general
registers. */
@@ -3418,25 +3525,10 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
int named, int incoming)
{
int basereg = (incoming ? GR_ARG_FIRST : AR_ARG_FIRST);
- int words = (((mode == BLKmode ? int_size_in_bytes (type)
- : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
- int offset = 0;
+ int words = ia64_function_arg_words (type, mode);
+ int offset = ia64_function_arg_offset (cum, type, words);
enum machine_mode hfa_mode = VOIDmode;
- /* Integer and float arguments larger than 8 bytes start at the next even
- boundary. Aggregates larger than 8 bytes start at the next even boundary
- if the aggregate has 16 byte alignment. Net effect is that types with
- alignment greater than 8 start at the next even boundary. */
- /* ??? The ABI does not specify how to handle aggregates with alignment from
- 9 to 15 bytes, or greater than 16. We handle them all as if they had
- 16 byte alignment. Such aggregates can occur only if gcc extensions are
- used. */
- if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
- : (words > 1))
- && (cum->words & 1))
- offset = 1;
-
/* If all argument slots are used, then it must go on the stack. */
if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
return 0;
@@ -3590,17 +3682,8 @@ int
ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named ATTRIBUTE_UNUSED)
{
- int words = (((mode == BLKmode ? int_size_in_bytes (type)
- : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
- int offset = 0;
-
- /* Arguments with alignment larger than 8 bytes start at the next even
- boundary. */
- if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
- : (words > 1))
- && (cum->words & 1))
- offset = 1;
+ int words = ia64_function_arg_words (type, mode);
+ int offset = ia64_function_arg_offset (cum, type, words);
/* If all argument slots are used, then it must go on the stack. */
if (cum->words + offset >= MAX_ARGUMENT_SLOTS)
@@ -3624,23 +3707,14 @@ void
ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named)
{
- int words = (((mode == BLKmode ? int_size_in_bytes (type)
- : GET_MODE_SIZE (mode)) + UNITS_PER_WORD - 1)
- / UNITS_PER_WORD);
- int offset = 0;
+ int words = ia64_function_arg_words (type, mode);
+ int offset = ia64_function_arg_offset (cum, type, words);
enum machine_mode hfa_mode = VOIDmode;
/* If all arg slots are already full, then there is nothing to do. */
if (cum->words >= MAX_ARGUMENT_SLOTS)
return;
- /* Arguments with alignment larger than 8 bytes start at the next even
- boundary. */
- if ((type ? (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
- : (words > 1))
- && (cum->words & 1))
- offset = 1;
-
cum->words += words + offset;
/* Check for and handle homogeneous FP aggregates. */
@@ -3750,9 +3824,12 @@ ia64_va_arg (tree valist, tree type)
return gen_rtx_MEM (ptr_mode, addr);
}
- /* Arguments with alignment larger than 8 bytes start at the next even
- boundary. */
- if (TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
+ /* Aggregate arguments with alignment larger than 8 bytes start at
+ the next even boundary. Integer and floating point arguments
+ do so if they are larger than 8 bytes, whether or not they are
+ also aligned larger than 8 bytes. */
+ if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
+ ? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
{
t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
build_int_2 (2 * UNITS_PER_WORD - 1, 0));
@@ -3839,7 +3916,7 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
else
return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
- else if (FLOAT_TYPE_P (valtype) && mode != TFmode)
+ else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
{
@@ -4380,7 +4457,7 @@ ia64_secondary_reload_class (enum reg_class class,
case GR_REGS:
/* Since we have no offsettable memory addresses, we need a temporary
to hold the address of the second word. */
- if (mode == TImode)
+ if (mode == TImode || mode == TFmode)
return GR_REGS;
break;
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index 01e4d73..169569a 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -606,70 +606,7 @@
"reload_completed"
[(const_int 0)]
{
- rtx adj1, adj2, in[2], out[2], insn;
- int first;
-
- adj1 = ia64_split_timode (in, operands[1], operands[2]);
- adj2 = ia64_split_timode (out, operands[0], operands[2]);
-
- first = 0;
- if (reg_overlap_mentioned_p (out[0], in[1]))
- {
- if (reg_overlap_mentioned_p (out[1], in[0]))
- abort ();
- first = 1;
- }
-
- if (adj1 && adj2)
- abort ();
- if (adj1)
- emit_insn (adj1);
- if (adj2)
- emit_insn (adj2);
- insn = emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first]));
- if (GET_CODE (out[first]) == MEM
- && GET_CODE (XEXP (out[first], 0)) == POST_MODIFY)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
- XEXP (XEXP (out[first], 0), 0),
- REG_NOTES (insn));
- insn = emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first]));
- if (GET_CODE (out[!first]) == MEM
- && GET_CODE (XEXP (out[!first], 0)) == POST_MODIFY)
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_INC,
- XEXP (XEXP (out[!first], 0), 0),
- REG_NOTES (insn));
- DONE;
-}
- [(set_attr "itanium_class" "unknown")
- (set_attr "predicable" "no")])
-
-;; ??? SSA creates these. Can't allow memories since we don't have
-;; the scratch register. Fortunately combine will know how to add
-;; the clobber and scratch.
-(define_insn_and_split "*movti_internal_reg"
- [(set (match_operand:TI 0 "register_operand" "=r")
- (match_operand:TI 1 "nonmemory_operand" "ri"))]
- ""
- "#"
- "reload_completed"
- [(const_int 0)]
-{
- rtx in[2], out[2];
- int first;
-
- ia64_split_timode (in, operands[1], NULL_RTX);
- ia64_split_timode (out, operands[0], NULL_RTX);
-
- first = 0;
- if (reg_overlap_mentioned_p (out[0], in[1]))
- {
- if (reg_overlap_mentioned_p (out[1], in[0]))
- abort ();
- first = 1;
- }
-
- emit_insn (gen_rtx_SET (VOIDmode, out[first], in[first]));
- emit_insn (gen_rtx_SET (VOIDmode, out[!first], in[!first]));
+ ia64_split_tmode_move (operands);
DONE;
}
[(set_attr "itanium_class" "unknown")
@@ -677,27 +614,17 @@
(define_expand "reload_inti"
[(parallel [(set (match_operand:TI 0 "register_operand" "=r")
- (match_operand:TI 1 "" "m"))
- (clobber (match_operand:TI 2 "register_operand" "=&r"))])]
+ (match_operand:TI 1 "memory_operand" "m"))
+ (clobber (match_operand:DI 2 "register_operand" "=&r"))])]
""
-{
- unsigned int s_regno = REGNO (operands[2]);
- if (s_regno == REGNO (operands[0]))
- s_regno += 1;
- operands[2] = gen_rtx_REG (DImode, s_regno);
-})
+ "")
(define_expand "reload_outti"
- [(parallel [(set (match_operand:TI 0 "" "=m")
+ [(parallel [(set (match_operand:TI 0 "memory_operand" "=m")
(match_operand:TI 1 "register_operand" "r"))
- (clobber (match_operand:TI 2 "register_operand" "=&r"))])]
+ (clobber (match_operand:DI 2 "register_operand" "=&r"))])]
""
-{
- unsigned int s_regno = REGNO (operands[2]);
- if (s_regno == REGNO (operands[1]))
- s_regno += 1;
- operands[2] = gen_rtx_REG (DImode, s_regno);
-})
+ "")
;; Floating Point Moves
;;
@@ -835,6 +762,51 @@
ldfe %0 = %1%P1
stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
+
+;; Better code generation via insns that deal with TFmode register pairs
+;; directly.
+;; With no offsettable memory references, we've got to have a scratch
+;; around to play with the second word.
+(define_expand "movtf"
+ [(parallel [(set (match_operand:TF 0 "general_operand" "")
+ (match_operand:TF 1 "general_operand" ""))
+ (clobber (match_scratch:DI 2 ""))])]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn_and_split "*movtf_internal"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m")
+ (match_operand:TF 1 "general_operand" "ri,m,r"))
+ (clobber (match_scratch:DI 2 "=X,&r,&r"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ ia64_split_tmode_move (operands);
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown")
+ (set_attr "predicable" "no")])
+
+(define_expand "reload_intf"
+ [(parallel [(set (match_operand:TF 0 "register_operand" "=r")
+ (match_operand:TF 1 "memory_operand" "m"))
+ (clobber (match_operand:DI 2 "register_operand" "=&r"))])]
+ ""
+ "")
+
+(define_expand "reload_outtf"
+ [(parallel [(set (match_operand:TF 0 "memory_operand" "=m")
+ (match_operand:TF 1 "register_operand" "r"))
+ (clobber (match_operand:DI 2 "register_operand" "=&r"))])]
+ ""
+ "")
;; ::::::::::::::::::::
;; ::