]>
Commit | Line | Data |
---|---|---|
d263732c | 1 | /* Generic hooks for the RTL middle-end. |
8e8f6434 | 2 | Copyright (C) 2004-2018 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" |
ad7b10a2 | 28 | #include "memmodel.h" |
7c29e30e | 29 | #include "emit-rtl.h" |
30 | #include "recog.h" | |
31 | #include "rtlhooks-def.h" | |
d53441c8 | 32 | #include "explow.h" |
050dd610 | 33 | #include "target.h" |
d263732c | 34 | \f |
35 | ||
36 | /* For speed, we will copy the RTX hooks struct member-by-member | |
37 | instead of doing indirect calls. For these reason, we initialize | |
38 | *two* struct rtl_hooks globals: rtl_hooks is the one that is used | |
39 | to actually call the hooks, while general_rtl_hooks is used | |
40 | to restore the hooks by passes that modify them. */ | |
41 | ||
42 | const struct rtl_hooks general_rtl_hooks = RTL_HOOKS_INITIALIZER; | |
43 | struct rtl_hooks rtl_hooks = RTL_HOOKS_INITIALIZER; | |
44 | ||
45 | rtx | |
3754d046 | 46 | gen_lowpart_general (machine_mode mode, rtx x) |
d263732c | 47 | { |
48 | rtx result = gen_lowpart_common (mode, x); | |
49 | ||
50 | if (result) | |
51 | return result; | |
10d4de0e | 52 | /* Handle SUBREGs and hard REGs that were rejected by |
53 | simplify_gen_subreg. */ | |
54 | else if (REG_P (x) || GET_CODE (x) == SUBREG) | |
d263732c | 55 | { |
d263732c | 56 | result = gen_lowpart_common (mode, copy_to_reg (x)); |
04e579b6 | 57 | gcc_assert (result != 0); |
d263732c | 58 | return result; |
59 | } | |
04e579b6 | 60 | else |
d263732c | 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. */ |
8974b7a3 | 66 | scalar_int_mode xmode; |
67 | if (is_a <scalar_int_mode> (GET_MODE (x), &xmode) | |
68 | && GET_MODE_SIZE (xmode) <= UNITS_PER_WORD | |
69 | && TRULY_NOOP_TRUNCATION_MODES_P (mode, xmode) | |
4629257b | 70 | && !reload_completed) |
8974b7a3 | 71 | return gen_lowpart_general (mode, force_reg (xmode, x)); |
d263732c | 72 | |
9edf7ea8 | 73 | poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x)); |
d263732c | 74 | return adjust_address (x, mode, offset); |
75 | } | |
d263732c | 76 | } |
77 | ||
78 | rtx | |
652e50b4 | 79 | reg_num_sign_bit_copies_general (const_rtx, scalar_int_mode, scalar_int_mode, |
80 | unsigned int *) | |
d263732c | 81 | { |
82 | return NULL; | |
83 | } | |
84 | ||
85 | rtx | |
652e50b4 | 86 | reg_nonzero_bits_general (const_rtx, scalar_int_mode, scalar_int_mode, |
87 | unsigned HOST_WIDE_INT *) | |
d263732c | 88 | { |
89 | return NULL; | |
90 | } | |
f4a8fff4 | 91 | |
fd95fba4 | 92 | bool |
3754d046 | 93 | reg_truncated_to_mode_general (machine_mode mode ATTRIBUTE_UNUSED, |
b7bf20db | 94 | const_rtx x ATTRIBUTE_UNUSED) |
fd95fba4 | 95 | { |
96 | return false; | |
97 | } | |
98 | ||
f4a8fff4 | 99 | /* Assuming that X is an rtx (e.g., MEM, REG or SUBREG) for a fixed-point |
100 | number, return an rtx (MEM, SUBREG, or CONST_INT) that refers to the | |
101 | least-significant part of X. | |
102 | MODE specifies how big a part of X to return. | |
103 | ||
104 | If the requested operation cannot be done, 0 is returned. | |
105 | ||
106 | This is similar to gen_lowpart_general. */ | |
107 | ||
108 | rtx | |
3754d046 | 109 | gen_lowpart_if_possible (machine_mode mode, rtx x) |
f4a8fff4 | 110 | { |
111 | rtx result = gen_lowpart_common (mode, x); | |
112 | ||
113 | if (result) | |
114 | return result; | |
115 | else if (MEM_P (x)) | |
116 | { | |
117 | /* This is the only other case we handle. */ | |
9edf7ea8 | 118 | poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x)); |
c04949fe | 119 | rtx new_rtx = adjust_address_nv (x, mode, offset); |
bd1a81f7 | 120 | if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0), |
121 | MEM_ADDR_SPACE (x))) | |
f4a8fff4 | 122 | return 0; |
123 | ||
47cfb7f4 | 124 | return new_rtx; |
f4a8fff4 | 125 | } |
99c73432 | 126 | else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode && !SUBREG_P (x) |
ed7dbf5d | 127 | && validate_subreg (mode, GET_MODE (x), x, |
99c73432 | 128 | subreg_lowpart_offset (mode, GET_MODE (x)))) |
f4a8fff4 | 129 | return gen_lowpart_SUBREG (mode, x); |
130 | else | |
131 | return 0; | |
132 | } | |
133 | \f |