Skip to content

Commit 246613e

Browse files
committed
arcv: apex: Use recog-based selection of variants via mode iterators.
GCC selects the "define_expand" based on the operand layout of the function declaration. Since the declaration may use different orders or types of operands, we take full advantage of GCC’s internal instruction recognizer to match RTL expressions with the correct pattern in the machine description. During the "define_expand", the compiler generates a generic RTL using an "UNSPEC" code to uniquely identify a family of custom instructions along with their operands. At this stage, it's not yet a real instruction — it's an abstract placeholder tagged with a unique "UNSPEC" code. Later, during instruction selection, GCC calls "recog", which matches this RTL expression to the appropriate "define_insn" based on: - The "UNSPEC" code (acts as a unique identifier); - Operand modes (e.g., "SI", `DI`, etc.); - Operand predicates and constraints. If all conditions match, GCC selects the correct "define_insn", and code generation proceeds accordingly. To cover all valid combinations of operand types, the "define_insn" uses mode iterators (like "DM", "S0M", "S1M"), allowing it to generate all required mode variants from a single pattern template. Signed-off-by: Luis Silva <[email protected]>
1 parent dbd117a commit 246613e

File tree

2 files changed

+208
-34
lines changed

2 files changed

+208
-34
lines changed

gcc/config/riscv/arcv-apex.md

Lines changed: 202 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
UNSPEC_ARCV_APEX_VOID_SRC0_V
2525
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V
2626
UNSPEC_ARCV_APEX_DEST
27+
UNSPEC_ARCV_APEX_DEST_V
2728
UNSPEC_ARCV_APEX_DEST_SRC0
29+
UNSPEC_ARCV_APEX_DEST_SRC0_V
2830
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1
31+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V
2932
])
3033

3134
;; Used by "XD" insn. format: `insn`
@@ -41,9 +44,9 @@
4144
)
4245

4346
;; Used by "XI","XD" insn. format: `insn src0`
44-
(define_insn "riscv_arcv_apex_void_ftype_src0"
45-
[(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXI,xAVpXD")
46-
(match_operand:SI 1 "nonmemory_operand" "I,r")]
47+
(define_insn "riscv_arcv_apex_void_ftype_<S0M:mode>"
48+
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXI,xAVpXD")
49+
(match_operand:S0M 1 "nonmemory_operand" "I,r")]
4750
UNSPEC_ARCV_APEX_VOID_SRC0_V)]
4851
""
4952
{
@@ -65,11 +68,30 @@
6568
[(set_attr "type" "arith,arith")]
6669
)
6770

71+
(define_expand "riscv_arcv_apex_void_ftype_src0_v"
72+
[(unspec_volatile [(match_operand:SI 0 "const_int_operand")
73+
(match_operand 1 "nonmemory_operand")]
74+
UNSPEC_ARCV_APEX_VOID_SRC0_V)]
75+
""
76+
{
77+
/* Build the SET exactly as it appears above, but with the
78+
real RTX objects. Every operand already carries its mode,
79+
so nothing needs to be guessed. The UNSPEC code is
80+
essential as it tags this RTL with a unique ID, so the
81+
recognizer can match it to the correct mode-specific
82+
define_insn. */
83+
emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
84+
gen_rtvec (2, operands[0],
85+
operands[1]),
86+
UNSPEC_ARCV_APEX_VOID_SRC0_V));
87+
DONE;
88+
})
89+
6890
;; Used by "XS","XD" insn. format: `insn src0, src1`
69-
(define_insn "riscv_arcv_apex_void_ftype_src0_src1"
70-
[(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXS,xAVpXD")
71-
(match_operand:SI 1 "register_operand" "r,r")
72-
(match_operand:SI 2 "nonmemory_operand" "B8,r")]
91+
(define_insn "riscv_arcv_apex_void_ftype_<S0M:mode>_<S1M:mode>_v"
92+
[(unspec_volatile [(match_operand:SI 0 "const_int_operand" "xAVpXS,xAVpXD")
93+
(match_operand:S0M 1 "register_operand" "r,r")
94+
(match_operand:S1M 2 "nonmemory_operand" "B8,r")]
7395
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
7496
""
7597
{
@@ -93,11 +115,32 @@
93115
[(set_attr "type" "arith,arith")]
94116
)
95117

118+
(define_expand "riscv_arcv_apex_void_ftype_src0_src1_v"
119+
[(unspec_volatile [(match_operand:SI 0 "const_int_operand")
120+
(match_operand 1 "register_operand")
121+
(match_operand 2 "nonmemory_operand")]
122+
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
123+
""
124+
{
125+
/* Build the SET exactly as it appears above, but with the
126+
real RTX objects. Every operand already carries its mode,
127+
so nothing needs to be guessed. The UNSPEC code is
128+
essential as it tags this RTL with a unique ID, so the
129+
recognizer can match it to the correct mode-specific
130+
define_insn. */
131+
emit_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
132+
gen_rtvec (3, operands[0],
133+
operands[1],
134+
operands[2]),
135+
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V));
136+
DONE;
137+
})
138+
96139
;; Used by "XD" insn. format: `insn dest` volatile
97-
(define_insn "riscv_arcv_apex_dest_volatile"
98-
[(set (match_operand:SI 0 "register_operand" "=r")
99-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
100-
UNSPEC_ARCV_APEX_DEST))]
140+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype_v"
141+
[(set (match_operand:DM 0 "register_operand" "=r")
142+
(unspec_volatile:DM [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
143+
UNSPEC_ARCV_APEX_DEST_V))]
101144
""
102145
{
103146
const char *str = arcv_apex_get_insn_name (operands[1]);
@@ -108,10 +151,29 @@
108151
[(set_attr "type" "arith")]
109152
)
110153

154+
(define_expand "riscv_arcv_apex_dest_ftype_v"
155+
[(set (match_operand 0 "register_operand")
156+
(unspec [(match_operand:SI 1 "const_int_operand")]
157+
UNSPEC_ARCV_APEX_DEST_V))]
158+
""
159+
{
160+
/* Build the SET exactly as it appears above, but with the
161+
real RTX objects. Every operand already carries its mode,
162+
so nothing needs to be guessed. The UNSPEC code is
163+
essential as it tags this RTL with a unique ID, so the
164+
recognizer can match it to the correct mode-specific
165+
define_insn. */
166+
emit_insn (gen_rtx_SET (operands[0],
167+
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
168+
gen_rtvec (1, operands[1]),
169+
UNSPEC_ARCV_APEX_DEST_V)));
170+
DONE;
171+
})
172+
111173
;; Used by "XD" insn. format: `insn dest`
112-
(define_insn "riscv_arcv_apex_dest_ftype"
113-
[(set (match_operand:SI 0 "register_operand" "=r")
114-
(unspec:SI [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
174+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype"
175+
[(set (match_operand:DM 0 "register_operand" "=r")
176+
(unspec:DM [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
115177
UNSPEC_ARCV_APEX_DEST))]
116178
""
117179
{
@@ -123,12 +185,31 @@
123185
[(set_attr "type" "arith")]
124186
)
125187

188+
(define_expand "riscv_arcv_apex_dest_ftype"
189+
[(set (match_operand 0 "register_operand")
190+
(unspec [(match_operand:SI 1 "const_int_operand")]
191+
UNSPEC_ARCV_APEX_DEST))]
192+
""
193+
{
194+
/* Build the SET exactly as it appears above, but with the
195+
real RTX objects. Every operand already carries its mode,
196+
so nothing needs to be guessed. The UNSPEC code is
197+
essential as it tags this RTL with a unique ID, so the
198+
recognizer can match it to the correct mode-specific
199+
define_insn. */
200+
emit_insn (gen_rtx_SET (operands[0],
201+
gen_rtx_UNSPEC (GET_MODE (operands[0]),
202+
gen_rtvec (1, operands[1]),
203+
UNSPEC_ARCV_APEX_DEST)));
204+
DONE;
205+
})
206+
126207
;; Used by "XI","XD" insn. format: `insn dest, src0` volatile
127-
(define_insn "riscv_arcv_apex_dest_src0_volatile"
128-
[(set (match_operand:SI 0 "register_operand" "=r,r")
129-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
130-
(match_operand:SI 2 "nonmemory_operand" "I,r")]
131-
UNSPEC_ARCV_APEX_DEST_SRC0))]
208+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype_<S0M:mode>_v"
209+
[(set (match_operand:DM 0 "register_operand" "=r,r")
210+
(unspec_volatile:DM [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
211+
(match_operand:S0M 2 "nonmemory_operand" "I,r")]
212+
UNSPEC_ARCV_APEX_DEST_SRC0_V))]
132213
""
133214
{
134215
const char *str = arcv_apex_get_insn_name (operands[1]);
@@ -151,11 +232,32 @@
151232
[(set_attr "type" "arith,arith")]
152233
)
153234

235+
(define_expand "riscv_arcv_apex_dest_ftype_src0_v"
236+
[(set (match_operand 0 "register_operand")
237+
(unspec_volatile [(match_operand:SI 1 "const_int_operand")
238+
(match_operand 2 "nonmemory_operand")]
239+
UNSPEC_ARCV_APEX_DEST_SRC0_V))]
240+
""
241+
{
242+
/* Build the SET exactly as it appears above, but with the
243+
real RTX objects. Every operand already carries its mode,
244+
so nothing needs to be guessed. The UNSPEC code is
245+
essential as it tags this RTL with a unique ID, so the
246+
recognizer can match it to the correct mode-specific
247+
define_insn. */
248+
emit_insn (gen_rtx_SET (operands[0],
249+
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
250+
gen_rtvec (2, operands[1],
251+
operands[2]),
252+
UNSPEC_ARCV_APEX_DEST_SRC0_V)));
253+
DONE;
254+
})
255+
154256
;; Used by "XI","XD" insn. format: `insn dest, src0`
155-
(define_insn "riscv_arcv_apex_dest_ftype_src0"
156-
[(set (match_operand:SI 0 "register_operand" "=r,r")
157-
(unspec:SI [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
158-
(match_operand:SI 2 "nonmemory_operand" "I,r")]
257+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype_<S0M:mode>"
258+
[(set (match_operand:DM 0 "register_operand" "=r,r")
259+
(unspec:DM [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
260+
(match_operand:S0M 2 "nonmemory_operand" "I,r")]
159261
UNSPEC_ARCV_APEX_DEST_SRC0))]
160262
""
161263
{
@@ -179,13 +281,34 @@
179281
[(set_attr "type" "arith,arith")]
180282
)
181283

284+
(define_expand "riscv_arcv_apex_dest_ftype_src0"
285+
[(set (match_operand 0 "register_operand")
286+
(unspec [(match_operand:SI 1 "const_int_operand")
287+
(match_operand 2 "nonmemory_operand")]
288+
UNSPEC_ARCV_APEX_DEST_SRC0))]
289+
""
290+
{
291+
/* Build the SET exactly as it appears above, but with the
292+
real RTX objects. Every operand already carries its mode,
293+
so nothing needs to be guessed. The UNSPEC code is
294+
essential as it tags this RTL with a unique ID, so the
295+
recognizer can match it to the correct mode-specific
296+
define_insn. */
297+
emit_insn (gen_rtx_SET (operands[0],
298+
gen_rtx_UNSPEC (GET_MODE (operands[0]),
299+
gen_rtvec (2, operands[1],
300+
operands[2]),
301+
UNSPEC_ARCV_APEX_DEST_SRC0)));
302+
DONE;
303+
})
304+
182305
;; Used by "XS","XC","XD" insn. format: `insn dest, src0, imm/src1` volatile
183-
(define_insn "riscv_arcv_apex_dest_src0_src1_volatile"
184-
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
185-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
186-
(match_operand:SI 2 "register_operand" "r,0,r")
187-
(match_operand:SI 3 "nonmemory_operand" "B8,I,r")]
188-
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
306+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype_<S0M:mode>_<S1M:mode>_v"
307+
[(set (match_operand:DM 0 "register_operand" "=r,r,r")
308+
(unspec_volatile:DM [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
309+
(match_operand:S0M 2 "register_operand" "r,0,r")
310+
(match_operand:S1M 3 "nonmemory_operand" "B8,I,r")]
311+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
189312
""
190313
{
191314
const char *str = arcv_apex_get_insn_name (operands[1]);
@@ -216,12 +339,35 @@
216339
[(set_attr "type" "arith,arith,arith")]
217340
)
218341

342+
(define_expand "riscv_arcv_apex_dest_ftype_src0_src1_v"
343+
[(set (match_operand 0 "register_operand")
344+
(unspec [(match_operand:SI 1 "const_int_operand")
345+
(match_operand 2 "register_operand")
346+
(match_operand 3 "nonmemory_operand")]
347+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
348+
""
349+
{
350+
/* Build the SET exactly as it appears above, but with the
351+
real RTX objects. Every operand already carries its mode,
352+
so nothing needs to be guessed. The UNSPEC code is
353+
essential as it tags this RTL with a unique ID, so the
354+
recognizer can match it to the correct mode-specific
355+
define_insn. */
356+
emit_insn (gen_rtx_SET (operands[0],
357+
gen_rtx_UNSPEC_VOLATILE (GET_MODE (operands[0]),
358+
gen_rtvec (3, operands[1],
359+
operands[2],
360+
operands[3]),
361+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V)));
362+
DONE;
363+
})
364+
219365
;; Used by "XS","XC","XD" insn. format: `insn dest, src0, imm/src1`
220-
(define_insn "riscv_arcv_apex_dest_ftype_src0_src1"
221-
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
222-
(unspec:SI [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
223-
(match_operand:SI 2 "register_operand" "r,0,r")
224-
(match_operand:SI 3 "nonmemory_operand" "B8,I,r")]
366+
(define_insn "riscv_arcv_apex_<DM:mode>_ftype_<S0M:mode>_<S1M:mode>"
367+
[(set (match_operand:DM 0 "register_operand" "=r,r,r")
368+
(unspec:DM [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
369+
(match_operand:S0M 2 "register_operand" "r,0,r")
370+
(match_operand:S1M 3 "nonmemory_operand" "B8,I,r")]
225371
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
226372
""
227373
{
@@ -253,3 +399,25 @@
253399
[(set_attr "type" "arith,arith,arith")]
254400
)
255401

402+
(define_expand "riscv_arcv_apex_dest_ftype_src0_src1"
403+
[(set (match_operand 0 "register_operand")
404+
(unspec [(match_operand:SI 1 "const_int_operand")
405+
(match_operand 2 "register_operand")
406+
(match_operand 3 "nonmemory_operand")]
407+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
408+
""
409+
{
410+
/* Build the SET exactly as it appears above, but with the
411+
real RTX objects. Every operand already carries its mode,
412+
so nothing needs to be guessed. The UNSPEC code is
413+
essential as it tags this RTL with a unique ID, so the
414+
recognizer can match it to the correct mode-specific
415+
define_insn. */
416+
emit_insn (gen_rtx_SET (operands[0],
417+
gen_rtx_UNSPEC (GET_MODE (operands[0]),
418+
gen_rtvec (3, operands[1],
419+
operands[2],
420+
operands[3]),
421+
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1)));
422+
DONE;
423+
})

gcc/config/riscv/iterators.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@
2222
;; Mode Iterators
2323
;; -------------------------------------------------------------------
2424

25+
;; These mode iterators are used by ARCV APEX to generate
26+
;; all valid combinations of operand types.
27+
(define_mode_iterator DM [SI DI SF DF]) ;; dest
28+
(define_mode_iterator S0M [SI DI SF DF]) ;; src0
29+
(define_mode_iterator S1M [SI DI SF DF]) ;; src1
30+
2531
;; This mode iterator allows 32-bit and 64-bit GPR patterns to be generated
2632
;; from the same template.
2733
(define_mode_iterator GPR [SI (DI "TARGET_64BIT")])

0 commit comments

Comments
 (0)