/* Generic hooks for the RTL middle-end.
- Copyright (C) 2004 Free Software Foundation, Inc.
+ Copyright (C) 2004-2015 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "tm.h"
#include "rtl.h"
#include "rtlhooks-def.h"
+#include "symtab.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "flags.h"
+#include "alias.h"
+#include "tree.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
+#include "recog.h"
\f
/* For speed, we will copy the RTX hooks struct member-by-member
struct rtl_hooks rtl_hooks = RTL_HOOKS_INITIALIZER;
rtx
-gen_lowpart_general (enum machine_mode mode, rtx x)
+gen_lowpart_general (machine_mode mode, rtx x)
{
rtx result = gen_lowpart_common (mode, x);
if (result)
return result;
- else if (REG_P (x))
+ /* Handle SUBREGs and hard REGs that were rejected by
+ simplify_gen_subreg. */
+ else if (REG_P (x) || GET_CODE (x) == SUBREG)
{
- /* Must be a hard reg that's not valid in MODE. */
result = gen_lowpart_common (mode, copy_to_reg (x));
gcc_assert (result != 0);
return result;
/* The following exposes the use of "x" to CSE. */
if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
&& SCALAR_INT_MODE_P (GET_MODE (x))
- && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (mode),
- GET_MODE_BITSIZE (GET_MODE (x)))
- && ! no_new_pseudos)
+ && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x))
+ && !reload_completed)
return gen_lowpart_general (mode, force_reg (GET_MODE (x), x));
if (WORDS_BIG_ENDIAN)
}
}
-/* Similar to gen_lowpart, but cannot emit any instruction via
- copy_to_reg or force_reg. Mainly used in simplify-rtx.c. */
rtx
-gen_lowpart_no_emit_general (enum machine_mode mode, rtx x)
-{
- rtx result = gen_lowpart_common (mode, x);
- if (result)
- return result;
- if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode)
- return gen_lowpart_SUBREG (mode, x);
- return x;
-}
-
-rtx
-reg_num_sign_bit_copies_general (rtx x ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx known_x ATTRIBUTE_UNUSED,
- enum machine_mode known_mode ATTRIBUTE_UNUSED,
+reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ const_rtx known_x ATTRIBUTE_UNUSED,
+ machine_mode known_mode ATTRIBUTE_UNUSED,
unsigned int known_ret ATTRIBUTE_UNUSED,
unsigned int *result ATTRIBUTE_UNUSED)
{
}
rtx
-reg_nonzero_bits_general (rtx x ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx known_x ATTRIBUTE_UNUSED,
- enum machine_mode known_mode ATTRIBUTE_UNUSED,
+reg_nonzero_bits_general (const_rtx x ATTRIBUTE_UNUSED,
+ machine_mode mode ATTRIBUTE_UNUSED,
+ const_rtx known_x ATTRIBUTE_UNUSED,
+ machine_mode known_mode ATTRIBUTE_UNUSED,
unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
unsigned HOST_WIDE_INT *nonzero ATTRIBUTE_UNUSED)
{
return NULL;
}
+
+bool
+reg_truncated_to_mode_general (machine_mode mode ATTRIBUTE_UNUSED,
+ const_rtx x ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
+ number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
+ least-significant part of X.
+ MODE specifies how big a part of X to return.
+
+ If the requested operation cannot be done, 0 is returned.
+
+ This is similar to gen_lowpart_general. */
+
+rtx
+gen_lowpart_if_possible (machine_mode mode, rtx x)
+{
+ rtx result = gen_lowpart_common (mode, x);
+
+ if (result)
+ return result;
+ else if (MEM_P (x))
+ {
+ /* This is the only other case we handle. */
+ int offset = 0;
+ rtx new_rtx;
+
+ if (WORDS_BIG_ENDIAN)
+ offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
+ - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
+ if (BYTES_BIG_ENDIAN)
+ /* Adjust the address so that the address-after-the-data is
+ unchanged. */
+ offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
+ - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
+
+ new_rtx = adjust_address_nv (x, mode, offset);
+ if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0),
+ MEM_ADDR_SPACE (x)))
+ return 0;
+
+ return new_rtx;
+ }
+ else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode
+ && validate_subreg (mode, GET_MODE (x), x,
+ subreg_lowpart_offset (mode, GET_MODE (x))))
+ return gen_lowpart_SUBREG (mode, x);
+ else
+ return 0;
+}
+\f