Skip to content

Commit 2f72850

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 33f4f74 commit 2f72850

File tree

2 files changed

+202
-31
lines changed

2 files changed

+202
-31
lines changed

gcc/config/riscv/arcv-apex.md

Lines changed: 196 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@
4444
)
4545

4646
;; Used by "XI","XD" insn. format: `insn src0`
47-
(define_insn "riscv_arcv_apex_void_ftype_src0"
48-
[(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXI,xAVpXD")
49-
(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")]
5050
UNSPEC_ARCV_APEX_VOID_SRC0_V)]
5151
""
5252
{
@@ -68,11 +68,30 @@
6868
[(set_attr "type" "arith,arith")]
6969
)
7070

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+
7190
;; Used by "XS","XD" insn. format: `insn src0, src1`
72-
(define_insn "riscv_arcv_apex_void_ftype_src0_src1"
73-
[(unspec_volatile:SI [(match_operand:SI 0 "const_int_operand" "xAVpXS,xAVpXD")
74-
(match_operand:SI 1 "register_operand" "r,r")
75-
(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")]
7695
UNSPEC_ARCV_APEX_VOID_SRC0_SRC1_V)]
7796
""
7897
{
@@ -96,10 +115,31 @@
96115
[(set_attr "type" "arith,arith")]
97116
)
98117

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+
99139
;; Used by "XD" insn. format: `insn dest` volatile
100-
(define_insn "riscv_arcv_apex_dest_volatile"
101-
[(set (match_operand:SI 0 "register_operand" "=r")
102-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXD")]
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")]
103143
UNSPEC_ARCV_APEX_DEST_V))]
104144
""
105145
{
@@ -111,10 +151,29 @@
111151
[(set_attr "type" "arith")]
112152
)
113153

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+
114173
;; Used by "XD" insn. format: `insn dest`
115-
(define_insn "riscv_arcv_apex_dest_ftype"
116-
[(set (match_operand:SI 0 "register_operand" "=r")
117-
(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")]
118177
UNSPEC_ARCV_APEX_DEST))]
119178
""
120179
{
@@ -126,11 +185,30 @@
126185
[(set_attr "type" "arith")]
127186
)
128187

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+
129207
;; Used by "XI","XD" insn. format: `insn dest, src0` volatile
130-
(define_insn "riscv_arcv_apex_dest_src0_volatile"
131-
[(set (match_operand:SI 0 "register_operand" "=r,r")
132-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
133-
(match_operand:SI 2 "nonmemory_operand" "I,r")]
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")]
134212
UNSPEC_ARCV_APEX_DEST_SRC0_V))]
135213
""
136214
{
@@ -154,11 +232,32 @@
154232
[(set_attr "type" "arith,arith")]
155233
)
156234

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+
157256
;; Used by "XI","XD" insn. format: `insn dest, src0`
158-
(define_insn "riscv_arcv_apex_dest_ftype_src0"
159-
[(set (match_operand:SI 0 "register_operand" "=r,r")
160-
(unspec:SI [(match_operand:SI 1 "const_int_operand" "xAVpXI,xAVpXD")
161-
(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")]
162261
UNSPEC_ARCV_APEX_DEST_SRC0))]
163262
""
164263
{
@@ -182,12 +281,33 @@
182281
[(set_attr "type" "arith,arith")]
183282
)
184283

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+
185305
;; Used by "XS","XC","XD" insn. format: `insn dest, src0, imm/src1` volatile
186-
(define_insn "riscv_arcv_apex_dest_src0_src1_volatile"
187-
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
188-
(unspec_volatile:SI [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
189-
(match_operand:SI 2 "register_operand" "r,0,r")
190-
(match_operand:SI 3 "nonmemory_operand" "B8,I,r")]
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")]
191311
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1_V))]
192312
""
193313
{
@@ -219,12 +339,35 @@
219339
[(set_attr "type" "arith,arith,arith")]
220340
)
221341

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+
222365
;; Used by "XS","XC","XD" insn. format: `insn dest, src0, imm/src1`
223-
(define_insn "riscv_arcv_apex_dest_ftype_src0_src1"
224-
[(set (match_operand:SI 0 "register_operand" "=r,r,r")
225-
(unspec:SI [(match_operand:SI 1 "const_int_operand" "xAVpXS,xAVpXC,xAVpXD")
226-
(match_operand:SI 2 "register_operand" "r,0,r")
227-
(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")]
228371
UNSPEC_ARCV_APEX_DEST_SRC0_SRC1))]
229372
""
230373
{
@@ -256,3 +399,25 @@
256399
[(set_attr "type" "arith,arith,arith")]
257400
)
258401

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)