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