]>
Commit | Line | Data |
---|---|---|
bcaf571c | 1 | ;; Predicate definitions for LoongArch target. |
83ffe9cd | 2 | ;; Copyright (C) 2021-2023 Free Software Foundation, Inc. |
bcaf571c | 3 | ;; Contributed by Loongson Ltd. |
4 | ;; Based on MIPS target for GNU compiler. | |
5 | ;; | |
6 | ;; This file is part of GCC. | |
7 | ;; | |
8 | ;; GCC is free software; you can redistribute it and/or modify | |
9 | ;; it under the terms of the GNU General Public License as published by | |
10 | ;; the Free Software Foundation; either version 3, or (at your option) | |
11 | ;; any later version. | |
12 | ;; | |
13 | ;; GCC is distributed in the hope that it will be useful, | |
14 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | ;; GNU General Public License for more details. | |
17 | ;; | |
18 | ;; You should have received a copy of the GNU General Public License | |
19 | ;; along with GCC; see the file COPYING3. If not see | |
20 | ;; <http://www.gnu.org/licenses/>. | |
21 | ||
22 | (define_predicate "const_uns_arith_operand" | |
23 | (and (match_code "const_int") | |
24 | (match_test "IMM12_OPERAND_UNSIGNED (INTVAL (op))"))) | |
25 | ||
26 | (define_predicate "uns_arith_operand" | |
27 | (ior (match_operand 0 "const_uns_arith_operand") | |
28 | (match_operand 0 "register_operand"))) | |
29 | ||
30 | (define_predicate "const_lu32i_operand" | |
31 | (and (match_code "const_int") | |
32 | (match_test "LU32I_OPERAND (INTVAL (op))"))) | |
33 | ||
34 | (define_predicate "const_lu52i_operand" | |
35 | (and (match_code "const_int") | |
36 | (match_test "LU52I_OPERAND (INTVAL (op))"))) | |
37 | ||
38 | (define_predicate "const_arith_operand" | |
39 | (and (match_code "const_int") | |
40 | (match_test "IMM12_OPERAND (INTVAL (op))"))) | |
41 | ||
42 | (define_predicate "const_imm16_operand" | |
43 | (and (match_code "const_int") | |
44 | (match_test "IMM16_OPERAND (INTVAL (op))"))) | |
45 | ||
46 | (define_predicate "arith_operand" | |
47 | (ior (match_operand 0 "const_arith_operand") | |
48 | (match_operand 0 "register_operand"))) | |
49 | ||
50 | (define_predicate "const_immalsl_operand" | |
51 | (and (match_code "const_int") | |
52 | (match_test "IN_RANGE (INTVAL (op), 1, 4)"))) | |
53 | ||
54 | (define_predicate "const_uimm5_operand" | |
55 | (and (match_code "const_int") | |
56 | (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) | |
57 | ||
58 | (define_predicate "const_uimm14_operand" | |
59 | (and (match_code "const_int") | |
60 | (match_test "IN_RANGE (INTVAL (op), 0, 16383)"))) | |
61 | ||
62 | (define_predicate "const_uimm15_operand" | |
63 | (and (match_code "const_int") | |
64 | (match_test "IN_RANGE (INTVAL (op), 0, 32767)"))) | |
65 | ||
66 | (define_predicate "const_imm12_operand" | |
67 | (and (match_code "const_int") | |
68 | (match_test "IMM12_OPERAND (INTVAL (op))"))) | |
69 | ||
70 | (define_predicate "sle_operand" | |
71 | (and (match_code "const_int") | |
72 | (match_test "IMM12_OPERAND (INTVAL (op) + 1)"))) | |
73 | ||
74 | (define_predicate "sleu_operand" | |
75 | (and (match_operand 0 "sle_operand") | |
76 | (match_test "INTVAL (op) + 1 != 0"))) | |
77 | ||
78 | (define_predicate "const_0_operand" | |
79 | (and (match_code "const_int,const_double,const_vector") | |
80 | (match_test "op == CONST0_RTX (GET_MODE (op))"))) | |
81 | ||
82 | (define_predicate "reg_or_0_operand" | |
83 | (ior (match_operand 0 "const_0_operand") | |
84 | (match_operand 0 "register_operand"))) | |
85 | ||
86 | (define_predicate "const_1_operand" | |
87 | (and (match_code "const_int,const_double,const_vector") | |
88 | (match_test "op == CONST1_RTX (GET_MODE (op))"))) | |
89 | ||
90 | (define_predicate "reg_or_1_operand" | |
91 | (ior (match_operand 0 "const_1_operand") | |
92 | (match_operand 0 "register_operand"))) | |
93 | ||
94 | (define_predicate "const_0_to_3_operand" | |
95 | (and (match_code "const_int") | |
96 | (match_test "IN_RANGE (INTVAL (op), 0, 3)"))) | |
97 | ||
98 | (define_predicate "const_0_to_7_operand" | |
99 | (and (match_code "const_int") | |
100 | (match_test "IN_RANGE (INTVAL (op), 0, 7)"))) | |
101 | ||
102 | (define_predicate "lu52i_mask_operand" | |
103 | (and (match_code "const_int") | |
104 | (match_test "UINTVAL (op) == 0xfffffffffffff"))) | |
105 | ||
106 | (define_predicate "low_bitmask_operand" | |
107 | (and (match_code "const_int") | |
108 | (match_test "low_bitmask_len (mode, INTVAL (op)) > 12"))) | |
109 | ||
110 | (define_predicate "const_call_insn_operand" | |
111 | (match_code "const,symbol_ref,label_ref") | |
112 | { | |
16fc26d4 | 113 | /* Split symbol to high and low if return false. |
69458145 | 114 | If defined TARGET_CMODEL_EXTREME, all symbol would be splited, |
16fc26d4 LC |
115 | else if offset is not zero, the symbol would be splited. */ |
116 | ||
bcaf571c | 117 | enum loongarch_symbol_type symbol_type; |
d5e401fb | 118 | loongarch_symbolic_constant_p (op, &symbol_type); |
bcaf571c | 119 | |
d5e401fb LC |
120 | rtx offset, x = op; |
121 | split_const (x, &x, &offset); | |
122 | ||
123 | if (offset != const0_rtx) | |
bcaf571c | 124 | return false; |
125 | ||
d1028c57 LC |
126 | /* When compiling with '-mcmodel=medium -mexplicit-relocs' |
127 | symbols are splited in loongarch_legitimize_call_address. | |
128 | ||
129 | When compiling with '-mcmodel=medium -mno-explicit-relocs', | |
130 | first obtain the symbolic address or the address of the | |
131 | plt entry, and then perform an indirect jump, so return false. */ | |
132 | ||
bcaf571c | 133 | switch (symbol_type) |
134 | { | |
d5e401fb | 135 | case SYMBOL_PCREL: |
d1028c57 LC |
136 | if (TARGET_CMODEL_EXTREME |
137 | || (TARGET_CMODEL_MEDIUM && !TARGET_EXPLICIT_RELOCS)) | |
69458145 LC |
138 | return false; |
139 | else | |
140 | return 1; | |
bcaf571c | 141 | |
d5e401fb | 142 | case SYMBOL_GOT_DISP: |
d1028c57 LC |
143 | if (TARGET_CMODEL_EXTREME |
144 | || !flag_plt | |
145 | || (flag_plt && TARGET_CMODEL_MEDIUM | |
146 | && !TARGET_EXPLICIT_RELOCS)) | |
d5e401fb LC |
147 | return false; |
148 | else | |
149 | return 1; | |
150 | ||
bcaf571c | 151 | default: |
152 | return false; | |
153 | } | |
154 | }) | |
155 | ||
156 | (define_predicate "call_insn_operand" | |
157 | (ior (match_operand 0 "const_call_insn_operand") | |
158 | (match_operand 0 "register_operand"))) | |
159 | ||
160 | (define_predicate "is_const_call_local_symbol" | |
161 | (and (match_operand 0 "const_call_insn_operand") | |
162 | (ior (match_test "loongarch_global_symbol_p (op) == 0") | |
163 | (match_test "loongarch_symbol_binds_local_p (op) != 0")) | |
164 | (match_test "CONSTANT_P (op)"))) | |
165 | ||
d5e401fb | 166 | (define_predicate "is_const_call_no_local_symbol" |
bcaf571c | 167 | (and (match_operand 0 "const_call_insn_operand") |
d5e401fb LC |
168 | (ior (match_test "loongarch_global_symbol_p (op) != 0") |
169 | (match_test "loongarch_symbol_binds_local_p (op) == 0") | |
170 | (match_test "loongarch_weak_symbol_p (op) != 0")) | |
bcaf571c | 171 | (match_test "CONSTANT_P (op)"))) |
172 | ||
173 | ;; A legitimate CONST_INT operand that takes more than one instruction | |
174 | ;; to load. | |
175 | (define_predicate "splittable_const_int_operand" | |
176 | (match_code "const_int") | |
177 | { | |
178 | /* Don't handle multi-word moves this way; we don't want to introduce | |
179 | the individual word-mode moves until after reload. */ | |
180 | if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) | |
181 | return false; | |
182 | ||
183 | /* Otherwise check whether the constant can be loaded in a single | |
184 | instruction. */ | |
185 | return !LU12I_INT (op) && !IMM12_INT (op) && !IMM12_INT_UNSIGNED (op) | |
186 | && !LU52I_INT (op); | |
187 | }) | |
188 | ||
189 | (define_predicate "move_operand" | |
190 | (match_operand 0 "general_operand") | |
191 | { | |
192 | enum loongarch_symbol_type symbol_type; | |
193 | ||
194 | /* The thinking here is as follows: | |
195 | ||
196 | (1) The move expanders should split complex load sequences into | |
197 | individual instructions. Those individual instructions can | |
198 | then be optimized by all rtl passes. | |
199 | ||
200 | (2) The target of pre-reload load sequences should not be used | |
201 | to store temporary results. If the target register is only | |
202 | assigned one value, reload can rematerialize that value | |
203 | on demand, rather than spill it to the stack. | |
204 | ||
205 | (3) If we allowed pre-reload passes like combine and cse to recreate | |
206 | complex load sequences, we would want to be able to split the | |
207 | sequences before reload as well, so that the pre-reload scheduler | |
208 | can see the individual instructions. This falls foul of (2); | |
209 | the splitter would be forced to reuse the target register for | |
210 | intermediate results. | |
211 | ||
212 | (4) We want to define complex load splitters for combine. These | |
213 | splitters can request a temporary scratch register, which avoids | |
214 | the problem in (2). They allow things like: | |
215 | ||
216 | (set (reg T1) (high SYM)) | |
217 | (set (reg T2) (low (reg T1) SYM)) | |
218 | (set (reg X) (plus (reg T2) (const_int OFFSET))) | |
219 | ||
220 | to be combined into: | |
221 | ||
222 | (set (reg T3) (high SYM+OFFSET)) | |
223 | (set (reg X) (lo_sum (reg T3) SYM+OFFSET)) | |
224 | ||
225 | if T2 is only used this once. */ | |
226 | switch (GET_CODE (op)) | |
227 | { | |
228 | case CONST_INT: | |
be591d00 | 229 | return true; |
bcaf571c | 230 | |
231 | case CONST: | |
232 | case SYMBOL_REF: | |
233 | case LABEL_REF: | |
16fc26d4 LC |
234 | return (loongarch_symbolic_constant_p (op, &symbol_type) |
235 | && (!TARGET_EXPLICIT_RELOCS | |
236 | || !loongarch_split_symbol_type (symbol_type))); | |
237 | ||
238 | case HIGH: | |
239 | /* '-mno-explicit-relocs' don't generate high/low pairs. */ | |
240 | if (!TARGET_EXPLICIT_RELOCS) | |
241 | return false; | |
242 | ||
243 | op = XEXP (op, 0); | |
244 | return (loongarch_symbolic_constant_p (op, &symbol_type) | |
245 | && loongarch_split_symbol_type (symbol_type)); | |
246 | ||
bcaf571c | 247 | default: |
248 | return true; | |
249 | } | |
250 | }) | |
251 | ||
252 | (define_predicate "symbolic_operand" | |
253 | (match_code "const,symbol_ref,label_ref") | |
254 | { | |
255 | enum loongarch_symbol_type type; | |
256 | return loongarch_symbolic_constant_p (op, &type); | |
257 | }) | |
258 | ||
259 | (define_predicate "equality_operator" | |
260 | (match_code "eq,ne")) | |
261 | ||
262 | (define_predicate "order_operator" | |
263 | (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) | |
264 | ||
265 | ;; For NE, cstore uses sltu instructions in which the first operand is $0. | |
266 | ||
267 | (define_predicate "loongarch_cstore_operator" | |
268 | (match_code "ne,eq,gt,gtu,ge,geu,lt,ltu,le,leu")) | |
269 | ||
270 | (define_predicate "small_data_pattern" | |
271 | (and (match_code "set,parallel,unspec,unspec_volatile,prefetch") | |
272 | (match_test "loongarch_small_data_pattern_p (op)"))) | |
273 | ||
274 | ;; Return 1 if the operand is in non-volatile memory. | |
275 | (define_predicate "non_volatile_mem_operand" | |
276 | (and (match_operand 0 "memory_operand") | |
277 | (not (match_test "MEM_VOLATILE_P (op)")))) |