| 1 |
684 |
jeremybenn |
/* Generic hooks for the RTL middle-end.
|
| 2 |
|
|
Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
|
| 3 |
|
|
|
| 4 |
|
|
This file is part of GCC.
|
| 5 |
|
|
|
| 6 |
|
|
GCC is free software; you can redistribute it and/or modify it under
|
| 7 |
|
|
the terms of the GNU General Public License as published by the Free
|
| 8 |
|
|
Software Foundation; either version 3, or (at your option) any later
|
| 9 |
|
|
version.
|
| 10 |
|
|
|
| 11 |
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
| 12 |
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| 13 |
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
| 14 |
|
|
for more details.
|
| 15 |
|
|
|
| 16 |
|
|
You should have received a copy of the GNU General Public License
|
| 17 |
|
|
along with GCC; see the file COPYING3. If not see
|
| 18 |
|
|
<http://www.gnu.org/licenses/>. */
|
| 19 |
|
|
|
| 20 |
|
|
#include "config.h"
|
| 21 |
|
|
#include "system.h"
|
| 22 |
|
|
#include "coretypes.h"
|
| 23 |
|
|
#include "tm.h"
|
| 24 |
|
|
#include "rtl.h"
|
| 25 |
|
|
#include "rtlhooks-def.h"
|
| 26 |
|
|
#include "expr.h"
|
| 27 |
|
|
#include "recog.h"
|
| 28 |
|
|
|
| 29 |
|
|
|
| 30 |
|
|
/* For speed, we will copy the RTX hooks struct member-by-member
|
| 31 |
|
|
instead of doing indirect calls. For these reason, we initialize
|
| 32 |
|
|
*two* struct rtl_hooks globals: rtl_hooks is the one that is used
|
| 33 |
|
|
to actually call the hooks, while general_rtl_hooks is used
|
| 34 |
|
|
to restore the hooks by passes that modify them. */
|
| 35 |
|
|
|
| 36 |
|
|
const struct rtl_hooks general_rtl_hooks = RTL_HOOKS_INITIALIZER;
|
| 37 |
|
|
struct rtl_hooks rtl_hooks = RTL_HOOKS_INITIALIZER;
|
| 38 |
|
|
|
| 39 |
|
|
rtx
|
| 40 |
|
|
gen_lowpart_general (enum machine_mode mode, rtx x)
|
| 41 |
|
|
{
|
| 42 |
|
|
rtx result = gen_lowpart_common (mode, x);
|
| 43 |
|
|
|
| 44 |
|
|
if (result)
|
| 45 |
|
|
return result;
|
| 46 |
|
|
/* Handle SUBREGs and hard REGs that were rejected by
|
| 47 |
|
|
simplify_gen_subreg. */
|
| 48 |
|
|
else if (REG_P (x) || GET_CODE (x) == SUBREG)
|
| 49 |
|
|
{
|
| 50 |
|
|
result = gen_lowpart_common (mode, copy_to_reg (x));
|
| 51 |
|
|
gcc_assert (result != 0);
|
| 52 |
|
|
return result;
|
| 53 |
|
|
}
|
| 54 |
|
|
else
|
| 55 |
|
|
{
|
| 56 |
|
|
int offset = 0;
|
| 57 |
|
|
|
| 58 |
|
|
/* The only additional case we can do is MEM. */
|
| 59 |
|
|
gcc_assert (MEM_P (x));
|
| 60 |
|
|
|
| 61 |
|
|
/* The following exposes the use of "x" to CSE. */
|
| 62 |
|
|
if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
|
| 63 |
|
|
&& SCALAR_INT_MODE_P (GET_MODE (x))
|
| 64 |
|
|
&& TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x))
|
| 65 |
|
|
&& !reload_completed)
|
| 66 |
|
|
return gen_lowpart_general (mode, force_reg (GET_MODE (x), x));
|
| 67 |
|
|
|
| 68 |
|
|
if (WORDS_BIG_ENDIAN)
|
| 69 |
|
|
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
|
| 70 |
|
|
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
|
| 71 |
|
|
|
| 72 |
|
|
if (BYTES_BIG_ENDIAN)
|
| 73 |
|
|
/* Adjust the address so that the address-after-the-data
|
| 74 |
|
|
is unchanged. */
|
| 75 |
|
|
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
|
| 76 |
|
|
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
|
| 77 |
|
|
|
| 78 |
|
|
return adjust_address (x, mode, offset);
|
| 79 |
|
|
}
|
| 80 |
|
|
}
|
| 81 |
|
|
|
| 82 |
|
|
/* Similar to gen_lowpart, but cannot emit any instruction via
|
| 83 |
|
|
copy_to_reg or force_reg. Mainly used in simplify-rtx.c. */
|
| 84 |
|
|
rtx
|
| 85 |
|
|
gen_lowpart_no_emit_general (enum machine_mode mode, rtx x)
|
| 86 |
|
|
{
|
| 87 |
|
|
rtx result = gen_lowpart_if_possible (mode, x);
|
| 88 |
|
|
if (result)
|
| 89 |
|
|
return result;
|
| 90 |
|
|
else
|
| 91 |
|
|
return x;
|
| 92 |
|
|
}
|
| 93 |
|
|
|
| 94 |
|
|
rtx
|
| 95 |
|
|
reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED,
|
| 96 |
|
|
enum machine_mode mode ATTRIBUTE_UNUSED,
|
| 97 |
|
|
const_rtx known_x ATTRIBUTE_UNUSED,
|
| 98 |
|
|
enum machine_mode known_mode ATTRIBUTE_UNUSED,
|
| 99 |
|
|
unsigned int known_ret ATTRIBUTE_UNUSED,
|
| 100 |
|
|
unsigned int *result ATTRIBUTE_UNUSED)
|
| 101 |
|
|
{
|
| 102 |
|
|
return NULL;
|
| 103 |
|
|
}
|
| 104 |
|
|
|
| 105 |
|
|
rtx
|
| 106 |
|
|
reg_nonzero_bits_general (const_rtx x ATTRIBUTE_UNUSED,
|
| 107 |
|
|
enum machine_mode mode ATTRIBUTE_UNUSED,
|
| 108 |
|
|
const_rtx known_x ATTRIBUTE_UNUSED,
|
| 109 |
|
|
enum machine_mode known_mode ATTRIBUTE_UNUSED,
|
| 110 |
|
|
unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED,
|
| 111 |
|
|
unsigned HOST_WIDE_INT *nonzero ATTRIBUTE_UNUSED)
|
| 112 |
|
|
{
|
| 113 |
|
|
return NULL;
|
| 114 |
|
|
}
|
| 115 |
|
|
|
| 116 |
|
|
bool
|
| 117 |
|
|
reg_truncated_to_mode_general (enum machine_mode mode ATTRIBUTE_UNUSED,
|
| 118 |
|
|
const_rtx x ATTRIBUTE_UNUSED)
|
| 119 |
|
|
{
|
| 120 |
|
|
return false;
|
| 121 |
|
|
}
|
| 122 |
|
|
|
| 123 |
|
|
/* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point
|
| 124 |
|
|
number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the
|
| 125 |
|
|
least-significant part of X.
|
| 126 |
|
|
MODE specifies how big a part of X to return.
|
| 127 |
|
|
|
| 128 |
|
|
If the requested operation cannot be done, 0 is returned.
|
| 129 |
|
|
|
| 130 |
|
|
This is similar to gen_lowpart_general. */
|
| 131 |
|
|
|
| 132 |
|
|
rtx
|
| 133 |
|
|
gen_lowpart_if_possible (enum machine_mode mode, rtx x)
|
| 134 |
|
|
{
|
| 135 |
|
|
rtx result = gen_lowpart_common (mode, x);
|
| 136 |
|
|
|
| 137 |
|
|
if (result)
|
| 138 |
|
|
return result;
|
| 139 |
|
|
else if (MEM_P (x))
|
| 140 |
|
|
{
|
| 141 |
|
|
/* This is the only other case we handle. */
|
| 142 |
|
|
int offset = 0;
|
| 143 |
|
|
rtx new_rtx;
|
| 144 |
|
|
|
| 145 |
|
|
if (WORDS_BIG_ENDIAN)
|
| 146 |
|
|
offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD)
|
| 147 |
|
|
- MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD));
|
| 148 |
|
|
if (BYTES_BIG_ENDIAN)
|
| 149 |
|
|
/* Adjust the address so that the address-after-the-data is
|
| 150 |
|
|
unchanged. */
|
| 151 |
|
|
offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode))
|
| 152 |
|
|
- MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x))));
|
| 153 |
|
|
|
| 154 |
|
|
new_rtx = adjust_address_nv (x, mode, offset);
|
| 155 |
|
|
if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0),
|
| 156 |
|
|
MEM_ADDR_SPACE (x)))
|
| 157 |
|
|
return 0;
|
| 158 |
|
|
|
| 159 |
|
|
return new_rtx;
|
| 160 |
|
|
}
|
| 161 |
|
|
else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode
|
| 162 |
|
|
&& validate_subreg (mode, GET_MODE (x), x,
|
| 163 |
|
|
subreg_lowpart_offset (mode, GET_MODE (x))))
|
| 164 |
|
|
return gen_lowpart_SUBREG (mode, x);
|
| 165 |
|
|
else
|
| 166 |
|
|
return 0;
|
| 167 |
|
|
}
|
| 168 |
|
|
|