/* Subroutines for manipulating rtx's in semantically interesting ways.
Copyright (C) 1987, 1991, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
This file is part of GCC.
We may not immediately return from the recursive call here, lest
all_constant gets lost. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ if (CONST_INT_P (XEXP (x, 1)))
{
c += INTVAL (XEXP (x, 1));
return x;
/* First handle constants appearing at this level explicitly. */
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ if (CONST_INT_P (XEXP (x, 1))
&& 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x), *constptr,
XEXP (x, 1)))
- && GET_CODE (tem) == CONST_INT)
+ && CONST_INT_P (tem))
{
*constptr = tem;
return eliminate_constant_term (XEXP (x, 0), constptr);
if ((x1 != XEXP (x, 1) || x0 != XEXP (x, 0))
&& 0 != (tem = simplify_binary_operation (PLUS, GET_MODE (x),
*constptr, tem))
- && GET_CODE (tem) == CONST_INT)
+ && CONST_INT_P (tem))
{
*constptr = tem;
return gen_rtx_PLUS (GET_MODE (x), x0, x1);
size = TREE_OPERAND (exp, 1);
else
{
- size = lang_hooks.expr_size (exp);
+ size = tree_expr_size (exp);
gcc_assert (size);
- size = SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp);
+ gcc_assert (size == SUBSTITUTE_PLACEHOLDER_IN_EXPR (size, exp));
}
return expand_expr (size, NULL_RTX, TYPE_MODE (sizetype), EXPAND_NORMAL);
size = TREE_OPERAND (exp, 1);
else
{
- size = lang_hooks.expr_size (exp);
+ size = tree_expr_size (exp);
gcc_assert (size);
}
narrower. */
if (GET_MODE_SIZE (to_mode) < GET_MODE_SIZE (from_mode)
|| (GET_CODE (x) == PLUS
- && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && CONST_INT_P (XEXP (x, 1))
&& (XEXP (x, 1) == convert_memory_address (to_mode, XEXP (x, 1))
|| POINTERS_EXTEND_UNSIGNED < 0)))
return gen_rtx_fmt_ee (GET_CODE (x), to_mode,
in certain cases. This is not necessary since the code
below can handle all possible cases, but machine-dependent
transformations can make better code. */
- LEGITIMIZE_ADDRESS (x, oldx, mode, done);
+ {
+ rtx orig_x = x;
+ x = targetm.legitimize_address (x, oldx, mode);
+ if (orig_x != x && memory_address_p (mode, x))
+ goto done;
+ }
/* PLUS and MULT can appear in special ways
as the result of attempts to make an address usable for indexing.
mark_reg_pointer (x, BITS_PER_UNIT);
else if (GET_CODE (x) == PLUS
&& REG_P (XEXP (x, 0))
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (x, 1)))
mark_reg_pointer (XEXP (x, 0), BITS_PER_UNIT);
/* OLDX may have been the address on a temporary. Update the address
offset = 0;
if (GET_CODE (base) == CONST
&& GET_CODE (XEXP (base, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (base, 0), 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (XEXP (base, 0), 1)))
{
offset += INTVAL (XEXP (XEXP (base, 0), 1));
base = XEXP (XEXP (base, 0), 0);
else if (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
- && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
{
rtx s = XEXP (XEXP (x, 0), 0);
rtx c = XEXP (XEXP (x, 0), 1);
align = MIN (sa, ca);
}
- else if (MEM_P (x) && MEM_POINTER (x))
- align = MEM_ALIGN (x);
- if (align)
+ if (align || (MEM_P (x) && MEM_POINTER (x)))
mark_reg_pointer (temp, align);
}
return temp;
}
\f
-/* Return the mode to use to store a scalar of TYPE and MODE.
+/* Return the mode to use to pass or return a scalar of TYPE and MODE.
PUNSIGNEDP points to the signedness of the type and may be adjusted
to show what signedness to use on extension operations.
- FOR_CALL is nonzero if this call is promoting args for a call. */
+ FOR_RETURN is nonzero if the caller is promoting the return value
+ of FNDECL, else it is for promoting args. */
-#if defined(PROMOTE_MODE) && !defined(PROMOTE_FUNCTION_MODE)
-#define PROMOTE_FUNCTION_MODE PROMOTE_MODE
-#endif
+enum machine_mode
+promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp,
+ const_tree funtype, int for_return)
+{
+ switch (TREE_CODE (type))
+ {
+ case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
+ case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
+ case POINTER_TYPE: case REFERENCE_TYPE:
+ return targetm.calls.promote_function_mode (type, mode, punsignedp, funtype,
+ for_return);
+
+ default:
+ return mode;
+ }
+}
+/* Return the mode to use to store a scalar of TYPE and MODE.
+ PUNSIGNEDP points to the signedness of the type and may be adjusted
+ to show what signedness to use on extension operations. */
enum machine_mode
-promote_mode (const_tree type, enum machine_mode mode, int *punsignedp,
- int for_call ATTRIBUTE_UNUSED)
+promote_mode (const_tree type ATTRIBUTE_UNUSED, enum machine_mode mode,
+ int *punsignedp ATTRIBUTE_UNUSED)
{
+ /* FIXME: this is the same logic that was there until GCC 4.4, but we
+ probably want to test POINTERS_EXTEND_UNSIGNED even if PROMOTE_MODE
+ is not defined. The affected targets are M32C, S390, SPARC. */
+#ifdef PROMOTE_MODE
const enum tree_code code = TREE_CODE (type);
int unsignedp = *punsignedp;
-#ifndef PROMOTE_MODE
- if (! for_call)
- return mode;
-#endif
-
switch (code)
{
-#ifdef PROMOTE_FUNCTION_MODE
case INTEGER_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE:
case REAL_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE:
-#ifdef PROMOTE_MODE
- if (for_call)
- {
-#endif
- PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
-#ifdef PROMOTE_MODE
- }
- else
- {
- PROMOTE_MODE (mode, unsignedp, type);
- }
-#endif
+ PROMOTE_MODE (mode, unsignedp, type);
+ *punsignedp = unsignedp;
+ return mode;
break;
-#endif
#ifdef POINTERS_EXTEND_UNSIGNED
case REFERENCE_TYPE:
case POINTER_TYPE:
- mode = Pmode;
- unsignedp = POINTERS_EXTEND_UNSIGNED;
+ *punsignedp = POINTERS_EXTEND_UNSIGNED;
+ return Pmode;
break;
#endif
default:
- break;
+ return mode;
}
-
- *punsignedp = unsignedp;
+#else
return mode;
+#endif
+}
+
+
+/* Use one of promote_mode or promote_function_mode to find the promoted
+ mode of DECL. If PUNSIGNEDP is not NULL, store there the unsignedness
+ of DECL after promotion. */
+
+enum machine_mode
+promote_decl_mode (const_tree decl, int *punsignedp)
+{
+ tree type = TREE_TYPE (decl);
+ int unsignedp = TYPE_UNSIGNED (type);
+ enum machine_mode mode = DECL_MODE (decl);
+ enum machine_mode pmode;
+
+ if (TREE_CODE (decl) == RESULT_DECL
+ || TREE_CODE (decl) == PARM_DECL)
+ pmode = promote_function_mode (type, mode, &unsignedp,
+ TREE_TYPE (current_function_decl), 2);
+ else
+ pmode = promote_mode (type, mode, &unsignedp);
+
+ if (punsignedp)
+ *punsignedp = unsignedp;
+ return pmode;
}
+
\f
/* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
This pops when ADJUST is positive. ADJUST need not be constant. */
/* We expect all variable sized adjustments to be multiple of
PREFERRED_STACK_BOUNDARY. */
- if (GET_CODE (adjust) == CONST_INT)
+ if (CONST_INT_P (adjust))
stack_pointer_delta -= INTVAL (adjust);
temp = expand_binop (Pmode,
/* We expect all variable sized adjustments to be multiple of
PREFERRED_STACK_BOUNDARY. */
- if (GET_CODE (adjust) == CONST_INT)
+ if (CONST_INT_P (adjust))
stack_pointer_delta += INTVAL (adjust);
temp = expand_binop (Pmode,
if (align == 1)
return size;
- if (GET_CODE (size) == CONST_INT)
+ if (CONST_INT_P (size))
{
HOST_WIDE_INT new_size = (INTVAL (size) + align - 1) / align * align;
alignment. This constraint may be too strong. */
gcc_assert (PREFERRED_STACK_BOUNDARY == BIGGEST_ALIGNMENT);
- if (GET_CODE (size) == CONST_INT)
+ if (CONST_INT_P (size))
{
HOST_WIDE_INT new_size = INTVAL (size) / align * align;
/* If we have to generate explicit probes, see if we have a constant
small number of them to generate. If so, that's the easy case. */
- else if (GET_CODE (size) == CONST_INT
+ else if (CONST_INT_P (size)
&& INTVAL (size) < 10 * STACK_CHECK_PROBE_INTERVAL)
{
HOST_WIDE_INT offset;
in which a scalar value of mode MODE was returned by a library call. */
rtx
-hard_libcall_value (enum machine_mode mode)
+hard_libcall_value (enum machine_mode mode, rtx fun)
{
- return LIBCALL_VALUE (mode);
+ return targetm.calls.libcall_value (mode, fun);
}
/* Look up the tree code for a given rtx code