Branch data Line data Source code
1 : : /* Generic hooks for the RTL middle-end.
2 : : Copyright (C) 2004-2025 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 "function.h"
25 : : #include "rtl.h"
26 : : #include "tree.h"
27 : : #include "insn-config.h"
28 : : #include "memmodel.h"
29 : : #include "emit-rtl.h"
30 : : #include "recog.h"
31 : : #include "rtlhooks-def.h"
32 : : #include "explow.h"
33 : : #include "target.h"
34 : :
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
46 : 4633004 : gen_lowpart_general (machine_mode mode, rtx x)
47 : : {
48 : 4661767 : rtx result = gen_lowpart_common (mode, x);
49 : :
50 : 4661767 : if (result)
51 : : return result;
52 : : /* Handle SUBREGs and hard REGs that were rejected by
53 : : simplify_gen_subreg. */
54 : 98894 : else if (REG_P (x) || GET_CODE (x) == SUBREG)
55 : : {
56 : 55 : result = gen_lowpart_common (mode, copy_to_reg (x));
57 : 55 : gcc_assert (result != 0);
58 : : return result;
59 : : }
60 : : else
61 : : {
62 : : /* The only additional case we can do is MEM. */
63 : 98839 : gcc_assert (MEM_P (x));
64 : :
65 : : /* The following exposes the use of "x" to CSE. */
66 : 98839 : scalar_int_mode xmode;
67 : 98839 : if (is_a <scalar_int_mode> (GET_MODE (x), &xmode)
68 : 43281 : && GET_MODE_SIZE (xmode) <= UNITS_PER_WORD
69 : 34829 : && TRULY_NOOP_TRUNCATION_MODES_P (mode, xmode)
70 : 34829 : && !reload_completed)
71 : 28763 : return gen_lowpart_general (mode, force_reg (xmode, x));
72 : :
73 : 70076 : poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x));
74 : 70076 : return adjust_address (x, mode, offset);
75 : : }
76 : : }
77 : :
78 : : rtx
79 : 28493939 : reg_num_sign_bit_copies_general (const_rtx, scalar_int_mode, scalar_int_mode,
80 : : unsigned int *)
81 : : {
82 : 28493939 : return NULL;
83 : : }
84 : :
85 : : rtx
86 : 70419416 : reg_nonzero_bits_general (const_rtx, scalar_int_mode, scalar_int_mode,
87 : : unsigned HOST_WIDE_INT *)
88 : : {
89 : 70419416 : return NULL;
90 : : }
91 : :
92 : : bool
93 : 0 : reg_truncated_to_mode_general (machine_mode mode ATTRIBUTE_UNUSED,
94 : : const_rtx x ATTRIBUTE_UNUSED)
95 : : {
96 : 0 : return false;
97 : : }
98 : :
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
109 : 23625443 : gen_lowpart_if_possible (machine_mode mode, rtx x)
110 : : {
111 : 23625443 : rtx result = gen_lowpart_common (mode, x);
112 : :
113 : 23625443 : if (result)
114 : : return result;
115 : 37128 : else if (MEM_P (x))
116 : : {
117 : : /* This is the only other case we handle. */
118 : 5740 : poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x));
119 : 5740 : rtx new_rtx = adjust_address_nv (x, mode, offset);
120 : 11480 : if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0),
121 : 5740 : MEM_ADDR_SPACE (x)))
122 : : return 0;
123 : :
124 : 5362 : return new_rtx;
125 : : }
126 : 31388 : else if (mode != GET_MODE (x) && GET_MODE (x) != VOIDmode && !SUBREG_P (x)
127 : 62431 : && validate_subreg (mode, GET_MODE (x), x,
128 : : subreg_lowpart_offset (mode, GET_MODE (x))))
129 : 30521 : return gen_lowpart_SUBREG (mode, x);
130 : : else
131 : 867 : return 0;
132 : : }
133 : :
|