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