]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/nvptx/nvptx.md
* match.pd ((x + y) - (x | y) -> x & y,
[thirdparty/gcc.git] / gcc / config / nvptx / nvptx.md
CommitLineData
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;")