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