* include/bits/stl_iterator.h (make_reverse_iterator): LWG DR 2285.
[official-gcc.git] / gcc / config / nvptx / nvptx.md
blob966c28be11ef87de0af00e71cae39cce8e380711
1 ;; Machine description for NVPTX.
2 ;; Copyright (C) 2014 Free Software Foundation, Inc.
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.
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.
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/>.
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
34    UNSPEC_CPLX_LOWPART
35    UNSPEC_CPLX_HIGHPART
37    UNSPEC_COPYSIGN
38    UNSPEC_LOG2
39    UNSPEC_EXP2
40    UNSPEC_SIN
41    UNSPEC_COS
43    UNSPEC_FPINT_FLOOR
44    UNSPEC_FPINT_BTRUNC
45    UNSPEC_FPINT_CEIL
46    UNSPEC_FPINT_NEARBYINT
48    UNSPEC_BITREV
50    UNSPEC_ALLOCA
52    UNSPEC_NTID
53    UNSPEC_TID
56 (define_c_enum "unspecv" [
57    UNSPECV_LOCK
58    UNSPECV_CAS
59    UNSPECV_XCHG
62 (define_attr "subregs_ok" "false,true"
63   (const_string "false"))
65 (define_predicate "nvptx_register_operand"
66   (match_code "reg,subreg")
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);
77 (define_predicate "nvptx_reg_or_mem_operand"
78   (match_code "mem,reg,subreg")
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);
89 ;; Allow symbolic constants.
90 (define_predicate "symbolic_operand"
91   (match_code "symbol_ref,const"))
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")
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);
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")
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);
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")
126   if (REG_P (op))
127     return !HARD_REGISTER_P (op);
128   return general_operand (op, mode);
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")
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);
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))")))
147 (define_predicate "global_mem_operand"
148   (and (match_code "mem")
149        (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_GLOBAL")))
151 (define_predicate "const_mem_operand"
152   (and (match_code "mem")
153        (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_CONST")))
155 (define_predicate "param_mem_operand"
156   (and (match_code "mem")
157        (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_PARAM")))
159 (define_predicate "shared_mem_operand"
160   (and (match_code "mem")
161        (match_test "MEM_ADDR_SPACE (op) == ADDR_SPACE_SHARED")))
163 (define_predicate "const0_operand"
164   (and (match_code "const_int")
165        (match_test "op == const0_rtx")))
167 ;; True if this operator is valid for predication.
168 (define_predicate "predicate_operator"
169   (match_code "eq,ne"))
171 (define_predicate "ne_operator"
172   (match_code "ne"))
174 (define_predicate "nvptx_comparison_operator"
175   (match_code "eq,ne,le,ge,lt,gt,leu,geu,ltu,gtu"))
177 (define_predicate "nvptx_float_comparison_operator"
178   (match_code "eq,ne,le,ge,lt,gt,uneq,unle,unge,unlt,ungt,unordered,ordered"))
180 ;; Test for a valid operand for a call instruction.
181 (define_special_predicate "call_insn_operand"
182   (match_code "symbol_ref,reg")
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;
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")
200   unsigned i;
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;
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)
214         return false;
215     }
216   return true;
219 (define_constraint "P0"
220   "An integer with the value 0."
221   (and (match_code "const_int")
222        (match_test "ival == 0")))
224 (define_constraint "P1"
225   "An integer with the value 1."
226   (and (match_code "const_int")
227        (match_test "ival == 1")))
229 (define_constraint "Pn"
230   "An integer with the value -1."
231   (and (match_code "const_int")
232        (match_test "ival == -1")))
234 (define_constraint "R"
235   "A pseudo register."
236   (match_code "reg"))
238 (define_constraint "Ia"
239   "Any integer constant."
240   (and (match_code "const_int") (match_test "true")))
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])
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")])
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;")
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))"
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;";
279   rtx dst = operands[0];
280   rtx src = operands[1];
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     }
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;";
312   [(set_attr "subregs_ok" "true")])
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]))"
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;";
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 ();
338   [(set_attr "subregs_ok" "true")])
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;")
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;")
354 (define_expand "mov<mode>"
355   [(set (match_operand:QHSDISDFM 0 "nvptx_nonimmediate_operand" "")
356         (match_operand:QHSDISDFM 1 "general_operand" ""))]
357   ""
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     }
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]));
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;")
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;")
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;")
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;")
416 (define_expand "mov<mode>"
417   [(set (match_operand:SDCM 0 "nvptx_nonimmediate_operand" "")
418         (match_operand:SDCM 1 "general_operand" ""))]
419   ""
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;
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     }
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     }
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     }
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;
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")])
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")])
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")])
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")])
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")])
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")])
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")])
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")])
568 ;; Pointer address space conversions
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])
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")])
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")])
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;")
606 ;; Integer arithmetic
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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   ""
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;
735 ;; Shifts
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;")
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;")
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;")
758 ;; Logical operations
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;")
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;")
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;")
781 ;; Comparisons and branches
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;")
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;")
799 (define_insn "jump"
800   [(set (pc)
801         (label_ref (match_operand 0 "" "")))]
802   ""
803   "%.\\tbra\\t%l0;")
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;")
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;")
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   ""
832   rtx t = nvptx_expand_compare (operands[0]);
833   operands[0] = t;
834   operands[1] = XEXP (t, 0);
835   operands[2] = XEXP (t, 1);
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   ""
847   rtx t = nvptx_expand_compare (operands[0]);
848   operands[0] = t;
849   operands[1] = XEXP (t, 0);
850   operands[2] = XEXP (t, 1);
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   "")
863 ;; Conditional stores
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;")
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;")
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;")
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;")
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;")
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   "")
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   "")
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   "")
928 ;; Calls
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   ""
936   return nvptx_output_call_insn (insn, NULL_RTX, operands[0]);
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   ""
946   return nvptx_output_call_insn (insn, operands[0], operands[1]);
949 (define_expand "call"
950  [(match_operand 0 "" "")]
951  ""
953   nvptx_expand_call (NULL_RTX, operands[0]);
954   DONE;
957 (define_expand "call_value"
958   [(match_operand 0 "" "")
959    (match_operand 1 "" "")]
960  ""
962   nvptx_expand_call (operands[0], operands[1]);
963   DONE;
966 ;; Floating point arithmetic.
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
1072 ;; Conversions involving floating point
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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;")
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")])
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;")
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")])
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;")
1165 ;; Miscellaneous
1167 (define_insn "nop"
1168   [(const_int 0)]
1169   ""
1170   "")
1172 (define_insn "return"
1173   [(return)]
1174   ""
1176   return nvptx_output_return ();
1179 (define_expand "epilogue"
1180   [(clobber (const_int 0))]
1181   ""
1183   emit_jump_insn (gen_return ());
1184   DONE;
1187 (define_expand "nonlocal_goto"
1188   [(match_operand 0 "" "")
1189    (match_operand 1 "" "")
1190    (match_operand 2 "" "")
1191    (match_operand 3 "" "")]
1192   ""
1194   sorry ("target cannot support nonlocal goto.");
1195   emit_insn (gen_nop ());
1196   DONE;
1199 (define_expand "nonlocal_goto_receiver"
1200   [(const_int 0)]
1201   ""
1203   sorry ("target cannot support nonlocal goto.");
1206 (define_insn "allocate_stack"
1207   [(set (match_operand 0 "nvptx_register_operand" "=R")
1208         (unspec [(match_operand 1 "nvptx_register_operand" "R")]
1209                   UNSPEC_ALLOCA))]
1210   ""
1211   "%.\\tcall (%0), %%alloca, (%1);")
1213 (define_expand "restore_stack_block"
1214   [(match_operand 0 "register_operand" "")
1215    (match_operand 1 "register_operand" "")]
1216   ""
1218   DONE;
1221 (define_expand "restore_stack_function"
1222   [(match_operand 0 "register_operand" "")
1223    (match_operand 1 "register_operand" "")]
1224   ""
1226   DONE;
1229 (define_insn "trap"
1230   [(trap_if (const_int 1) (const_int 0))]
1231   ""
1232   "trap;")
1234 (define_insn "trap_if_true"
1235   [(trap_if (ne (match_operand:BI 0 "nvptx_register_operand" "R")
1236                 (const_int 0))
1237             (const_int 0))]
1238   ""
1239   "%j0 trap;")
1241 (define_insn "trap_if_false"
1242   [(trap_if (eq (match_operand:BI 0 "nvptx_register_operand" "R")
1243                 (const_int 0))
1244             (const_int 0))]
1245   ""
1246   "%J0 trap;")
1248 (define_expand "ctrap<mode>4"
1249   [(trap_if (match_operator 0 "nvptx_comparison_operator"
1250                             [(match_operand:SDIM 1 "nvptx_register_operand")
1251                              (match_operand:SDIM 2 "nvptx_nonmemory_operand")])
1252             (match_operand 3 "const_0_operand"))]
1253   ""
1255   rtx t = nvptx_expand_compare (operands[0]);
1256   emit_insn (gen_trap_if_true (t));
1257   DONE;
1260 (define_insn "*oacc_ntid_insn"
1261   [(set (match_operand:SI 0 "nvptx_register_operand" "=R")
1262         (unspec:SI [(match_operand:SI 1 "const_int_operand" "n")] UNSPEC_NTID))]
1263   ""
1264   "%.\\tmov.u32 %0, %%ntid%d1;")
1266 (define_expand "oacc_ntid"
1267   [(set (match_operand:SI 0 "nvptx_register_operand" "")
1268         (unspec:SI [(match_operand:SI 1 "const_int_operand" "")] UNSPEC_NTID))]
1269   ""
1271   if (INTVAL (operands[1]) < 0 || INTVAL (operands[1]) > 2)
1272     FAIL;
1275 (define_insn "*oacc_tid_insn"
1276   [(set (match_operand:SI 0 "nvptx_register_operand" "=R")
1277         (unspec:SI [(match_operand:SI 1 "const_int_operand" "n")] UNSPEC_TID))]
1278   ""
1279   "%.\\tmov.u32 %0, %%tid%d1;")
1281 (define_expand "oacc_tid"
1282   [(set (match_operand:SI 0 "nvptx_register_operand" "")
1283         (unspec:SI [(match_operand:SI 1 "const_int_operand" "")] UNSPEC_TID))]
1284   ""
1286   if (INTVAL (operands[1]) < 0 || INTVAL (operands[1]) > 2)
1287     FAIL;
1290 ;; Atomic insns.
1292 (define_expand "atomic_compare_and_swap<mode>"
1293   [(match_operand:SI 0 "nvptx_register_operand")        ;; bool success output
1294    (match_operand:SDIM 1 "nvptx_register_operand")      ;; oldval output
1295    (match_operand:SDIM 2 "memory_operand")              ;; memory
1296    (match_operand:SDIM 3 "nvptx_register_operand")      ;; expected input
1297    (match_operand:SDIM 4 "nvptx_register_operand")      ;; newval input
1298    (match_operand:SI 5 "const_int_operand")             ;; is_weak
1299    (match_operand:SI 6 "const_int_operand")             ;; success model
1300    (match_operand:SI 7 "const_int_operand")]            ;; failure model
1301   ""
1303   emit_insn (gen_atomic_compare_and_swap<mode>_1 (operands[1], operands[2], operands[3],
1304                                                   operands[4], operands[6]));
1306   rtx tmp = gen_reg_rtx (GET_MODE (operands[0]));
1307   emit_insn (gen_cstore<mode>4 (tmp,
1308                                 gen_rtx_EQ (SImode, operands[1], operands[3]),
1309                                 operands[1], operands[3]));
1310   emit_insn (gen_andsi3 (operands[0], tmp, GEN_INT (1)));
1311   DONE;
1314 (define_insn "atomic_compare_and_swap<mode>_1"
1315   [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
1316         (unspec_volatile:SDIM
1317           [(match_operand:SDIM 1 "memory_operand" "+m")
1318            (match_operand:SDIM 2 "nvptx_register_operand" "R")
1319            (match_operand:SDIM 3 "nvptx_register_operand" "R")
1320            (match_operand:SI 4 "const_int_operand")]
1321           UNSPECV_CAS))
1322    (set (match_dup 1)
1323         (unspec_volatile:SDIM [(const_int 0)] UNSPECV_CAS))]
1324   ""
1325   "%.\\tatom%A1.cas.b%T0\\t%0, %1, %2, %3;")
1327 (define_insn "atomic_exchange<mode>"
1328   [(set (match_operand:SDIM 0 "nvptx_register_operand" "=R")    ;; output
1329         (unspec_volatile:SDIM
1330           [(match_operand:SDIM 1 "memory_operand" "+m")         ;; memory
1331            (match_operand:SI 3 "const_int_operand")]            ;; model
1332           UNSPECV_XCHG))
1333    (set (match_dup 1)
1334         (match_operand:SDIM 2 "nvptx_register_operand" "R"))]   ;; input
1335   ""
1336   "%.\\tatom%A1.exch.b%T0\\t%0, %1, %2;")
1338 (define_insn "atomic_fetch_add<mode>"
1339   [(set (match_operand:SDIM 1 "memory_operand" "+m")
1340         (unspec_volatile:SDIM
1341           [(plus:SDIM (match_dup 1)
1342                       (match_operand:SDIM 2 "nvptx_nonmemory_operand" "Ri"))
1343            (match_operand:SI 3 "const_int_operand")]            ;; model
1344           UNSPECV_LOCK))
1345    (set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
1346         (match_dup 1))]
1347   ""
1348   "%.\\tatom%A1.add%t0\\t%0, %1, %2;")
1350 (define_insn "atomic_fetch_addsf"
1351   [(set (match_operand:SF 1 "memory_operand" "+m")
1352         (unspec_volatile:SF
1353          [(plus:SF (match_dup 1)
1354                    (match_operand:SF 2 "nvptx_nonmemory_operand" "RF"))
1355            (match_operand:SI 3 "const_int_operand")]            ;; model
1356           UNSPECV_LOCK))
1357    (set (match_operand:SF 0 "nvptx_register_operand" "=R")
1358         (match_dup 1))]
1359   ""
1360   "%.\\tatom%A1.add%t0\\t%0, %1, %2;")
1362 (define_code_iterator any_logic [and ior xor])
1363 (define_code_attr logic [(and "and") (ior "or") (xor "xor")])
1365 ;; Currently disabled until we add better subtarget support - requires sm_32.
1366 (define_insn "atomic_fetch_<logic><mode>"
1367   [(set (match_operand:SDIM 1 "memory_operand" "+m")
1368         (unspec_volatile:SDIM
1369           [(any_logic:SDIM (match_dup 1)
1370                            (match_operand:SDIM 2 "nvptx_nonmemory_operand" "Ri"))
1371            (match_operand:SI 3 "const_int_operand")]            ;; model
1372           UNSPECV_LOCK))
1373    (set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
1374         (match_dup 1))]
1375   "0"
1376   "%.\\tatom%A1.b%T0.<logic>\\t%0, %1, %2;")