]>
Commit | Line | Data |
---|---|---|
09cae750 | 1 | ;; Predicate description for RISC-V target. |
a5544970 | 2 | ;; Copyright (C) 2011-2019 Free Software Foundation, Inc. |
09cae750 PD |
3 | ;; Contributed by Andrew Waterman (andrew@sifive.com). |
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_arith_operand" | |
23 | (and (match_code "const_int") | |
24 | (match_test "SMALL_OPERAND (INTVAL (op))"))) | |
25 | ||
26 | (define_predicate "arith_operand" | |
27 | (ior (match_operand 0 "const_arith_operand") | |
28 | (match_operand 0 "register_operand"))) | |
29 | ||
30 | (define_predicate "const_csr_operand" | |
31 | (and (match_code "const_int") | |
32 | (match_test "IN_RANGE (INTVAL (op), 0, 31)"))) | |
33 | ||
34 | (define_predicate "csr_operand" | |
35 | (ior (match_operand 0 "const_csr_operand") | |
36 | (match_operand 0 "register_operand"))) | |
37 | ||
38 | (define_predicate "sle_operand" | |
39 | (and (match_code "const_int") | |
40 | (match_test "SMALL_OPERAND (INTVAL (op) + 1)"))) | |
41 | ||
42 | (define_predicate "sleu_operand" | |
43 | (and (match_operand 0 "sle_operand") | |
44 | (match_test "INTVAL (op) + 1 != 0"))) | |
45 | ||
46 | (define_predicate "const_0_operand" | |
47 | (and (match_code "const_int,const_wide_int,const_double,const_vector") | |
48 | (match_test "op == CONST0_RTX (GET_MODE (op))"))) | |
49 | ||
50 | (define_predicate "reg_or_0_operand" | |
51 | (ior (match_operand 0 "const_0_operand") | |
52 | (match_operand 0 "register_operand"))) | |
53 | ||
54 | ;; Only use branch-on-bit sequences when the mask is not an ANDI immediate. | |
55 | (define_predicate "branch_on_bit_operand" | |
56 | (and (match_code "const_int") | |
57 | (match_test "INTVAL (op) >= IMM_BITS - 1"))) | |
58 | ||
59 | ;; A legitimate CONST_INT operand that takes more than one instruction | |
60 | ;; to load. | |
61 | (define_predicate "splittable_const_int_operand" | |
62 | (match_code "const_int") | |
63 | { | |
64 | /* Don't handle multi-word moves this way; we don't want to introduce | |
65 | the individual word-mode moves until after reload. */ | |
66 | if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) | |
67 | return false; | |
68 | ||
69 | /* Otherwise check whether the constant can be loaded in a single | |
70 | instruction. */ | |
71 | return !LUI_OPERAND (INTVAL (op)) && !SMALL_OPERAND (INTVAL (op)); | |
72 | }) | |
73 | ||
666fdc46 JW |
74 | (define_predicate "p2m1_shift_operand" |
75 | (match_code "const_int") | |
76 | { | |
77 | int val = exact_log2 (INTVAL (op) + 1); | |
78 | if (val < 12) | |
79 | return false; | |
80 | return true; | |
81 | }) | |
82 | ||
83 | (define_predicate "high_mask_shift_operand" | |
84 | (match_code "const_int") | |
85 | { | |
86 | int val1 = clz_hwi (~ INTVAL (op)); | |
87 | int val0 = ctz_hwi (INTVAL (op)); | |
88 | if ((val0 + val1 == BITS_PER_WORD) | |
89 | && val0 > 31 && val0 < 64) | |
90 | return true; | |
91 | return false; | |
92 | }) | |
93 | ||
09cae750 PD |
94 | (define_predicate "move_operand" |
95 | (match_operand 0 "general_operand") | |
96 | { | |
97 | enum riscv_symbol_type symbol_type; | |
98 | ||
99 | /* The thinking here is as follows: | |
100 | ||
101 | (1) The move expanders should split complex load sequences into | |
102 | individual instructions. Those individual instructions can | |
103 | then be optimized by all rtl passes. | |
104 | ||
105 | (2) The target of pre-reload load sequences should not be used | |
106 | to store temporary results. If the target register is only | |
107 | assigned one value, reload can rematerialize that value | |
108 | on demand, rather than spill it to the stack. | |
109 | ||
110 | (3) If we allowed pre-reload passes like combine and cse to recreate | |
111 | complex load sequences, we would want to be able to split the | |
112 | sequences before reload as well, so that the pre-reload scheduler | |
113 | can see the individual instructions. This falls foul of (2); | |
114 | the splitter would be forced to reuse the target register for | |
115 | intermediate results. | |
116 | ||
117 | (4) We want to define complex load splitters for combine. These | |
118 | splitters can request a temporary scratch register, which avoids | |
119 | the problem in (2). They allow things like: | |
120 | ||
121 | (set (reg T1) (high SYM)) | |
122 | (set (reg T2) (low (reg T1) SYM)) | |
123 | (set (reg X) (plus (reg T2) (const_int OFFSET))) | |
124 | ||
125 | to be combined into: | |
126 | ||
127 | (set (reg T3) (high SYM+OFFSET)) | |
128 | (set (reg X) (lo_sum (reg T3) SYM+OFFSET)) | |
129 | ||
130 | if T2 is only used this once. */ | |
131 | switch (GET_CODE (op)) | |
132 | { | |
133 | case CONST_INT: | |
134 | return !splittable_const_int_operand (op, mode); | |
135 | ||
136 | case CONST: | |
137 | case SYMBOL_REF: | |
138 | case LABEL_REF: | |
139 | return riscv_symbolic_constant_p (op, &symbol_type) | |
140 | && !riscv_split_symbol_type (symbol_type); | |
141 | ||
142 | case HIGH: | |
143 | op = XEXP (op, 0); | |
144 | return riscv_symbolic_constant_p (op, &symbol_type) | |
145 | && riscv_split_symbol_type (symbol_type) | |
146 | && symbol_type != SYMBOL_PCREL; | |
147 | ||
148 | default: | |
149 | return true; | |
150 | } | |
151 | }) | |
152 | ||
153 | (define_predicate "symbolic_operand" | |
154 | (match_code "const,symbol_ref,label_ref") | |
155 | { | |
156 | enum riscv_symbol_type type; | |
157 | return riscv_symbolic_constant_p (op, &type); | |
158 | }) | |
159 | ||
160 | (define_predicate "absolute_symbolic_operand" | |
161 | (match_code "const,symbol_ref,label_ref") | |
162 | { | |
163 | enum riscv_symbol_type type; | |
164 | return (riscv_symbolic_constant_p (op, &type) | |
165 | && (type == SYMBOL_ABSOLUTE || type == SYMBOL_PCREL)); | |
166 | }) | |
167 | ||
168 | (define_predicate "plt_symbolic_operand" | |
169 | (match_code "const,symbol_ref,label_ref") | |
170 | { | |
171 | enum riscv_symbol_type type; | |
172 | return (riscv_symbolic_constant_p (op, &type) | |
173 | && type == SYMBOL_GOT_DISP && !SYMBOL_REF_WEAK (op) && TARGET_PLT); | |
174 | }) | |
175 | ||
176 | (define_predicate "call_insn_operand" | |
177 | (ior (match_operand 0 "absolute_symbolic_operand") | |
178 | (match_operand 0 "plt_symbolic_operand") | |
179 | (match_operand 0 "register_operand"))) | |
180 | ||
181 | (define_predicate "modular_operator" | |
182 | (match_code "plus,minus,mult,ashift")) | |
183 | ||
184 | (define_predicate "equality_operator" | |
185 | (match_code "eq,ne")) | |
186 | ||
187 | (define_predicate "order_operator" | |
188 | (match_code "eq,ne,lt,ltu,le,leu,ge,geu,gt,gtu")) | |
189 | ||
190 | (define_predicate "signed_order_operator" | |
191 | (match_code "eq,ne,lt,le,ge,gt")) | |
192 | ||
193 | (define_predicate "fp_native_comparison" | |
194 | (match_code "eq,lt,le,gt,ge")) | |
195 | ||
196 | (define_predicate "fp_scc_comparison" | |
197 | (match_code "unordered,ordered,unlt,unge,unle,ungt,ltgt,ne,eq,lt,le,gt,ge")) | |
198 | ||
199 | (define_predicate "fp_branch_comparison" | |
200 | (match_code "unordered,ordered,unlt,unge,unle,ungt,uneq,ltgt,ne,eq,lt,le,gt,ge")) |