#include "hashtab.h"
#include "langhooks.h"
#include "cfglayout.h"
+#include "tree-gimple.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
/* Current frame information calculated by ia64_compute_frame_size. */
static struct ia64_frame_info current_frame_info;
\f
-static int ia64_use_dfa_pipeline_interface (void);
static int ia64_first_cycle_multipass_dfa_lookahead (void);
static void ia64_dependencies_evaluation_hook (rtx, rtx);
static void ia64_init_dfa_pre_cycle_insn (void);
static enum machine_mode hfa_element_mode (tree, int);
static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
tree, int *, int);
+static bool ia64_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
static bool ia64_function_ok_for_sibcall (tree, tree);
static bool ia64_return_in_memory (tree, tree);
static bool ia64_rtx_costs (rtx, int, int, int *);
ATTRIBUTE_UNUSED;
static void ia64_hpux_init_libfuncs (void)
ATTRIBUTE_UNUSED;
+static void ia64_sysv4_init_libfuncs (void)
+ ATTRIBUTE_UNUSED;
static void ia64_vms_init_libfuncs (void)
ATTRIBUTE_UNUSED;
static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
static void ia64_encode_section_info (tree, rtx, int);
static rtx ia64_struct_value_rtx (tree, int);
+static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
\f
/* Table of valid machine attributes. */
#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE ia64_use_dfa_pipeline_interface
-
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE ia64_pass_by_reference
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY ia64_return_in_memory
-
#undef TARGET_SETUP_INCOMING_VARARGS
#define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
-struct gcc_target targetm = TARGET_INITIALIZER;
-\f
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op) && mode != VOIDmode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
- || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
-}
-
-/* Return 1 if OP refers to a symbol in the sdata section. */
-
-int
-sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- if (GET_CODE (XEXP (op, 0)) != PLUS
- || GET_CODE (XEXP (XEXP (op, 0), 0)) != SYMBOL_REF)
- break;
- op = XEXP (XEXP (op, 0), 0);
- /* FALLTHRU */
-
- case SYMBOL_REF:
- if (CONSTANT_POOL_ADDRESS_P (op))
- return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold;
- else
- return SYMBOL_REF_LOCAL_P (op) && SYMBOL_REF_SMALL_P (op);
-
- default:
- break;
- }
-
- return 0;
-}
-
-int
-small_addr_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return SYMBOL_REF_SMALL_ADDR_P (op);
-}
-
-/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */
-
-int
-got_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- op = XEXP (op, 1);
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return 1;
-
- /* Ok if we're not using GOT entries at all. */
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- return 1;
-
- /* "Ok" while emitting rtl, since otherwise we won't be provided
- with the entire offset during emission, which makes it very
- hard to split the offset into high and low parts. */
- if (rtx_equal_function_value_matters)
- return 1;
-
- /* Force the low 14 bits of the constant to zero so that we do not
- use up so many GOT entries. */
- return (INTVAL (op) & 0x3fff) == 0;
-
- case SYMBOL_REF:
- if (SYMBOL_REF_SMALL_ADDR_P (op))
- return 0;
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return 1 if OP refers to a symbol. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return tls_model if OP refers to a TLS symbol. */
-
-int
-tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-
-/* Return 1 if OP refers to a function. */
-
-int
-function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op))
- return 1;
- else
- return 0;
-}
-
-/* Return 1 if OP is setjmp or a similar function. */
-
-/* ??? This is an unsatisfying solution. Should rethink. */
-
-int
-setjmp_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- const char *name;
- int retval = 0;
-
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
-
- name = XSTR (op, 0);
-
- /* The following code is borrowed from special_function_p in calls.c. */
-
- /* Disregard prefix _, __ or __x. */
- if (name[0] == '_')
- {
- if (name[1] == '_' && name[2] == 'x')
- name += 3;
- else if (name[1] == '_')
- name += 2;
- else
- name += 1;
- }
-
- if (name[0] == 's')
- {
- retval
- = ((name[1] == 'e'
- && (! strcmp (name, "setjmp")
- || ! strcmp (name, "setjmp_syscall")))
- || (name[1] == 'i'
- && ! strcmp (name, "sigsetjmp"))
- || (name[1] == 'a'
- && ! strcmp (name, "savectx")));
- }
- else if ((name[0] == 'q' && name[1] == 's'
- && ! strcmp (name, "qsetjmp"))
- || (name[0] == 'v' && name[1] == 'f'
- && ! strcmp (name, "vfork")))
- retval = 1;
-
- return retval;
-}
-
-/* Return 1 if OP is a general operand, excluding tls symbolic operands. */
-
-int
-move_operand (rtx op, enum machine_mode mode)
-{
- return general_operand (op, mode) && !tls_symbolic_operand (op, mode);
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR reg. */
-
-int
-gr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) an FR reg. */
-
-int
-fr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg. */
-
-int
-grfr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg. */
-
-int
-gr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg. */
-
-int
-fr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg. */
-
-int
-grfr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a GR register operand, or zero. */
-
-int
-gr_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- return (op == const0_rtx || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand. */
-
-int
-gr_reg_or_5bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand. */
-
-int
-gr_reg_or_6bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
-/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand. */
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT process_for_unwind_directive
-int
-gr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate. */
-
-int
-grfr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || grfr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate
- operand. */
-
-int
-gr_reg_or_8bit_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
-/* Return 1 if OP is a register operand, or is valid for both an 8 bit
- immediate and an 8 bit adjusted immediate operand. This is necessary
- because when we emit a compare, we don't know what the condition will be,
- so we need the union of the immediates accepted by GT and LT. */
-
-int
-gr_reg_or_8bit_and_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
- && CONST_OK_FOR_L (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 14 bit immediate operand. */
-
-int
-gr_reg_or_14bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 22 bit immediate operand. */
-
-int
-gr_reg_or_22bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a 6 bit immediate operand. */
-
-int
-shift_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)));
-}
-
-/* Return 1 if OP is a 5 bit immediate operand. */
-
-int
-shift_32bit_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) < 32));
-}
-
-/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand. */
-
-int
-shladd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == 2 || INTVAL (op) == 4
- || INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand. */
-
-int
-fetchadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
- INTVAL (op) == -4 || INTVAL (op) == -1 ||
- INTVAL (op) == 1 || INTVAL (op) == 4 ||
- INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a floating-point constant zero, one, or a register. */
-
-int
-fr_reg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
- || fr_register_operand (op, mode));
-}
-
-/* Like nonimmediate_operand, but don't allow MEMs that try to use a
- POST_MODIFY with a REG as displacement. */
-
-int
-destination_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == POST_MODIFY
- && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
- return 0;
- return 1;
-}
-
-/* Like memory_operand, but don't allow post-increments. */
-
-int
-not_postinc_memory_operand (rtx op, enum machine_mode mode)
-{
- return (memory_operand (op, mode)
- && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC);
-}
-
-/* Return 1 if this is a comparison operator, which accepts a normal 8-bit
- signed immediate operand. */
-
-int
-normal_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == EQ || code == NE
- || code == GT || code == LE || code == GTU || code == LEU));
-}
-
-/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit
- signed immediate operand. */
-
-int
-adjusted_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == LT || code == GE || code == LTU || code == GEU));
-}
-
-/* Return 1 if this is a signed inequality operator. */
-
-int
-signed_inequality_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == GE || code == GT
- || code == LE || code == LT));
-}
-
-/* Return 1 if this operator is valid for predication. */
-
-int
-predicate_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == EQ || code == NE));
-}
-
-/* Return 1 if this operator can be used in a conditional operation. */
-
-int
-condop_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == PLUS || code == MINUS || code == AND
- || code == IOR || code == XOR));
-}
-
-/* Return 1 if this is the ar.lc register. */
-
-int
-ar_lc_reg_operand (register rtx op, enum machine_mode mode)
-{
- return (GET_MODE (op) == DImode
- && (mode == DImode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_LC_REGNUM);
-}
-
-/* Return 1 if this is the ar.ccv register. */
-
-int
-ar_ccv_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_CCV_REGNUM);
-}
-
-/* Return 1 if this is the ar.pfs register. */
-
-int
-ar_pfs_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_PFS_REGNUM);
-}
-
-/* Like general_operand, but don't allow (mem (addressof)). */
-
-int
-general_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! general_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-destination_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! destination_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-xfreg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG)
- return 0;
- return fr_reg_or_fp01_operand (op, mode);
-}
-
-/* Return 1 if OP is valid as a base register in a reg + offset address. */
-
-int
-basereg_operand (rtx op, enum machine_mode mode)
-{
- /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
- checks from pa.c basereg_operand as well? Seems to be OK without them
- in test runs. */
-
- return (register_operand (op, mode) &&
- REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
-}
+struct gcc_target targetm = TARGET_INITIALIZER;
\f
typedef enum
{
void
ia64_expand_load_address (rtx dest, rtx src)
{
- if (tls_symbolic_operand (src, VOIDmode))
+ if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (src))
abort ();
if (GET_CODE (dest) != REG)
abort ();
if (GET_CODE (src) == CONST
&& GET_CODE (XEXP (src, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
- && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
+ && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x3fff) != 0)
{
rtx sym = XEXP (XEXP (src, 0), 0);
HOST_WIDE_INT ofs, hi, lo;
gen_thread_pointer (void)
{
if (!thread_pointer_rtx)
- {
- thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
- RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
- }
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
return thread_pointer_rtx;
}
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ tga_op1 = gen_const_mem (Pmode, tga_op1);
tga_op2 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
- tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
- RTX_UNCHANGING_P (tga_op2) = 1;
+ tga_op2 = gen_const_mem (Pmode, tga_op2);
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
LCT_CONST, Pmode, 2, tga_op1,
tga_op1 = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ tga_op1 = gen_const_mem (Pmode, tga_op1);
tga_op2 = const0_rtx;
case TLS_MODEL_INITIAL_EXEC:
tmp = gen_reg_rtx (Pmode);
emit_insn (gen_load_ltoff_tprel (tmp, op1));
- tmp = gen_rtx_MEM (Pmode, tmp);
- RTX_UNCHANGING_P (tmp) = 1;
+ tmp = gen_const_mem (Pmode, tmp);
tmp = force_reg (Pmode, tmp);
if (!register_operand (op0, Pmode))
if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
{
enum tls_model tls_kind;
- if ((tls_kind = tls_symbolic_operand (op1, VOIDmode)))
+ if (GET_CODE (op1) == SYMBOL_REF
+ && (tls_kind = SYMBOL_REF_TLS_MODEL (op1)))
return ia64_expand_tls_address (tls_kind, op0, op1);
if (!TARGET_NO_PIC && reload_completed)
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
- rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memt = assign_stack_temp (TImode, 16, 0);
+ emit_move_insn (memt, SUBREG_REG (in));
+ return adjust_address (memt, XFmode, 0);
}
else if (force && GET_CODE (in) == REG)
{
- rtx mem = gen_mem_addressof (in, NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memx = assign_stack_temp (XFmode, 16, 0);
+ emit_move_insn (memx, in);
+ return memx;
}
- else if (GET_CODE (in) == MEM
- && GET_CODE (XEXP (in, 0)) == ADDRESSOF)
- return change_address (in, XFmode, copy_to_reg (XEXP (in, 0)));
else
return in;
}
/* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
magic number as its third argument, that indicates what to do.
The return value is an integer to be compared against zero. */
- else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
+ else if (GET_MODE (op0) == TFmode)
{
enum qfcmp_magic {
QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */
} magic;
enum rtx_code ncode;
rtx ret, insns;
- if (GET_MODE (op1) != TFmode)
+ if (!cmptf_libfunc || GET_MODE (op1) != TFmode)
abort ();
switch (code)
{
case NE: magic = QCMP_EQ; ncode = EQ; break;
/* isunordered() from C99. */
case UNORDERED: magic = QCMP_UNORD; ncode = NE; break;
+ case ORDERED: magic = QCMP_UNORD; ncode = EQ; break;
/* Relational operators raise FP_INVALID when given
an SNaN operand. */
case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break;
if (optimize)
{
edge e;
+ edge_iterator ei;
- for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
if ((e->flags & EDGE_FAKE) == 0
&& (e->flags & EDGE_FALLTHRU) != 0)
break;
preserve those input registers used as arguments to the sibling call.
It is unclear how to compute that number here. */
if (current_frame_info.n_input_regs != 0)
- emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
- const0_rtx, const0_rtx,
- GEN_INT (current_frame_info.n_input_regs),
- const0_rtx));
+ {
+ rtx n_inputs = GEN_INT (current_frame_info.n_input_regs);
+ insn = emit_insn (gen_alloc (gen_rtx_REG (DImode, fp),
+ const0_rtx, const0_rtx,
+ n_inputs, const0_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
}
}
}
}
+ /* Make sure addresses are Pmode even if we are in ILP32 mode. */
+ addr = convert_memory_address (Pmode, addr);
+ fnaddr = convert_memory_address (Pmode, fnaddr);
+ static_chain = convert_memory_address (Pmode, static_chain);
+
/* Load up our iterator. */
addr_reg = gen_reg_rtx (Pmode);
emit_move_insn (addr_reg, addr);
else if (gr_size > UNITS_PER_WORD)
int_regs += gr_size / UNITS_PER_WORD;
}
-
- /* If we ended up using just one location, just return that one loc, but
- change the mode back to the argument mode. */
- if (i == 1)
- return gen_rtx_REG (mode, REGNO (XEXP (loc[0], 0)));
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
/* Integral and aggregates go in general registers. If we have run out of
cum->fp_regs = fp_regs;
}
- /* Integral and aggregates go in general registers. If we have run out of
- FR registers, then FP values must also go in general registers. This can
- happen when we have a SFmode HFA. */
- else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
+ /* Integral and aggregates go in general registers. So do TFmode FP values.
+ If we have run out of FR registers, then other FP values must also go in
+ general registers. This can happen when we have a SFmode HFA. */
+ else if (mode == TFmode || mode == TCmode
+ || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
}
}
+/* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. On ILP32 HPUX, TFmode arguments start on next even boundary
+ even though their normal alignment is 8 bytes. See ia64_function_arg. */
+
+int
+ia64_function_arg_boundary (enum machine_mode mode, tree type)
+{
+
+ if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
+ return PARM_BOUNDARY * 2;
+
+ if (type)
+ {
+ if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+ }
+
+ if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+}
+
/* Variable sized types are passed by reference. */
/* ??? At present this is a GCC extension to the IA-64 ABI. */
-int
-ia64_function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int named ATTRIBUTE_UNUSED)
+static bool
+ia64_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type, bool named ATTRIBUTE_UNUSED)
{
return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
}
static bool
ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
+ /* We can't perform a sibcall if the current function has the syscall_linkage
+ attribute. */
+ if (lookup_attribute ("syscall_linkage",
+ TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
+ return false;
+
/* We must always return with our current GP. This means we can
only sibcall to functions defined in the current module. */
return decl && (*targetm.binds_local_p) (decl);
/* Implement va_arg. */
-rtx
-ia64_va_arg (tree valist, tree type)
+static tree
+ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{
- tree t;
-
/* Variable sized types are passed by reference. */
- if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
- rtx addr = force_reg (ptr_mode,
- std_expand_builtin_va_arg (valist, build_pointer_type (type)));
-#ifdef POINTERS_EXTEND_UNSIGNED
- addr = convert_memory_address (Pmode, addr);
-#endif
- return gen_rtx_MEM (ptr_mode, addr);
+ tree ptrtype = build_pointer_type (type);
+ tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
+ return build_va_arg_indirect_ref (addr);
}
/* Aggregate arguments with alignment larger than 8 bytes start at
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));
+ tree t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
+ build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
- build_int_2 (-2 * UNITS_PER_WORD, -1));
+ build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ gimplify_and_add (t, pre_p);
}
- return std_expand_builtin_va_arg (valist, type);
+ return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
\f
/* Return 1 if function return value returned in memory. Return 0 if it is
GEN_INT (offset));
offset += hfa_size;
}
-
- if (i == 1)
- return XEXP (loc[0], 0);
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
}
/* For all ASM_OPERANDS, we must traverse the vector of input operands.
- We can not just fall through here since then we would be confused
+ We cannot just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
HOST_WIDE_INT bit = (offset >> 3) & 63;
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
- new_flags.is_write = (XINT (x, 1) == 1);
+ new_flags.is_write = (XINT (x, 1) == UNSPEC_GR_SPILL);
need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
new_flags, pred);
break;
static rtx dfa_pre_cycle_insn;
-/* We are about to being issuing INSN. Return nonzero if we can not
+/* We are about to being issuing INSN. Return nonzero if we cannot
issue it on given cycle CLOCK and return zero if we should not sort
the ready queue on the next clock start. */
}
else if (reload_completed)
setup_clocks_p = TRUE;
- memcpy (curr_state, prev_cycle_state, dfa_state_size);
- state_transition (curr_state, dfa_stop_insn);
- state_transition (curr_state, dfa_pre_cycle_insn);
- state_transition (curr_state, NULL);
+ if (GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
+ || asm_noperands (PATTERN (last_scheduled_insn)) >= 0)
+ state_reset (curr_state);
+ else
+ {
+ memcpy (curr_state, prev_cycle_state, dfa_state_size);
+ state_transition (curr_state, dfa_stop_insn);
+ state_transition (curr_state, dfa_pre_cycle_insn);
+ state_transition (curr_state, NULL);
+ }
}
else if (reload_completed)
setup_clocks_p = TRUE;
- if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM)
+ if (setup_clocks_p && ia64_tune == PROCESSOR_ITANIUM
+ && GET_CODE (PATTERN (insn)) != ASM_INPUT
+ && asm_noperands (PATTERN (insn)) < 0)
{
enum attr_itanium_class c = ia64_safe_itanium_class (insn);
by structure bundle_state (see above). If we generate the same
bundle state (key is automaton state after issuing the insns and
nops for it), we reuse already generated one. As consequence we
- reject some decisions which can not improve the solution and
+ reject some decisions which cannot improve the solution and
reduce memory for the algorithm.
When we reach the end of EBB (extended basic block), we choose the
guarantee issuing all insns on the same cycle for
Itanium 1, we need to issue 2 nops after the first M
insn (MnnMII where n is a nop insn). */
- || (type == TYPE_M && ia64_tune == PROCESSOR_ITANIUM
+ || ((type == TYPE_M || type == TYPE_A)
+ && ia64_tune == PROCESSOR_ITANIUM
&& !bundle_end_p && pos == 1))
issue_nops_and_insn (curr_state, 2, insn, bundle_end_p,
only_bundle_end_p);
= gen_bundle_selector (const2_rtx); /* -> MFI */
break;
}
- else if (recog_memoized (last) != CODE_FOR_insn_group_barrier)
+ else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
+ && (ia64_safe_itanium_class (last)
+ != ITANIUM_CLASS_IGNORE))
n++;
/* Some check of correctness: the stop is not at the
bundle start, there are no more 3 insns in the bundle,
insn scheduler. */
static int
-ia64_use_dfa_pipeline_interface (void)
-{
- return 1;
-}
-
-/* If the following function returns TRUE, we will use the the DFA
- insn scheduler. */
-
-static int
ia64_first_cycle_multipass_dfa_lookahead (void)
{
return (reload_completed ? 6 : 4);
insn = get_last_insn ();
if (! INSN_P (insn))
insn = prev_active_insn (insn);
- if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
- {
- saw_stop = 1;
+ /* Skip over insns that expand to nothing. */
+ while (GET_CODE (insn) == INSN && get_attr_empty (insn) == EMPTY_YES)
+ {
+ if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
+ && XINT (PATTERN (insn), 1) == UNSPECV_INSN_GROUP_BARRIER)
+ saw_stop = 1;
insn = prev_active_insn (insn);
}
if (GET_CODE (insn) == CALL_INSN)
{
dest_regno = REGNO (dest);
- /* If this isn't the final destination for ar.pfs, the alloc
- shouldn't have been marked frame related. */
- if (dest_regno != current_frame_info.reg_save_ar_pfs)
- abort ();
-
- fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ /* If this is the final destination for ar.pfs, then this must
+ be the alloc in the prologue. */
+ if (dest_regno == current_frame_info.reg_save_ar_pfs)
+ fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ else
+ {
+ /* This must be an alloc before a sibcall. We must drop the
+ old frame info. The easiest way to drop the old frame
+ info is to ensure we had a ".restore sp" directive
+ followed by a new prologue. If the procedure doesn't
+ have a memory-stack frame, we'll issue a dummy ".restore
+ sp" now. */
+ if (current_frame_info.total_size == 0)
+ /* if haven't done process_epilogue() yet, do it now */
+ process_epilogue ();
+ fprintf (asm_out_file, "\t.prologue\n");
+ }
return 1;
}
fpreg_type = make_node (REAL_TYPE);
/* ??? The back end should know to load/save __fpreg variables using
the ldf.fill and stf.spill instructions. */
- TYPE_PRECISION (fpreg_type) = 96;
+ TYPE_PRECISION (fpreg_type) = 80;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type) = 96;
+ TYPE_PRECISION (float80_type) = 80;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float128");
-#define def_builtin(name, type, code) \
- builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
+#define def_builtin(name, type, code) \
+ lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, \
+ NULL, NULL_TREE)
def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
}
/* Set SImode div/mod functions, init_integral_libfuncs only initializes
- modes of word_mode and larger. */
+ modes of word_mode and larger. Rename the TFmode libfuncs using the
+ HPUX conventions. __divtf3 is used for XFmode. We need to keep it for
+ backward compatibility. */
static void
ia64_init_libfuncs (void)
set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
set_optab_libfunc (smod_optab, SImode, "__modsi3");
set_optab_libfunc (umod_optab, SImode, "__umodsi3");
+
+ set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
+ set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
+ set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
+ set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
+ set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
+
+ set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+ set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
+
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
+ set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
+ set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
+
+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+ set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
}
/* Rename all the TFmode libfuncs using the HPUX conventions. */
{
ia64_init_libfuncs ();
- set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
- set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
- set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
- set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
- set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
/* ia64_expand_compare uses this. */
cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
set_optab_libfunc (ge_optab, TFmode, 0);
set_optab_libfunc (lt_optab, TFmode, 0);
set_optab_libfunc (le_optab, TFmode, 0);
-
- set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
- set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
- set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
- set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
-
- set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
- set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
- set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
- set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
-
- set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
- set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
}
/* Rename the division and modulus functions in VMS. */
set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
}
+
+/* Rename the TFmode libfuncs available from soft-fp in glibc using
+ the HPUX conventions. */
+
+static void
+ia64_sysv4_init_libfuncs (void)
+{
+ ia64_init_libfuncs ();
+
+ /* These functions are not part of the HPUX TFmode interface. We
+ use them instead of _U_Qfcmp, which doesn't work the way we
+ expect. */
+ set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+ set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+ set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+ set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+ set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+ set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
+
+ /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
+ glibc doesn't have them. */
+}
\f
/* Switch to the section to which we should output X. The only thing
special we do here is to honor small data. */
reload_completed = 1;
epilogue_completed = 1;
no_new_pseudos = 1;
+ reset_block_changes ();
/* Set things up as ia64_expand_prologue might. */
last_scratch_gr_reg = 15;
return gen_rtx_REG (Pmode, GR_REG (8));
}
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ case TImode:
+ return true;
+
+ case SFmode:
+ case DFmode:
+ case XFmode:
+ return true;
+
+ case TFmode:
+ return TARGET_HPUX;
+
+ default:
+ return false;
+ }
+}
+
#include "gt-ia64.h"