]>
Commit | Line | Data |
---|---|---|
8ce80784 | 1 | ;; Machine description for NVPTX. |
d353bf18 | 2 | ;; Copyright (C) 2014-2015 Free Software Foundation, Inc. |
8ce80784 | 3 | ;; Contributed by Bernd Schmidt <bernds@codesourcery.com> |
4 | ;; | |
5 | ;; This file is part of GCC. | |
6 | ;; | |
7 | ;; GCC is free software; you can redistribute it and/or modify | |
8 | ;; it under the terms of the GNU General Public License as published by | |
9 | ;; the Free Software Foundation; either version 3, or (at your option) | |
10 | ;; any later version. | |
11 | ;; | |
12 | ;; GCC is distributed in the hope that it will be useful, | |
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | ;; GNU General Public License for more details. | |
16 | ;; | |
17 | ;; You should have received a copy of the GNU General Public License | |
18 | ;; along with GCC; see the file COPYING3. If not see | |
19 | ;; <http://www.gnu.org/licenses/>. | |
20 | ||
21 | (define_c_enum "unspec" [ | |
22 | UNSPEC_ARG_REG | |
23 | UNSPEC_FROM_GLOBAL | |
24 | UNSPEC_FROM_LOCAL | |
25 | UNSPEC_FROM_PARAM | |
26 | UNSPEC_FROM_SHARED | |
27 | UNSPEC_FROM_CONST | |
28 | UNSPEC_TO_GLOBAL | |
29 | UNSPEC_TO_LOCAL | |
30 | UNSPEC_TO_PARAM | |
31 | UNSPEC_TO_SHARED | |
32 | UNSPEC_TO_CONST | |
33 | ||
34 | UNSPEC_CPLX_LOWPART | |
35 | UNSPEC_CPLX_HIGHPART | |
36 | ||
37 | UNSPEC_COPYSIGN | |
38 | UNSPEC_LOG2 | |
39 | UNSPEC_EXP2 | |
40 | UNSPEC_SIN | |
41 | UNSPEC_COS | |
42 | ||
43 | UNSPEC_FPINT_FLOOR | |
44 | UNSPEC_FPINT_BTRUNC | |
45 | UNSPEC_FPINT_CEIL | |
46 | UNSPEC_FPINT_NEARBYINT | |
47 | ||
48 | UNSPEC_BITREV | |
49 | ||
50 | UNSPEC_ALLOCA | |
51 | ||
52 | UNSPEC_NTID | |
53 | UNSPEC_TID | |
54 | ]) | |
55 | ||
56 | (define_c_enum "unspecv" [ | |
57 | UNSPECV_LOCK | |
58 | UNSPECV_CAS | |
59 | UNSPECV_XCHG | |
60 | ]) | |
61 | ||
62 | (define_attr "subregs_ok" "false,true" | |
63 | (const_string "false")) | |
64 | ||
65 | (define_predicate "nvptx_register_operand" | |
66 | (match_code "reg,subreg") | |
67 | { | |
68 | if (REG_P (op)) | |
69 | return !HARD_REGISTER_P (op); | |
70 | if (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) | |
71 | return false; | |
72 | if (GET_CODE (op) == SUBREG) | |
73 | return false; | |
74 | return register_operand (op, mode); | |
75 | }) | |
76 | ||
77 | (define_predicate "nvptx_reg_or_mem_operand" | |
78 | (match_code "mem,reg,subreg") | |
79 | { | |
80 | if (REG_P (op)) | |
81 | return !HARD_REGISTER_P (op); | |
82 | if (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) | |
83 | return false; | |
84 | if (GET_CODE (op) == SUBREG) | |
85 | return false; | |
86 | return memory_operand (op, mode) || register_operand (op, mode); | |
87 | }) | |
88 | ||
89 | ;; Allow symbolic constants. | |
90 | (define_predicate "symbolic_operand" | |
91 | (match_code "symbol_ref,const")) | |
92 | ||
93 | ;; Allow registers or symbolic constants. We can allow frame, arg or stack | |
94 | ;; pointers here since they are actually symbolic constants. | |
95 | (define_predicate "nvptx_register_or_symbolic_operand" | |
96 | (match_code "reg,subreg,symbol_ref,const") | |
97 | { | |
98 | if (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) | |
99 | return false; | |
100 | if (GET_CODE (op) == SUBREG) | |
101 | return false; | |
102 | if (CONSTANT_P (op)) | |
103 | return true; | |
104 | return register_operand (op, mode); | |
105 | }) | |
106 | ||
107 | ;; Registers or constants for normal instructions. Does not allow symbolic | |
108 | ;; constants. | |
109 | (define_predicate "nvptx_nonmemory_operand" | |
110 | (match_code "reg,subreg,const_int,const_double") | |
111 | { | |
112 | if (REG_P (op)) | |
113 | return !HARD_REGISTER_P (op); | |
114 | if (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))) | |
115 | return false; | |
116 | if (GET_CODE (op) == SUBREG) | |
117 | return false; | |
118 | return nonmemory_operand (op, mode); | |
119 | }) | |
120 | ||
121 | ;; A source operand for a move instruction. This is the only predicate we use | |
122 | ;; that accepts symbolic constants. | |
123 | (define_predicate "nvptx_general_operand" | |
124 | (match_code "reg,subreg,mem,const,symbol_ref,label_ref,const_int,const_double") | |
125 | { | |
126 | if (REG_P (op)) | |
127 | return !HARD_REGISTER_P (op); | |
128 | return general_operand (op, mode); | |
129 | }) | |
130 | ||
131 | ;; A destination operand for a move instruction. This is the only destination | |
132 | ;; predicate that accepts the return register since it requires special handling. | |
133 | (define_predicate "nvptx_nonimmediate_operand" | |
134 | (match_code "reg,subreg,mem") | |
135 | { | |
136 | if (REG_P (op)) | |
137 | return (op != frame_pointer_rtx | |
138 | && op != arg_pointer_rtx | |
139 | && op != stack_pointer_rtx); | |
140 | return nonimmediate_operand (op, mode); | |
141 | }) | |
142 | ||
143 | (define_predicate "const_0_operand" | |
144 | (and (match_code "const_int,const_double,const_vector") | |
145 | (match_test "op == CONST0_RTX (GET_MODE (op))"))) | |
146 | ||
147 | (define_predicate "global_mem_operand" | |
148 | (and (match_code "mem") | |
149 | (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_GLOBAL"))) | |
150 | ||
151 | (define_predicate "const_mem_operand" | |
152 | (and (match_code "mem") | |
153 | (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_CONST"))) | |
154 | ||
155 | (define_predicate "param_mem_operand" | |
156 | (and (match_code "mem") | |
157 | (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_PARAM"))) | |
158 | ||
159 | (define_predicate "shared_mem_operand" | |
160 | (and (match_code "mem") | |
161 | (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_SHARED"))) | |
162 | ||
163 | (define_predicate "const0_operand" | |
164 | (and (match_code "const_int") | |
165 | (match_test "op == const0_rtx"))) | |
166 | ||
167 | ;; True if this operator is valid for predication. | |
168 | (define_predicate "predicate_operator" | |
169 | (match_code "eq,ne")) | |
170 | ||
171 | (define_predicate "ne_operator" | |
172 | (match_code "ne")) | |
173 | ||
174 | (define_predicate "nvptx_comparison_operator" | |
175 | (match_code "eq,ne,le,ge,lt,gt,leu,geu,ltu,gtu")) | |
176 | ||
177 | (define_predicate "nvptx_float_comparison_operator" | |
178 | (match_code "eq,ne,le,ge,lt,gt,uneq,unle,unge,unlt,ungt,unordered,ordered")) | |
179 | ||
180 | ;; Test for a valid operand for a call instruction. | |
181 | (define_special_predicate "call_insn_operand" | |
182 | (match_code "symbol_ref,reg") | |
183 | { | |
184 | if (GET_CODE (op) == SYMBOL_REF) | |
185 | { | |
186 | tree decl = SYMBOL_REF_DECL (op); | |
187 | /* This happens for libcalls. */ | |
188 | if (decl == NULL_TREE) | |
189 | return true; | |
190 | return TREE_CODE (SYMBOL_REF_DECL (op)) == FUNCTION_DECL; | |
191 | } | |
192 | return true; | |
193 | }) | |
194 | ||
195 | ;; Return true if OP is a call with parallel USEs of the argument | |
196 | ;; pseudos. | |
197 | (define_predicate "call_operation" | |
198 | (match_code "parallel") | |
199 | { | |
200 | unsigned i; | |
201 | ||
202 | for (i = 1; i < XVECLEN (op, 0); i++) | |
203 | { | |
204 | rtx elt = XVECEXP (op, 0, i); | |
205 | enum machine_mode mode; | |
206 | unsigned regno; | |
207 | ||
208 | if (GET_CODE (elt) != USE | |
209 | || GET_CODE (XEXP (elt, 0)) != REG | |
210 | || XEXP (elt, 0) == frame_pointer_rtx | |
211 | || XEXP (elt, 0) == arg_pointer_rtx | |
212 | || XEXP (elt, 0) == stack_pointer_rtx) | |
213 | ||
214 | return false; | |
215 | } | |
216 | return true; | |
217 | }) | |
218 | ||
219 | (define_constraint "P0" | |
220 | "An integer with the value 0." | |
221 | (and (match_code "const_int") | |
222 | (match_test "ival == 0"))) | |
223 | ||
224 | (define_constraint "P1" | |
225 | "An integer with the value 1." | |
226 | (and (match_code "const_int") | |
227 | (match_test "ival == 1"))) | |
228 | ||
229 | (define_constraint "Pn" | |
230 | "An integer with the value -1." | |
231 | (and (match_code "const_int") | |
232 | (match_test "ival == -1"))) | |
233 | ||
234 | (define_constraint "R" | |
235 | "A pseudo register." | |
236 | (match_code "reg")) | |
237 | ||
238 | (define_constraint "Ia" | |
239 | "Any integer constant." | |
240 | (and (match_code "const_int") (match_test "true"))) | |
241 | ||
242 | (define_mode_iterator QHSDISDFM [QI HI SI DI SF DF]) | |
243 | (define_mode_iterator QHSDIM [QI HI SI DI]) | |
244 | (define_mode_iterator HSDIM [HI SI DI]) | |
245 | (define_mode_iterator BHSDIM [BI HI SI DI]) | |
246 | (define_mode_iterator SDIM [SI DI]) | |
247 | (define_mode_iterator SDISDFM [SI DI SF DF]) | |
248 | (define_mode_iterator QHIM [QI HI]) | |
249 | (define_mode_iterator QHSIM [QI HI SI]) | |
250 | (define_mode_iterator SDFM [SF DF]) | |
251 | (define_mode_iterator SDCM [SC DC]) | |
252 | ||
253 | ;; This mode iterator allows :P to be used for patterns that operate on | |
254 | ;; pointer-sized quantities. Exactly one of the two alternatives will match. | |
255 | (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) | |
256 | ||
257 | ;; We should get away with not defining memory alternatives, since we don't | |
258 | ;; get variables in this mode and pseudos are never spilled. | |
259 | (define_insn "movbi" | |
260 | [(set (match_operand:BI 0 "nvptx_register_operand" "=R,R,R") | |
261 | (match_operand:BI 1 "nvptx_nonmemory_operand" "R,P0,Pn"))] | |
262 | "" | |
263 | "@ | |
264 | %.\\tmov%t0\\t%0, %1; | |
265 | %.\\tsetp.eq.u32\\t%0, 1, 0; | |
266 | %.\\tsetp.eq.u32\\t%0, 1, 1;") | |
267 | ||
268 | (define_insn "*mov<mode>_insn" | |
269 | [(set (match_operand:QHSDIM 0 "nvptx_nonimmediate_operand" "=R,R,R,m") | |
270 | (match_operand:QHSDIM 1 "general_operand" "n,Ri,m,R"))] | |
271 | "!(MEM_P (operands[0]) | |
272 | && (!REG_P (operands[1]) || REGNO (operands[1]) <= LAST_VIRTUAL_REGISTER))" | |
273 | { | |
274 | if (which_alternative == 2) | |
275 | return "%.\\tld%A1%u1\\t%0, %1;"; | |
276 | if (which_alternative == 3) | |
277 | return "%.\\tst%A0%u0\\t%0, %1;"; | |
278 | ||
279 | rtx dst = operands[0]; | |
280 | rtx src = operands[1]; | |
281 | ||
282 | enum machine_mode dst_mode = nvptx_underlying_object_mode (dst); | |
283 | enum machine_mode src_mode = nvptx_underlying_object_mode (src); | |
284 | if (GET_CODE (dst) == SUBREG) | |
285 | dst = SUBREG_REG (dst); | |
286 | if (GET_CODE (src) == SUBREG) | |
287 | src = SUBREG_REG (src); | |
288 | if (src_mode == QImode) | |
289 | src_mode = SImode; | |
290 | if (dst_mode == QImode) | |
291 | dst_mode = SImode; | |
292 | if (CONSTANT_P (src)) | |
293 | { | |
294 | if (GET_MODE_CLASS (dst_mode) != MODE_INT) | |
295 | return "%.\\tmov.b%T0\\t%0, %1;"; | |
296 | else | |
297 | return "%.\\tmov%t0\\t%0, %1;"; | |
298 | } | |
299 | ||
300 | /* Special handling for the return register; we allow this register to | |
301 | only occur in the destination of a move insn. */ | |
302 | if (REG_P (dst) && REGNO (dst) == NVPTX_RETURN_REGNUM | |
303 | && dst_mode == HImode) | |
304 | dst_mode = SImode; | |
305 | if (dst_mode == src_mode) | |
306 | return "%.\\tmov%t0\\t%0, %1;"; | |
307 | /* Mode-punning between floating point and integer. */ | |
308 | if (GET_MODE_SIZE (dst_mode) == GET_MODE_SIZE (src_mode)) | |
309 | return "%.\\tmov.b%T0\\t%0, %1;"; | |
310 | return "%.\\tcvt%t0%t1\\t%0, %1;"; | |
311 | } | |
312 | [(set_attr "subregs_ok" "true")]) | |
313 | ||
314 | (define_insn "*mov<mode>_insn" | |
315 | [(set (match_operand:SDFM 0 "nvptx_nonimmediate_operand" "=R,R,m") | |
316 | (match_operand:SDFM 1 "general_operand" "RF,m,R"))] | |
317 | "!(MEM_P (operands[0]) && !REG_P (operands[1]))" | |
318 | { | |
319 | if (which_alternative == 1) | |
320 | return "%.\\tld%A1%u0\\t%0, %1;"; | |
321 | if (which_alternative == 2) | |
322 | return "%.\\tst%A0%u1\\t%0, %1;"; | |
323 | ||
324 | rtx dst = operands[0]; | |
325 | rtx src = operands[1]; | |
326 | if (GET_CODE (dst) == SUBREG) | |
327 | dst = SUBREG_REG (dst); | |
328 | if (GET_CODE (src) == SUBREG) | |
329 | src = SUBREG_REG (src); | |
330 | enum machine_mode dst_mode = GET_MODE (dst); | |
331 | enum machine_mode src_mode = GET_MODE (src); | |
332 | if (dst_mode == src_mode) | |
333 | return "%.\\tmov%t0\\t%0, %1;"; | |
334 | if (GET_MODE_SIZE (dst_mode) == GET_MODE_SIZE (src_mode)) | |
335 | return "%.\\tmov.b%T0\\t%0, %1;"; | |
336 | gcc_unreachable (); | |
337 | } | |
338 | [(set_attr "subregs_ok" "true")]) | |
339 | ||
340 | (define_insn "load_arg_reg<mode>" | |
341 | [(set (match_operand:QHIM 0 "nvptx_register_operand" "=R") | |
342 | (unspec:QHIM [(match_operand 1 "const_int_operand" "i")] | |
343 | UNSPEC_ARG_REG))] | |
344 | "" | |
345 | "%.\\tcvt%t0.u32\\t%0, %%ar%1;") | |
346 | ||
347 | (define_insn "load_arg_reg<mode>" | |
348 | [(set (match_operand:SDISDFM 0 "nvptx_register_operand" "=R") | |
349 | (unspec:SDISDFM [(match_operand 1 "const_int_operand" "i")] | |
350 | UNSPEC_ARG_REG))] | |
351 | "" | |
352 | "%.\\tmov%t0\\t%0, %%ar%1;") | |
353 | ||
354 | (define_expand "mov<mode>" | |
355 | [(set (match_operand:QHSDISDFM 0 "nvptx_nonimmediate_operand" "") | |
356 | (match_operand:QHSDISDFM 1 "general_operand" ""))] | |
357 | "" | |
358 | { | |
359 | operands[1] = nvptx_maybe_convert_symbolic_operand (operands[1]); | |
360 | /* Record the mode of the return register so that we can prevent | |
361 | later optimization passes from changing it. */ | |
362 | if (REG_P (operands[0]) && REGNO (operands[0]) == NVPTX_RETURN_REGNUM | |
363 | && cfun) | |
364 | { | |
365 | if (cfun->machine->ret_reg_mode == VOIDmode) | |
366 | cfun->machine->ret_reg_mode = GET_MODE (operands[0]); | |
367 | else | |
368 | gcc_assert (cfun->machine->ret_reg_mode == GET_MODE (operands[0])); | |
369 | } | |
370 | ||
371 | /* Hard registers are often actually symbolic operands on this target. | |
372 | Don't allow them when storing to memory. */ | |
373 | if (MEM_P (operands[0]) | |
374 | && (!REG_P (operands[1]) | |
375 | || REGNO (operands[1]) <= LAST_VIRTUAL_REGISTER)) | |
376 | { | |
377 | rtx tmp = gen_reg_rtx (<MODE>mode); | |
378 | emit_move_insn (tmp, operands[1]); | |
379 | emit_move_insn (operands[0], tmp); | |
380 | DONE; | |
381 | } | |
382 | if (GET_CODE (operands[1]) == SYMBOL_REF) | |
383 | nvptx_record_needed_fndecl (SYMBOL_REF_DECL (operands[1])); | |
384 | }) | |
385 | ||
386 | (define_insn "highpartscsf2" | |
387 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
388 | (unspec:SF [(match_operand:SC 1 "nvptx_register_operand")] | |
389 | UNSPEC_CPLX_HIGHPART))] | |
390 | "" | |
391 | "%.\\tmov%t0\\t%0, %f1$1;") | |
392 | ||
393 | (define_insn "set_highpartsfsc2" | |
394 | [(set (match_operand:SC 0 "nvptx_register_operand" "+R") | |
395 | (unspec:SC [(match_dup 0) | |
396 | (match_operand:SF 1 "nvptx_register_operand")] | |
397 | UNSPEC_CPLX_HIGHPART))] | |
398 | "" | |
399 | "%.\\tmov%t1\\t%f0$1, %1;") | |
400 | ||
401 | (define_insn "lowpartscsf2" | |
402 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
403 | (unspec:SF [(match_operand:SC 1 "nvptx_register_operand")] | |
404 | UNSPEC_CPLX_LOWPART))] | |
405 | "" | |
406 | "%.\\tmov%t0\\t%0, %f1$0;") | |
407 | ||
408 | (define_insn "set_lowpartsfsc2" | |
409 | [(set (match_operand:SC 0 "nvptx_register_operand" "+R") | |
410 | (unspec:SC [(match_dup 0) | |
411 | (match_operand:SF 1 "nvptx_register_operand")] | |
412 | UNSPEC_CPLX_LOWPART))] | |
413 | "" | |
414 | "%.\\tmov%t1\\t%f0$0, %1;") | |
415 | ||
416 | (define_expand "mov<mode>" | |
417 | [(set (match_operand:SDCM 0 "nvptx_nonimmediate_operand" "") | |
418 | (match_operand:SDCM 1 "general_operand" ""))] | |
419 | "" | |
420 | { | |
421 | enum machine_mode submode = <MODE>mode == SCmode ? SFmode : DFmode; | |
422 | int sz = GET_MODE_SIZE (submode); | |
423 | rtx xops[4]; | |
424 | rtx punning_reg = NULL_RTX; | |
425 | rtx copyback = NULL_RTX; | |
426 | ||
427 | if (GET_CODE (operands[0]) == SUBREG) | |
428 | { | |
429 | rtx inner = SUBREG_REG (operands[0]); | |
430 | enum machine_mode inner_mode = GET_MODE (inner); | |
431 | int sz2 = GET_MODE_SIZE (inner_mode); | |
432 | gcc_assert (sz2 >= sz); | |
433 | cfun->machine->punning_buffer_size | |
434 | = MAX (cfun->machine->punning_buffer_size, sz2); | |
435 | if (punning_reg == NULL_RTX) | |
436 | punning_reg = gen_rtx_REG (Pmode, NVPTX_PUNNING_BUFFER_REGNUM); | |
437 | copyback = gen_move_insn (inner, gen_rtx_MEM (inner_mode, punning_reg)); | |
438 | operands[0] = gen_rtx_MEM (<MODE>mode, punning_reg); | |
439 | } | |
440 | if (GET_CODE (operands[1]) == SUBREG) | |
441 | { | |
442 | rtx inner = SUBREG_REG (operands[1]); | |
443 | enum machine_mode inner_mode = GET_MODE (inner); | |
444 | int sz2 = GET_MODE_SIZE (inner_mode); | |
445 | gcc_assert (sz2 >= sz); | |
446 | cfun->machine->punning_buffer_size | |
447 | = MAX (cfun->machine->punning_buffer_size, sz2); | |
448 | if (punning_reg == NULL_RTX) | |
449 | punning_reg = gen_rtx_REG (Pmode, NVPTX_PUNNING_BUFFER_REGNUM); | |
450 | emit_move_insn (gen_rtx_MEM (inner_mode, punning_reg), inner); | |
451 | operands[1] = gen_rtx_MEM (<MODE>mode, punning_reg); | |
452 | } | |
453 | ||
454 | if (REG_P (operands[0]) && submode == SFmode) | |
455 | { | |
456 | xops[0] = gen_reg_rtx (submode); | |
457 | xops[1] = gen_reg_rtx (submode); | |
458 | } | |
459 | else | |
460 | { | |
461 | xops[0] = gen_lowpart (submode, operands[0]); | |
462 | if (MEM_P (operands[0])) | |
463 | xops[1] = adjust_address_nv (operands[0], submode, sz); | |
464 | else | |
465 | xops[1] = gen_highpart (submode, operands[0]); | |
466 | } | |
467 | ||
468 | if (REG_P (operands[1]) && submode == SFmode) | |
469 | { | |
470 | xops[2] = gen_reg_rtx (submode); | |
471 | xops[3] = gen_reg_rtx (submode); | |
472 | emit_insn (gen_lowpartscsf2 (xops[2], operands[1])); | |
473 | emit_insn (gen_highpartscsf2 (xops[3], operands[1])); | |
474 | } | |
475 | else | |
476 | { | |
477 | xops[2] = gen_lowpart (submode, operands[1]); | |
478 | if (MEM_P (operands[1])) | |
479 | xops[3] = adjust_address_nv (operands[1], submode, sz); | |
480 | else | |
481 | xops[3] = gen_highpart (submode, operands[1]); | |
482 | } | |
483 | ||
484 | emit_move_insn (xops[0], xops[2]); | |
485 | emit_move_insn (xops[1], xops[3]); | |
486 | if (REG_P (operands[0]) && submode == SFmode) | |
487 | { | |
488 | emit_insn (gen_set_lowpartsfsc2 (operands[0], xops[0])); | |
489 | emit_insn (gen_set_highpartsfsc2 (operands[0], xops[1])); | |
490 | } | |
491 | if (copyback) | |
492 | emit_insn (copyback); | |
493 | DONE; | |
494 | }) | |
495 | ||
496 | (define_insn "zero_extendqihi2" | |
497 | [(set (match_operand:HI 0 "nvptx_register_operand" "=R,R") | |
498 | (zero_extend:HI (match_operand:QI 1 "nvptx_reg_or_mem_operand" "R,m")))] | |
499 | "" | |
500 | "@ | |
501 | %.\\tcvt.u16.u%T1\\t%0, %1; | |
502 | %.\\tld%A1.u8\\t%0, %1;" | |
503 | [(set_attr "subregs_ok" "true")]) | |
504 | ||
505 | (define_insn "zero_extend<mode>si2" | |
506 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R,R") | |
507 | (zero_extend:SI (match_operand:QHIM 1 "nvptx_reg_or_mem_operand" "R,m")))] | |
508 | "" | |
509 | "@ | |
510 | %.\\tcvt.u32.u%T1\\t%0, %1; | |
511 | %.\\tld%A1.u%T1\\t%0, %1;" | |
512 | [(set_attr "subregs_ok" "true")]) | |
513 | ||
514 | (define_insn "zero_extend<mode>di2" | |
515 | [(set (match_operand:DI 0 "nvptx_register_operand" "=R,R") | |
516 | (zero_extend:DI (match_operand:QHSIM 1 "nvptx_reg_or_mem_operand" "R,m")))] | |
517 | "" | |
518 | "@ | |
519 | %.\\tcvt.u64.u%T1\\t%0, %1; | |
520 | %.\\tld%A1%u1\\t%0, %1;" | |
521 | [(set_attr "subregs_ok" "true")]) | |
522 | ||
523 | (define_insn "extend<mode>si2" | |
524 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R,R") | |
525 | (sign_extend:SI (match_operand:QHIM 1 "nvptx_reg_or_mem_operand" "R,m")))] | |
526 | "" | |
527 | "@ | |
528 | %.\\tcvt.s32.s%T1\\t%0, %1; | |
529 | %.\\tld%A1.s%T1\\t%0, %1;" | |
530 | [(set_attr "subregs_ok" "true")]) | |
531 | ||
532 | (define_insn "extend<mode>di2" | |
533 | [(set (match_operand:DI 0 "nvptx_register_operand" "=R,R") | |
534 | (sign_extend:DI (match_operand:QHSIM 1 "nvptx_reg_or_mem_operand" "R,m")))] | |
535 | "" | |
536 | "@ | |
537 | %.\\tcvt.s64.s%T1\\t%0, %1; | |
538 | %.\\tld%A1.s%T1\\t%0, %1;" | |
539 | [(set_attr "subregs_ok" "true")]) | |
540 | ||
541 | (define_insn "trunchiqi2" | |
542 | [(set (match_operand:QI 0 "nvptx_reg_or_mem_operand" "=R,m") | |
543 | (truncate:QI (match_operand:HI 1 "nvptx_register_operand" "R,R")))] | |
544 | "" | |
545 | "@ | |
546 | %.\\tcvt%t0.u16\\t%0, %1; | |
547 | %.\\tst%A0.u8\\t%0, %1;" | |
548 | [(set_attr "subregs_ok" "true")]) | |
549 | ||
550 | (define_insn "truncsi<mode>2" | |
551 | [(set (match_operand:QHIM 0 "nvptx_reg_or_mem_operand" "=R,m") | |
552 | (truncate:QHIM (match_operand:SI 1 "nvptx_register_operand" "R,R")))] | |
553 | "" | |
554 | "@ | |
555 | %.\\tcvt%t0.u32\\t%0, %1; | |
556 | %.\\tst%A0.u%T0\\t%0, %1;" | |
557 | [(set_attr "subregs_ok" "true")]) | |
558 | ||
559 | (define_insn "truncdi<mode>2" | |
560 | [(set (match_operand:QHSIM 0 "nvptx_reg_or_mem_operand" "=R,m") | |
561 | (truncate:QHSIM (match_operand:DI 1 "nvptx_register_operand" "R,R")))] | |
562 | "" | |
563 | "@ | |
564 | %.\\tcvt%t0.u64\\t%0, %1; | |
565 | %.\\tst%A0.u%T0\\t%0, %1;" | |
566 | [(set_attr "subregs_ok" "true")]) | |
567 | ||
568 | ;; Pointer address space conversions | |
569 | ||
570 | (define_int_iterator cvt_code | |
571 | [UNSPEC_FROM_GLOBAL | |
572 | UNSPEC_FROM_LOCAL | |
573 | UNSPEC_FROM_SHARED | |
574 | UNSPEC_FROM_CONST | |
575 | UNSPEC_TO_GLOBAL | |
576 | UNSPEC_TO_LOCAL | |
577 | UNSPEC_TO_SHARED | |
578 | UNSPEC_TO_CONST]) | |
579 | ||
580 | (define_int_attr cvt_name | |
581 | [(UNSPEC_FROM_GLOBAL "from_global") | |
582 | (UNSPEC_FROM_LOCAL "from_local") | |
583 | (UNSPEC_FROM_SHARED "from_shared") | |
584 | (UNSPEC_FROM_CONST "from_const") | |
585 | (UNSPEC_TO_GLOBAL "to_global") | |
586 | (UNSPEC_TO_LOCAL "to_local") | |
587 | (UNSPEC_TO_SHARED "to_shared") | |
588 | (UNSPEC_TO_CONST "to_const")]) | |
589 | ||
590 | (define_int_attr cvt_str | |
591 | [(UNSPEC_FROM_GLOBAL ".global") | |
592 | (UNSPEC_FROM_LOCAL ".local") | |
593 | (UNSPEC_FROM_SHARED ".shared") | |
594 | (UNSPEC_FROM_CONST ".const") | |
595 | (UNSPEC_TO_GLOBAL ".to.global") | |
596 | (UNSPEC_TO_LOCAL ".to.local") | |
597 | (UNSPEC_TO_SHARED ".to.shared") | |
598 | (UNSPEC_TO_CONST ".to.const")]) | |
599 | ||
600 | (define_insn "convaddr_<cvt_name><mode>" | |
601 | [(set (match_operand:P 0 "nvptx_register_operand" "=R") | |
602 | (unspec:P [(match_operand:P 1 "nvptx_register_or_symbolic_operand" "Rs")] cvt_code))] | |
603 | "" | |
604 | "%.\\tcvta<cvt_str>%t0\\t%0, %1;") | |
605 | ||
606 | ;; Integer arithmetic | |
607 | ||
608 | (define_insn "add<mode>3" | |
609 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
610 | (plus:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
611 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
612 | "" | |
613 | "%.\\tadd%t0\\t%0, %1, %2;") | |
614 | ||
615 | (define_insn "sub<mode>3" | |
616 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
617 | (minus:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
618 | (match_operand:HSDIM 2 "nvptx_register_operand" "R")))] | |
619 | "" | |
620 | "%.\\tsub%t0\\t%0, %1, %2;") | |
621 | ||
622 | (define_insn "mul<mode>3" | |
623 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
624 | (mult:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
625 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
626 | "" | |
627 | "%.\\tmul.lo%t0\\t%0, %1, %2;") | |
628 | ||
629 | (define_insn "*mad<mode>3" | |
630 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
631 | (plus:HSDIM (mult:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
632 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")) | |
633 | (match_operand:HSDIM 3 "nvptx_nonmemory_operand" "Ri")))] | |
634 | "" | |
635 | "%.\\tmad.lo%t0\\t%0, %1, %2, %3;") | |
636 | ||
637 | (define_insn "div<mode>3" | |
638 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
639 | (div:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
640 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
641 | "" | |
642 | "%.\\tdiv.s%T0\\t%0, %1, %2;") | |
643 | ||
644 | (define_insn "udiv<mode>3" | |
645 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
646 | (udiv:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
647 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
648 | "" | |
649 | "%.\\tdiv.u%T0\\t%0, %1, %2;") | |
650 | ||
651 | (define_insn "mod<mode>3" | |
652 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
653 | (mod:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "Ri") | |
654 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
655 | "" | |
656 | "%.\\trem.s%T0\\t%0, %1, %2;") | |
657 | ||
658 | (define_insn "umod<mode>3" | |
659 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
660 | (umod:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "Ri") | |
661 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
662 | "" | |
663 | "%.\\trem.u%T0\\t%0, %1, %2;") | |
664 | ||
665 | (define_insn "smin<mode>3" | |
666 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
667 | (smin:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
668 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
669 | "" | |
670 | "%.\\tmin.s%T0\\t%0, %1, %2;") | |
671 | ||
672 | (define_insn "umin<mode>3" | |
673 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
674 | (umin:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
675 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
676 | "" | |
677 | "%.\\tmin.u%T0\\t%0, %1, %2;") | |
678 | ||
679 | (define_insn "smax<mode>3" | |
680 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
681 | (smax:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
682 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
683 | "" | |
684 | "%.\\tmax.s%T0\\t%0, %1, %2;") | |
685 | ||
686 | (define_insn "umax<mode>3" | |
687 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
688 | (umax:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R") | |
689 | (match_operand:HSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
690 | "" | |
691 | "%.\\tmax.u%T0\\t%0, %1, %2;") | |
692 | ||
693 | (define_insn "abs<mode>2" | |
694 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
695 | (abs:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R")))] | |
696 | "" | |
697 | "%.\\tabs.s%T0\\t%0, %1;") | |
698 | ||
699 | (define_insn "neg<mode>2" | |
700 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
701 | (neg:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R")))] | |
702 | "" | |
703 | "%.\\tneg.s%T0\\t%0, %1;") | |
704 | ||
705 | (define_insn "one_cmpl<mode>2" | |
706 | [(set (match_operand:HSDIM 0 "nvptx_register_operand" "=R") | |
707 | (not:HSDIM (match_operand:HSDIM 1 "nvptx_register_operand" "R")))] | |
708 | "" | |
709 | "%.\\tnot.b%T0\\t%0, %1;") | |
710 | ||
711 | (define_insn "bitrev<mode>2" | |
712 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
713 | (unspec:SDIM [(match_operand:SDIM 1 "nvptx_register_operand" "R")] | |
714 | UNSPEC_BITREV))] | |
715 | "" | |
716 | "%.\\tbrev.b%T0\\t%0, %1;") | |
717 | ||
718 | (define_insn "clz<mode>2" | |
719 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
720 | (clz:SI (match_operand:SDIM 1 "nvptx_register_operand" "R")))] | |
721 | "" | |
722 | "%.\\tclz.b%T0\\t%0, %1;") | |
723 | ||
724 | (define_expand "ctz<mode>2" | |
725 | [(set (match_operand:SI 0 "nvptx_register_operand" "") | |
726 | (ctz:SI (match_operand:SDIM 1 "nvptx_register_operand" "")))] | |
727 | "" | |
728 | { | |
729 | rtx tmpreg = gen_reg_rtx (<MODE>mode); | |
730 | emit_insn (gen_bitrev<mode>2 (tmpreg, operands[1])); | |
731 | emit_insn (gen_clz<mode>2 (operands[0], tmpreg)); | |
732 | DONE; | |
733 | }) | |
734 | ||
735 | ;; Shifts | |
736 | ||
737 | (define_insn "ashl<mode>3" | |
738 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
739 | (ashift:SDIM (match_operand:SDIM 1 "nvptx_register_operand" "R") | |
740 | (match_operand:SI 2 "nvptx_nonmemory_operand" "Ri")))] | |
741 | "" | |
742 | "%.\\tshl.b%T0\\t%0, %1, %2;") | |
743 | ||
744 | (define_insn "ashr<mode>3" | |
745 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
746 | (ashiftrt:SDIM (match_operand:SDIM 1 "nvptx_register_operand" "R") | |
747 | (match_operand:SI 2 "nvptx_nonmemory_operand" "Ri")))] | |
748 | "" | |
749 | "%.\\tshr.s%T0\\t%0, %1, %2;") | |
750 | ||
751 | (define_insn "lshr<mode>3" | |
752 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
753 | (lshiftrt:SDIM (match_operand:SDIM 1 "nvptx_register_operand" "R") | |
754 | (match_operand:SI 2 "nvptx_nonmemory_operand" "Ri")))] | |
755 | "" | |
756 | "%.\\tshr.u%T0\\t%0, %1, %2;") | |
757 | ||
758 | ;; Logical operations | |
759 | ||
760 | (define_insn "and<mode>3" | |
761 | [(set (match_operand:BHSDIM 0 "nvptx_register_operand" "=R") | |
762 | (and:BHSDIM (match_operand:BHSDIM 1 "nvptx_register_operand" "R") | |
763 | (match_operand:BHSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
764 | "" | |
765 | "%.\\tand.b%T0\\t%0, %1, %2;") | |
766 | ||
767 | (define_insn "ior<mode>3" | |
768 | [(set (match_operand:BHSDIM 0 "nvptx_register_operand" "=R") | |
769 | (ior:BHSDIM (match_operand:BHSDIM 1 "nvptx_register_operand" "R") | |
770 | (match_operand:BHSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
771 | "" | |
772 | "%.\\tor.b%T0\\t%0, %1, %2;") | |
773 | ||
774 | (define_insn "xor<mode>3" | |
775 | [(set (match_operand:BHSDIM 0 "nvptx_register_operand" "=R") | |
776 | (xor:BHSDIM (match_operand:BHSDIM 1 "nvptx_register_operand" "R") | |
777 | (match_operand:BHSDIM 2 "nvptx_nonmemory_operand" "Ri")))] | |
778 | "" | |
779 | "%.\\txor.b%T0\\t%0, %1, %2;") | |
780 | ||
781 | ;; Comparisons and branches | |
782 | ||
783 | (define_insn "*cmp<mode>" | |
784 | [(set (match_operand:BI 0 "nvptx_register_operand" "=R") | |
785 | (match_operator:BI 1 "nvptx_comparison_operator" | |
786 | [(match_operand:HSDIM 2 "nvptx_register_operand" "R") | |
787 | (match_operand:HSDIM 3 "nvptx_nonmemory_operand" "Ri")]))] | |
788 | "" | |
789 | "%.\\tsetp%c1 %0,%2,%3;") | |
790 | ||
791 | (define_insn "*cmp<mode>" | |
792 | [(set (match_operand:BI 0 "nvptx_register_operand" "=R") | |
793 | (match_operator:BI 1 "nvptx_float_comparison_operator" | |
794 | [(match_operand:SDFM 2 "nvptx_register_operand" "R") | |
795 | (match_operand:SDFM 3 "nvptx_nonmemory_operand" "RF")]))] | |
796 | "" | |
797 | "%.\\tsetp%c1 %0,%2,%3;") | |
798 | ||
799 | (define_insn "jump" | |
800 | [(set (pc) | |
801 | (label_ref (match_operand 0 "" "")))] | |
802 | "" | |
803 | "%.\\tbra\\t%l0;") | |
804 | ||
805 | (define_insn "br_true" | |
806 | [(set (pc) | |
807 | (if_then_else (ne (match_operand:BI 0 "nvptx_register_operand" "R") | |
808 | (const_int 0)) | |
809 | (label_ref (match_operand 1 "" "")) | |
810 | (pc)))] | |
811 | "" | |
812 | "%j0\\tbra\\t%l1;") | |
813 | ||
814 | (define_insn "br_false" | |
815 | [(set (pc) | |
816 | (if_then_else (eq (match_operand:BI 0 "nvptx_register_operand" "R") | |
817 | (const_int 0)) | |
818 | (label_ref (match_operand 1 "" "")) | |
819 | (pc)))] | |
820 | "" | |
821 | "%J0\\tbra\\t%l1;") | |
822 | ||
823 | (define_expand "cbranch<mode>4" | |
824 | [(set (pc) | |
825 | (if_then_else (match_operator 0 "nvptx_comparison_operator" | |
826 | [(match_operand:HSDIM 1 "nvptx_register_operand" "") | |
827 | (match_operand:HSDIM 2 "nvptx_register_operand" "")]) | |
828 | (label_ref (match_operand 3 "" "")) | |
829 | (pc)))] | |
830 | "" | |
831 | { | |
832 | rtx t = nvptx_expand_compare (operands[0]); | |
833 | operands[0] = t; | |
834 | operands[1] = XEXP (t, 0); | |
835 | operands[2] = XEXP (t, 1); | |
836 | }) | |
837 | ||
838 | (define_expand "cbranch<mode>4" | |
839 | [(set (pc) | |
840 | (if_then_else (match_operator 0 "nvptx_float_comparison_operator" | |
841 | [(match_operand:SDFM 1 "nvptx_register_operand" "") | |
842 | (match_operand:SDFM 2 "nvptx_register_operand" "")]) | |
843 | (label_ref (match_operand 3 "" "")) | |
844 | (pc)))] | |
845 | "" | |
846 | { | |
847 | rtx t = nvptx_expand_compare (operands[0]); | |
848 | operands[0] = t; | |
849 | operands[1] = XEXP (t, 0); | |
850 | operands[2] = XEXP (t, 1); | |
851 | }) | |
852 | ||
853 | (define_expand "cbranchbi4" | |
854 | [(set (pc) | |
855 | (if_then_else (match_operator 0 "predicate_operator" | |
856 | [(match_operand:BI 1 "nvptx_register_operand" "") | |
857 | (match_operand:BI 2 "const0_operand" "")]) | |
858 | (label_ref (match_operand 3 "" "")) | |
859 | (pc)))] | |
860 | "" | |
861 | "") | |
862 | ||
863 | ;; Conditional stores | |
864 | ||
865 | (define_insn "setcc_from_bi" | |
866 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
867 | (ne:SI (match_operand:BI 1 "nvptx_register_operand" "R") | |
868 | (const_int 0)))] | |
869 | "" | |
870 | "%.\\tselp%t0 %0,-1,0,%1;") | |
871 | ||
872 | (define_insn "setcc_int<mode>" | |
873 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
874 | (match_operator:SI 1 "nvptx_comparison_operator" | |
875 | [(match_operand:HSDIM 2 "nvptx_register_operand" "R") | |
876 | (match_operand:HSDIM 3 "nvptx_nonmemory_operand" "Ri")]))] | |
877 | "" | |
878 | "%.\\tset%t0%c1 %0,%2,%3;") | |
879 | ||
880 | (define_insn "setcc_int<mode>" | |
881 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
882 | (match_operator:SI 1 "nvptx_float_comparison_operator" | |
883 | [(match_operand:SDFM 2 "nvptx_register_operand" "R") | |
884 | (match_operand:SDFM 3 "nvptx_nonmemory_operand" "RF")]))] | |
885 | "" | |
886 | "%.\\tset%t0%c1 %0,%2,%3;") | |
887 | ||
888 | (define_insn "setcc_float<mode>" | |
889 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
890 | (match_operator:SF 1 "nvptx_comparison_operator" | |
891 | [(match_operand:HSDIM 2 "nvptx_register_operand" "R") | |
892 | (match_operand:HSDIM 3 "nvptx_nonmemory_operand" "Ri")]))] | |
893 | "" | |
894 | "%.\\tset%t0%c1 %0,%2,%3;") | |
895 | ||
896 | (define_insn "setcc_float<mode>" | |
897 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
898 | (match_operator:SF 1 "nvptx_float_comparison_operator" | |
899 | [(match_operand:SDFM 2 "nvptx_register_operand" "R") | |
900 | (match_operand:SDFM 3 "nvptx_nonmemory_operand" "RF")]))] | |
901 | "" | |
902 | "%.\\tset%t0%c1 %0,%2,%3;") | |
903 | ||
904 | (define_expand "cstorebi4" | |
905 | [(set (match_operand:SI 0 "nvptx_register_operand") | |
906 | (match_operator:SI 1 "ne_operator" | |
907 | [(match_operand:BI 2 "nvptx_register_operand") | |
908 | (match_operand:BI 3 "const0_operand")]))] | |
909 | "" | |
910 | "") | |
911 | ||
912 | (define_expand "cstore<mode>4" | |
913 | [(set (match_operand:SI 0 "nvptx_register_operand") | |
914 | (match_operator:SI 1 "nvptx_comparison_operator" | |
915 | [(match_operand:HSDIM 2 "nvptx_register_operand") | |
916 | (match_operand:HSDIM 3 "nvptx_nonmemory_operand")]))] | |
917 | "" | |
918 | "") | |
919 | ||
920 | (define_expand "cstore<mode>4" | |
921 | [(set (match_operand:SI 0 "nvptx_register_operand") | |
922 | (match_operator:SI 1 "nvptx_float_comparison_operator" | |
923 | [(match_operand:SDFM 2 "nvptx_register_operand") | |
924 | (match_operand:SDFM 3 "nvptx_nonmemory_operand")]))] | |
925 | "" | |
926 | "") | |
927 | ||
928 | ;; Calls | |
929 | ||
930 | (define_insn "call_insn" | |
931 | [(match_parallel 2 "call_operation" | |
932 | [(call (mem:QI (match_operand:SI 0 "call_insn_operand" "Rs")) | |
933 | (match_operand 1))])] | |
934 | "" | |
935 | { | |
936 | return nvptx_output_call_insn (insn, NULL_RTX, operands[0]); | |
937 | }) | |
938 | ||
939 | (define_insn "call_value_insn" | |
940 | [(match_parallel 3 "call_operation" | |
941 | [(set (match_operand 0 "nvptx_register_operand" "=R") | |
942 | (call (mem:QI (match_operand:SI 1 "call_insn_operand" "Rs")) | |
943 | (match_operand 2)))])] | |
944 | "" | |
945 | { | |
946 | return nvptx_output_call_insn (insn, operands[0], operands[1]); | |
947 | }) | |
948 | ||
949 | (define_expand "call" | |
950 | [(match_operand 0 "" "")] | |
951 | "" | |
952 | { | |
953 | nvptx_expand_call (NULL_RTX, operands[0]); | |
954 | DONE; | |
955 | }) | |
956 | ||
957 | (define_expand "call_value" | |
958 | [(match_operand 0 "" "") | |
959 | (match_operand 1 "" "")] | |
960 | "" | |
961 | { | |
962 | nvptx_expand_call (operands[0], operands[1]); | |
963 | DONE; | |
964 | }) | |
965 | ||
966 | ;; Floating point arithmetic. | |
967 | ||
968 | (define_insn "add<mode>3" | |
969 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
970 | (plus:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
971 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF")))] | |
972 | "" | |
973 | "%.\\tadd%t0\\t%0, %1, %2;") | |
974 | ||
975 | (define_insn "sub<mode>3" | |
976 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
977 | (minus:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
978 | (match_operand:SDFM 2 "nvptx_register_operand" "R")))] | |
979 | "" | |
980 | "%.\\tsub%t0\\t%0, %1, %2;") | |
981 | ||
982 | (define_insn "mul<mode>3" | |
983 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
984 | (mult:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
985 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF")))] | |
986 | "" | |
987 | "%.\\tmul%t0\\t%0, %1, %2;") | |
988 | ||
989 | (define_insn "fma<mode>4" | |
990 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
991 | (fma:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
992 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF") | |
993 | (match_operand:SDFM 3 "nvptx_nonmemory_operand" "RF")))] | |
994 | "" | |
995 | "%.\\tfma%#%t0\\t%0, %1, %2, %3;") | |
996 | ||
997 | (define_insn "div<mode>3" | |
998 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
999 | (div:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
1000 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF")))] | |
1001 | "" | |
1002 | "%.\\tdiv%#%t0\\t%0, %1, %2;") | |
1003 | ||
1004 | (define_insn "copysign<mode>3" | |
1005 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1006 | (unspec:SDFM [(match_operand:SDFM 1 "nvptx_register_operand" "R") | |
1007 | (match_operand:SDFM 2 "nvptx_register_operand" "R")] | |
1008 | UNSPEC_COPYSIGN))] | |
1009 | "" | |
1010 | "%.\\tcopysign%t0\\t%0, %2, %1;") | |
1011 | ||
1012 | (define_insn "smin<mode>3" | |
1013 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1014 | (smin:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
1015 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF")))] | |
1016 | "" | |
1017 | "%.\\tmin%t0\\t%0, %1, %2;") | |
1018 | ||
1019 | (define_insn "smax<mode>3" | |
1020 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1021 | (smax:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R") | |
1022 | (match_operand:SDFM 2 "nvptx_nonmemory_operand" "RF")))] | |
1023 | "" | |
1024 | "%.\\tmax%t0\\t%0, %1, %2;") | |
1025 | ||
1026 | (define_insn "abs<mode>2" | |
1027 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1028 | (abs:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1029 | "" | |
1030 | "%.\\tabs%t0\\t%0, %1;") | |
1031 | ||
1032 | (define_insn "neg<mode>2" | |
1033 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1034 | (neg:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1035 | "" | |
1036 | "%.\\tneg%t0\\t%0, %1;") | |
1037 | ||
1038 | (define_insn "sqrt<mode>2" | |
1039 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1040 | (sqrt:SDFM (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1041 | "" | |
1042 | "%.\\tsqrt%#%t0\\t%0, %1;") | |
1043 | ||
1044 | (define_insn "sinsf2" | |
1045 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1046 | (unspec:SF [(match_operand:SF 1 "nvptx_register_operand" "R")] | |
1047 | UNSPEC_SIN))] | |
1048 | "flag_unsafe_math_optimizations" | |
1049 | "%.\\tsin.approx%t0\\t%0, %1;") | |
1050 | ||
1051 | (define_insn "cossf2" | |
1052 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1053 | (unspec:SF [(match_operand:SF 1 "nvptx_register_operand" "R")] | |
1054 | UNSPEC_COS))] | |
1055 | "flag_unsafe_math_optimizations" | |
1056 | "%.\\tcos.approx%t0\\t%0, %1;") | |
1057 | ||
1058 | (define_insn "log2sf2" | |
1059 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1060 | (unspec:SF [(match_operand:SF 1 "nvptx_register_operand" "R")] | |
1061 | UNSPEC_LOG2))] | |
1062 | "flag_unsafe_math_optimizations" | |
1063 | "%.\\tlg2.approx%t0\\t%0, %1;") | |
1064 | ||
1065 | (define_insn "exp2sf2" | |
1066 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1067 | (unspec:SF [(match_operand:SF 1 "nvptx_register_operand" "R")] | |
1068 | UNSPEC_EXP2))] | |
1069 | "flag_unsafe_math_optimizations" | |
1070 | "%.\\tex2.approx%t0\\t%0, %1;") | |
1071 | ||
1072 | ;; Conversions involving floating point | |
1073 | ||
1074 | (define_insn "extendsfdf2" | |
1075 | [(set (match_operand:DF 0 "nvptx_register_operand" "=R") | |
1076 | (float_extend:DF (match_operand:SF 1 "nvptx_register_operand" "R")))] | |
1077 | "" | |
1078 | "%.\\tcvt%t0%t1\\t%0, %1;") | |
1079 | ||
1080 | (define_insn "truncdfsf2" | |
1081 | [(set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1082 | (float_truncate:SF (match_operand:DF 1 "nvptx_register_operand" "R")))] | |
1083 | "" | |
1084 | "%.\\tcvt%#%t0%t1\\t%0, %1;") | |
1085 | ||
1086 | (define_insn "floatunssi<mode>2" | |
1087 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1088 | (unsigned_float:SDFM (match_operand:SI 1 "nvptx_register_operand" "R")))] | |
1089 | "" | |
1090 | "%.\\tcvt%#%t0.u%T1\\t%0, %1;") | |
1091 | ||
1092 | (define_insn "floatsi<mode>2" | |
1093 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1094 | (float:SDFM (match_operand:SI 1 "nvptx_register_operand" "R")))] | |
1095 | "" | |
1096 | "%.\\tcvt%#%t0.s%T1\\t%0, %1;") | |
1097 | ||
1098 | (define_insn "floatunsdi<mode>2" | |
1099 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1100 | (unsigned_float:SDFM (match_operand:DI 1 "nvptx_register_operand" "R")))] | |
1101 | "" | |
1102 | "%.\\tcvt%#%t0.u%T1\\t%0, %1;") | |
1103 | ||
1104 | (define_insn "floatdi<mode>2" | |
1105 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1106 | (float:SDFM (match_operand:DI 1 "nvptx_register_operand" "R")))] | |
1107 | "" | |
1108 | "%.\\tcvt%#%t0.s%T1\\t%0, %1;") | |
1109 | ||
1110 | (define_insn "fixuns_trunc<mode>si2" | |
1111 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
1112 | (unsigned_fix:SI (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1113 | "" | |
1114 | "%.\\tcvt.rzi.u%T0%t1\\t%0, %1;") | |
1115 | ||
1116 | (define_insn "fix_trunc<mode>si2" | |
1117 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
1118 | (fix:SI (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1119 | "" | |
1120 | "%.\\tcvt.rzi.s%T0%t1\\t%0, %1;") | |
1121 | ||
1122 | (define_insn "fixuns_trunc<mode>di2" | |
1123 | [(set (match_operand:DI 0 "nvptx_register_operand" "=R") | |
1124 | (unsigned_fix:DI (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1125 | "" | |
1126 | "%.\\tcvt.rzi.u%T0%t1\\t%0, %1;") | |
1127 | ||
1128 | (define_insn "fix_trunc<mode>di2" | |
1129 | [(set (match_operand:DI 0 "nvptx_register_operand" "=R") | |
1130 | (fix:DI (match_operand:SDFM 1 "nvptx_register_operand" "R")))] | |
1131 | "" | |
1132 | "%.\\tcvt.rzi.s%T0%t1\\t%0, %1;") | |
1133 | ||
1134 | (define_int_iterator FPINT [UNSPEC_FPINT_FLOOR UNSPEC_FPINT_BTRUNC | |
1135 | UNSPEC_FPINT_CEIL UNSPEC_FPINT_NEARBYINT]) | |
1136 | (define_int_attr fpint_name [(UNSPEC_FPINT_FLOOR "floor") | |
1137 | (UNSPEC_FPINT_BTRUNC "btrunc") | |
1138 | (UNSPEC_FPINT_CEIL "ceil") | |
1139 | (UNSPEC_FPINT_NEARBYINT "nearbyint")]) | |
1140 | (define_int_attr fpint_roundingmode [(UNSPEC_FPINT_FLOOR ".rmi") | |
1141 | (UNSPEC_FPINT_BTRUNC ".rzi") | |
1142 | (UNSPEC_FPINT_CEIL ".rpi") | |
1143 | (UNSPEC_FPINT_NEARBYINT "%#i")]) | |
1144 | ||
1145 | (define_insn "<FPINT:fpint_name><SDFM:mode>2" | |
1146 | [(set (match_operand:SDFM 0 "nvptx_register_operand" "=R") | |
1147 | (unspec:SDFM [(match_operand:SDFM 1 "nvptx_register_operand" "R")] | |
1148 | FPINT))] | |
1149 | "" | |
1150 | "%.\\tcvt<FPINT:fpint_roundingmode>%t0%t1\\t%0, %1;") | |
1151 | ||
1152 | (define_int_iterator FPINT2 [UNSPEC_FPINT_FLOOR UNSPEC_FPINT_CEIL]) | |
1153 | (define_int_attr fpint2_name [(UNSPEC_FPINT_FLOOR "lfloor") | |
1154 | (UNSPEC_FPINT_CEIL "lceil")]) | |
1155 | (define_int_attr fpint2_roundingmode [(UNSPEC_FPINT_FLOOR ".rmi") | |
1156 | (UNSPEC_FPINT_CEIL ".rpi")]) | |
1157 | ||
1158 | (define_insn "<FPINT2:fpint2_name><SDFM:mode><SDIM:mode>2" | |
1159 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
1160 | (unspec:SDIM [(match_operand:SDFM 1 "nvptx_register_operand" "R")] | |
1161 | FPINT2))] | |
1162 | "" | |
1163 | "%.\\tcvt<FPINT2:fpint2_roundingmode>.s%T0%t1\\t%0, %1;") | |
1164 | ||
1165 | ;; Miscellaneous | |
1166 | ||
1167 | (define_insn "nop" | |
1168 | [(const_int 0)] | |
1169 | "" | |
1170 | "") | |
1171 | ||
1172 | (define_insn "return" | |
1173 | [(return)] | |
1174 | "" | |
1175 | { | |
1176 | return nvptx_output_return (); | |
1177 | }) | |
1178 | ||
1179 | (define_expand "epilogue" | |
1180 | [(clobber (const_int 0))] | |
1181 | "" | |
1182 | { | |
1183 | emit_jump_insn (gen_return ()); | |
1184 | DONE; | |
1185 | }) | |
1186 | ||
1187 | (define_expand "nonlocal_goto" | |
1188 | [(match_operand 0 "" "") | |
1189 | (match_operand 1 "" "") | |
1190 | (match_operand 2 "" "") | |
1191 | (match_operand 3 "" "")] | |
1192 | "" | |
1193 | { | |
1194 | sorry ("target cannot support nonlocal goto."); | |
1195 | emit_insn (gen_nop ()); | |
1196 | DONE; | |
1197 | }) | |
1198 | ||
1199 | (define_expand "nonlocal_goto_receiver" | |
1200 | [(const_int 0)] | |
1201 | "" | |
1202 | { | |
1203 | sorry ("target cannot support nonlocal goto."); | |
1204 | }) | |
1205 | ||
ed20400d | 1206 | (define_expand "allocate_stack" |
1207 | [(match_operand 0 "nvptx_register_operand") | |
1208 | (match_operand 1 "nvptx_register_operand")] | |
1209 | "" | |
1210 | { | |
1211 | if (TARGET_ABI64) | |
1212 | emit_insn (gen_allocate_stack_di (operands[0], operands[1])); | |
1213 | else | |
1214 | emit_insn (gen_allocate_stack_si (operands[0], operands[1])); | |
1215 | DONE; | |
1216 | }) | |
1217 | ||
1218 | (define_insn "allocate_stack_<mode>" | |
1219 | [(set (match_operand:P 0 "nvptx_register_operand" "=R") | |
1220 | (unspec:P [(match_operand:P 1 "nvptx_register_operand" "R")] | |
1221 | UNSPEC_ALLOCA))] | |
8ce80784 | 1222 | "" |
1223 | "%.\\tcall (%0), %%alloca, (%1);") | |
1224 | ||
1225 | (define_expand "restore_stack_block" | |
1226 | [(match_operand 0 "register_operand" "") | |
1227 | (match_operand 1 "register_operand" "")] | |
1228 | "" | |
1229 | { | |
1230 | DONE; | |
1231 | }) | |
1232 | ||
1233 | (define_expand "restore_stack_function" | |
1234 | [(match_operand 0 "register_operand" "") | |
1235 | (match_operand 1 "register_operand" "")] | |
1236 | "" | |
1237 | { | |
1238 | DONE; | |
1239 | }) | |
1240 | ||
1241 | (define_insn "trap" | |
1242 | [(trap_if (const_int 1) (const_int 0))] | |
1243 | "" | |
1244 | "trap;") | |
1245 | ||
1246 | (define_insn "trap_if_true" | |
1247 | [(trap_if (ne (match_operand:BI 0 "nvptx_register_operand" "R") | |
1248 | (const_int 0)) | |
1249 | (const_int 0))] | |
1250 | "" | |
1251 | "%j0 trap;") | |
1252 | ||
1253 | (define_insn "trap_if_false" | |
1254 | [(trap_if (eq (match_operand:BI 0 "nvptx_register_operand" "R") | |
1255 | (const_int 0)) | |
1256 | (const_int 0))] | |
1257 | "" | |
1258 | "%J0 trap;") | |
1259 | ||
1260 | (define_expand "ctrap<mode>4" | |
1261 | [(trap_if (match_operator 0 "nvptx_comparison_operator" | |
1262 | [(match_operand:SDIM 1 "nvptx_register_operand") | |
1263 | (match_operand:SDIM 2 "nvptx_nonmemory_operand")]) | |
1264 | (match_operand 3 "const_0_operand"))] | |
1265 | "" | |
1266 | { | |
1267 | rtx t = nvptx_expand_compare (operands[0]); | |
1268 | emit_insn (gen_trap_if_true (t)); | |
1269 | DONE; | |
1270 | }) | |
1271 | ||
1272 | (define_insn "*oacc_ntid_insn" | |
1273 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
1274 | (unspec:SI [(match_operand:SI 1 "const_int_operand" "n")] UNSPEC_NTID))] | |
1275 | "" | |
1276 | "%.\\tmov.u32 %0, %%ntid%d1;") | |
1277 | ||
1278 | (define_expand "oacc_ntid" | |
1279 | [(set (match_operand:SI 0 "nvptx_register_operand" "") | |
1280 | (unspec:SI [(match_operand:SI 1 "const_int_operand" "")] UNSPEC_NTID))] | |
1281 | "" | |
1282 | { | |
1283 | if (INTVAL (operands[1]) < 0 || INTVAL (operands[1]) > 2) | |
1284 | FAIL; | |
1285 | }) | |
1286 | ||
1287 | (define_insn "*oacc_tid_insn" | |
1288 | [(set (match_operand:SI 0 "nvptx_register_operand" "=R") | |
1289 | (unspec:SI [(match_operand:SI 1 "const_int_operand" "n")] UNSPEC_TID))] | |
1290 | "" | |
1291 | "%.\\tmov.u32 %0, %%tid%d1;") | |
1292 | ||
1293 | (define_expand "oacc_tid" | |
1294 | [(set (match_operand:SI 0 "nvptx_register_operand" "") | |
1295 | (unspec:SI [(match_operand:SI 1 "const_int_operand" "")] UNSPEC_TID))] | |
1296 | "" | |
1297 | { | |
1298 | if (INTVAL (operands[1]) < 0 || INTVAL (operands[1]) > 2) | |
1299 | FAIL; | |
1300 | }) | |
1301 | ||
1302 | ;; Atomic insns. | |
1303 | ||
1304 | (define_expand "atomic_compare_and_swap<mode>" | |
1305 | [(match_operand:SI 0 "nvptx_register_operand") ;; bool success output | |
1306 | (match_operand:SDIM 1 "nvptx_register_operand") ;; oldval output | |
1307 | (match_operand:SDIM 2 "memory_operand") ;; memory | |
1308 | (match_operand:SDIM 3 "nvptx_register_operand") ;; expected input | |
1309 | (match_operand:SDIM 4 "nvptx_register_operand") ;; newval input | |
1310 | (match_operand:SI 5 "const_int_operand") ;; is_weak | |
1311 | (match_operand:SI 6 "const_int_operand") ;; success model | |
1312 | (match_operand:SI 7 "const_int_operand")] ;; failure model | |
1313 | "" | |
1314 | { | |
1315 | emit_insn (gen_atomic_compare_and_swap<mode>_1 (operands[1], operands[2], operands[3], | |
1316 | operands[4], operands[6])); | |
1317 | ||
1318 | rtx tmp = gen_reg_rtx (GET_MODE (operands[0])); | |
1319 | emit_insn (gen_cstore<mode>4 (tmp, | |
1320 | gen_rtx_EQ (SImode, operands[1], operands[3]), | |
1321 | operands[1], operands[3])); | |
1322 | emit_insn (gen_andsi3 (operands[0], tmp, GEN_INT (1))); | |
1323 | DONE; | |
1324 | }) | |
1325 | ||
1326 | (define_insn "atomic_compare_and_swap<mode>_1" | |
1327 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
1328 | (unspec_volatile:SDIM | |
1329 | [(match_operand:SDIM 1 "memory_operand" "+m") | |
1330 | (match_operand:SDIM 2 "nvptx_register_operand" "R") | |
1331 | (match_operand:SDIM 3 "nvptx_register_operand" "R") | |
1332 | (match_operand:SI 4 "const_int_operand")] | |
1333 | UNSPECV_CAS)) | |
1334 | (set (match_dup 1) | |
1335 | (unspec_volatile:SDIM [(const_int 0)] UNSPECV_CAS))] | |
1336 | "" | |
1337 | "%.\\tatom%A1.cas.b%T0\\t%0, %1, %2, %3;") | |
1338 | ||
1339 | (define_insn "atomic_exchange<mode>" | |
1340 | [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R") ;; output | |
1341 | (unspec_volatile:SDIM | |
1342 | [(match_operand:SDIM 1 "memory_operand" "+m") ;; memory | |
1343 | (match_operand:SI 3 "const_int_operand")] ;; model | |
1344 | UNSPECV_XCHG)) | |
1345 | (set (match_dup 1) | |
1346 | (match_operand:SDIM 2 "nvptx_register_operand" "R"))] ;; input | |
1347 | "" | |
1348 | "%.\\tatom%A1.exch.b%T0\\t%0, %1, %2;") | |
1349 | ||
1350 | (define_insn "atomic_fetch_add<mode>" | |
1351 | [(set (match_operand:SDIM 1 "memory_operand" "+m") | |
1352 | (unspec_volatile:SDIM | |
1353 | [(plus:SDIM (match_dup 1) | |
1354 | (match_operand:SDIM 2 "nvptx_nonmemory_operand" "Ri")) | |
1355 | (match_operand:SI 3 "const_int_operand")] ;; model | |
1356 | UNSPECV_LOCK)) | |
1357 | (set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
1358 | (match_dup 1))] | |
1359 | "" | |
1360 | "%.\\tatom%A1.add%t0\\t%0, %1, %2;") | |
1361 | ||
1362 | (define_insn "atomic_fetch_addsf" | |
1363 | [(set (match_operand:SF 1 "memory_operand" "+m") | |
1364 | (unspec_volatile:SF | |
1365 | [(plus:SF (match_dup 1) | |
1366 | (match_operand:SF 2 "nvptx_nonmemory_operand" "RF")) | |
1367 | (match_operand:SI 3 "const_int_operand")] ;; model | |
1368 | UNSPECV_LOCK)) | |
1369 | (set (match_operand:SF 0 "nvptx_register_operand" "=R") | |
1370 | (match_dup 1))] | |
1371 | "" | |
1372 | "%.\\tatom%A1.add%t0\\t%0, %1, %2;") | |
1373 | ||
1374 | (define_code_iterator any_logic [and ior xor]) | |
1375 | (define_code_attr logic [(and "and") (ior "or") (xor "xor")]) | |
1376 | ||
1377 | ;; Currently disabled until we add better subtarget support - requires sm_32. | |
1378 | (define_insn "atomic_fetch_<logic><mode>" | |
1379 | [(set (match_operand:SDIM 1 "memory_operand" "+m") | |
1380 | (unspec_volatile:SDIM | |
1381 | [(any_logic:SDIM (match_dup 1) | |
1382 | (match_operand:SDIM 2 "nvptx_nonmemory_operand" "Ri")) | |
1383 | (match_operand:SI 3 "const_int_operand")] ;; model | |
1384 | UNSPECV_LOCK)) | |
1385 | (set (match_operand:SDIM 0 "nvptx_register_operand" "=R") | |
1386 | (match_dup 1))] | |
1387 | "0" | |
1388 | "%.\\tatom%A1.b%T0.<logic>\\t%0, %1, %2;") |