]>
Commit | Line | Data |
---|---|---|
2f93eea8 | 1 | /* Generic hooks for the RTL middle-end. |
99dee823 | 2 | Copyright (C) 2004-2021 Free Software Foundation, Inc. |
2f93eea8 PB |
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 | |
9dcd6f09 | 8 | Software Foundation; either version 3, or (at your option) any later |
2f93eea8 PB |
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 | |
9dcd6f09 NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. */ | |
2f93eea8 PB |
19 | |
20 | #include "config.h" | |
21 | #include "system.h" | |
22 | #include "coretypes.h" | |
23 | #include "tm.h" | |
957060b5 | 24 | #include "function.h" |
2f93eea8 | 25 | #include "rtl.h" |
c7131fb2 | 26 | #include "tree.h" |
957060b5 | 27 | #include "insn-config.h" |
4d0cdd0c | 28 | #include "memmodel.h" |
957060b5 AM |
29 | #include "emit-rtl.h" |
30 | #include "recog.h" | |
31 | #include "rtlhooks-def.h" | |
36566b39 | 32 | #include "explow.h" |
bb149ca2 | 33 | #include "target.h" |
2f93eea8 PB |
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 | |
ef4bddc2 | 46 | gen_lowpart_general (machine_mode mode, rtx x) |
2f93eea8 PB |
47 | { |
48 | rtx result = gen_lowpart_common (mode, x); | |
49 | ||
50 | if (result) | |
51 | return result; | |
18b526e8 RS |
52 | /* Handle SUBREGs and hard REGs that were rejected by |
53 | simplify_gen_subreg. */ | |
54 | else if (REG_P (x) || GET_CODE (x) == SUBREG) | |
2f93eea8 | 55 | { |
2f93eea8 | 56 | result = gen_lowpart_common (mode, copy_to_reg (x)); |
41374e13 | 57 | gcc_assert (result != 0); |
2f93eea8 PB |
58 | return result; |
59 | } | |
41374e13 | 60 | else |
2f93eea8 | 61 | { |
41374e13 NS |
62 | /* The only additional case we can do is MEM. */ |
63 | gcc_assert (MEM_P (x)); | |
64 | ||
2f93eea8 | 65 | /* The following exposes the use of "x" to CSE. */ |
b0567726 RS |
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) | |
ef4375b2 | 70 | && !reload_completed) |
b0567726 | 71 | return gen_lowpart_general (mode, force_reg (xmode, x)); |
2f93eea8 | 72 | |
91914e56 | 73 | poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x)); |
2f93eea8 PB |
74 | return adjust_address (x, mode, offset); |
75 | } | |
2f93eea8 PB |
76 | } |
77 | ||
78 | rtx | |
401581b6 RS |
79 | reg_num_sign_bit_copies_general (const_rtx, scalar_int_mode, scalar_int_mode, |
80 | unsigned int *) | |
2f93eea8 PB |
81 | { |
82 | return NULL; | |
83 | } | |
84 | ||
85 | rtx | |
401581b6 RS |
86 | reg_nonzero_bits_general (const_rtx, scalar_int_mode, scalar_int_mode, |
87 | unsigned HOST_WIDE_INT *) | |
2f93eea8 PB |
88 | { |
89 | return NULL; | |
90 | } | |
bf667275 | 91 | |
d3b72690 | 92 | bool |
ef4bddc2 | 93 | reg_truncated_to_mode_general (machine_mode mode ATTRIBUTE_UNUSED, |
fa233e34 | 94 | const_rtx x ATTRIBUTE_UNUSED) |
d3b72690 PB |
95 | { |
96 | return false; | |
97 | } | |
98 | ||
bf667275 PB |
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 | |
ef4bddc2 | 109 | gen_lowpart_if_possible (machine_mode mode, rtx x) |
bf667275 PB |
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. */ | |
91914e56 | 118 | poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x)); |
90f2b7e2 | 119 | rtx new_rtx = adjust_address_nv (x, mode, offset); |
09e881c9 BE |
120 | if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0), |
121 | MEM_ADDR_SPACE (x))) | |
bf667275 PB |
122 | return 0; |
123 | ||
55d796da | 124 | return new_rtx; |
bf667275 | 125 | } |
50ffe7ad | 126 | else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode && !SUBREG_P (x) |
e4950e42 | 127 | && validate_subreg (mode, GET_MODE (x), x, |
50ffe7ad | 128 | subreg_lowpart_offset (mode, GET_MODE (x)))) |
bf667275 PB |
129 | return gen_lowpart_SUBREG (mode, x); |
130 | else | |
131 | return 0; | |
132 | } | |
133 | \f |