]>
Commit | Line | Data |
---|---|---|
d263732c | 1 | /* Generic hooks for the RTL middle-end. |
d353bf18 | 2 | Copyright (C) 2004-2015 Free Software Foundation, Inc. |
d263732c | 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 | |
8c4c00c1 | 8 | Software Foundation; either version 3, or (at your option) any later |
d263732c | 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 | |
8c4c00c1 | 17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
d263732c | 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" | |
b20a8bb4 | 26 | #include "symtab.h" |
d53441c8 | 27 | #include "hard-reg-set.h" |
d53441c8 | 28 | #include "function.h" |
29 | #include "flags.h" | |
d53441c8 | 30 | #include "alias.h" |
d53441c8 | 31 | #include "tree.h" |
32 | #include "insn-config.h" | |
33 | #include "expmed.h" | |
34 | #include "dojump.h" | |
35 | #include "explow.h" | |
36 | #include "calls.h" | |
37 | #include "emit-rtl.h" | |
38 | #include "varasm.h" | |
39 | #include "stmt.h" | |
d263732c | 40 | #include "expr.h" |
f4a8fff4 | 41 | #include "recog.h" |
d263732c | 42 | \f |
43 | ||
44 | /* For speed, we will copy the RTX hooks struct member-by-member | |
45 | instead of doing indirect calls. For these reason, we initialize | |
46 | *two* struct rtl_hooks globals: rtl_hooks is the one that is used | |
47 | to actually call the hooks, while general_rtl_hooks is used | |
48 | to restore the hooks by passes that modify them. */ | |
49 | ||
50 | const struct rtl_hooks general_rtl_hooks = RTL_HOOKS_INITIALIZER; | |
51 | struct rtl_hooks rtl_hooks = RTL_HOOKS_INITIALIZER; | |
52 | ||
53 | rtx | |
3754d046 | 54 | gen_lowpart_general (machine_mode mode, rtx x) |
d263732c | 55 | { |
56 | rtx result = gen_lowpart_common (mode, x); | |
57 | ||
58 | if (result) | |
59 | return result; | |
10d4de0e | 60 | /* Handle SUBREGs and hard REGs that were rejected by |
61 | simplify_gen_subreg. */ | |
62 | else if (REG_P (x) || GET_CODE (x) == SUBREG) | |
d263732c | 63 | { |
d263732c | 64 | result = gen_lowpart_common (mode, copy_to_reg (x)); |
04e579b6 | 65 | gcc_assert (result != 0); |
d263732c | 66 | return result; |
67 | } | |
04e579b6 | 68 | else |
d263732c | 69 | { |
d263732c | 70 | int offset = 0; |
71 | ||
04e579b6 | 72 | /* The only additional case we can do is MEM. */ |
73 | gcc_assert (MEM_P (x)); | |
74 | ||
d263732c | 75 | /* The following exposes the use of "x" to CSE. */ |
76 | if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD | |
77 | && SCALAR_INT_MODE_P (GET_MODE (x)) | |
396f2130 | 78 | && TRULY_NOOP_TRUNCATION_MODES_P (mode, GET_MODE (x)) |
4629257b | 79 | && !reload_completed) |
d263732c | 80 | return gen_lowpart_general (mode, force_reg (GET_MODE (x), x)); |
81 | ||
82 | if (WORDS_BIG_ENDIAN) | |
83 | offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) | |
84 | - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); | |
85 | ||
86 | if (BYTES_BIG_ENDIAN) | |
87 | /* Adjust the address so that the address-after-the-data | |
88 | is unchanged. */ | |
89 | offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) | |
90 | - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); | |
91 | ||
92 | return adjust_address (x, mode, offset); | |
93 | } | |
d263732c | 94 | } |
95 | ||
96 | rtx | |
b7bf20db | 97 | reg_num_sign_bit_copies_general (const_rtx x ATTRIBUTE_UNUSED, |
3754d046 | 98 | machine_mode mode ATTRIBUTE_UNUSED, |
b7bf20db | 99 | const_rtx known_x ATTRIBUTE_UNUSED, |
3754d046 | 100 | machine_mode known_mode ATTRIBUTE_UNUSED, |
d263732c | 101 | unsigned int known_ret ATTRIBUTE_UNUSED, |
102 | unsigned int *result ATTRIBUTE_UNUSED) | |
103 | { | |
104 | return NULL; | |
105 | } | |
106 | ||
107 | rtx | |
b7bf20db | 108 | reg_nonzero_bits_general (const_rtx x ATTRIBUTE_UNUSED, |
3754d046 | 109 | machine_mode mode ATTRIBUTE_UNUSED, |
b7bf20db | 110 | const_rtx known_x ATTRIBUTE_UNUSED, |
3754d046 | 111 | machine_mode known_mode ATTRIBUTE_UNUSED, |
d263732c | 112 | unsigned HOST_WIDE_INT known_ret ATTRIBUTE_UNUSED, |
113 | unsigned HOST_WIDE_INT *nonzero ATTRIBUTE_UNUSED) | |
114 | { | |
115 | return NULL; | |
116 | } | |
f4a8fff4 | 117 | |
fd95fba4 | 118 | bool |
3754d046 | 119 | reg_truncated_to_mode_general (machine_mode mode ATTRIBUTE_UNUSED, |
b7bf20db | 120 | const_rtx x ATTRIBUTE_UNUSED) |
fd95fba4 | 121 | { |
122 | return false; | |
123 | } | |
124 | ||
f4a8fff4 | 125 | /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point |
126 | number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the | |
127 | least-significant part of X. | |
128 | MODE specifies how big a part of X to return. | |
129 | ||
130 | If the requested operation cannot be done, 0 is returned. | |
131 | ||
132 | This is similar to gen_lowpart_general. */ | |
133 | ||
134 | rtx | |
3754d046 | 135 | gen_lowpart_if_possible (machine_mode mode, rtx x) |
f4a8fff4 | 136 | { |
137 | rtx result = gen_lowpart_common (mode, x); | |
138 | ||
139 | if (result) | |
140 | return result; | |
141 | else if (MEM_P (x)) | |
142 | { | |
143 | /* This is the only other case we handle. */ | |
144 | int offset = 0; | |
47cfb7f4 | 145 | rtx new_rtx; |
f4a8fff4 | 146 | |
147 | if (WORDS_BIG_ENDIAN) | |
148 | offset = (MAX (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD) | |
149 | - MAX (GET_MODE_SIZE (mode), UNITS_PER_WORD)); | |
150 | if (BYTES_BIG_ENDIAN) | |
151 | /* Adjust the address so that the address-after-the-data is | |
152 | unchanged. */ | |
153 | offset -= (MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)) | |
154 | - MIN (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))); | |
155 | ||
47cfb7f4 | 156 | new_rtx = adjust_address_nv (x, mode, offset); |
bd1a81f7 | 157 | if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0), |
158 | MEM_ADDR_SPACE (x))) | |
f4a8fff4 | 159 | return 0; |
160 | ||
47cfb7f4 | 161 | return new_rtx; |
f4a8fff4 | 162 | } |
ed7dbf5d | 163 | else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode |
164 | && validate_subreg (mode, GET_MODE (x), x, | |
165 | subreg_lowpart_offset (mode, GET_MODE (x)))) | |
f4a8fff4 | 166 | return gen_lowpart_SUBREG (mode, x); |
167 | else | |
168 | return 0; | |
169 | } | |
170 | \f |