diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 746d6ec4124..c23edcf34bf 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -118,6 +118,10 @@ (define_predicate "nvptx_float_comparison_operator" (match_code "eq,ne,le,ge,lt,gt,uneq,unle,unge,unlt,ungt,unordered,ordered")) +(define_predicate "nvptx_vector_index_operand" + (and (match_code "const_int") + (match_test "UINTVAL (op) < 4"))) + ;; Test for a valid operand for a call instruction. (define_predicate "call_insn_operand" (match_code "symbol_ref,reg") @@ -194,6 +198,10 @@ ;; pointer-sized quantities. Exactly one of the two alternatives will match. (define_mode_iterator P [(SI "Pmode == SImode") (DI "Pmode == DImode")]) +;; Define element mode for each vector mode. +(define_mode_attr VECELEM [(V2SI "SI") (V2DI "DI")]) +(define_mode_attr Vecelem [(V2SI "si") (V2DI "di")]) + ;; We should get away with not defining memory alternatives, since we don't ;; get variables in this mode and pseudos are never spilled. (define_insn "movbi" @@ -1067,6 +1075,78 @@ "" "%.\\tcvt.s%T0%t1\\t%0, %1;") +;; Vector operations + +(define_insn "*vec_set_0" + [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R") + (vec_merge:VECIM + (vec_duplicate:VECIM + (match_operand: 1 "nvptx_register_operand" "R")) + (match_dup 0) + (const_int 1)))] + "" + "%.\\tmov%t1\\t%0.x, %1;") + +(define_insn "*vec_set_1" + [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R") + (vec_merge:VECIM + (vec_duplicate:VECIM + (match_operand: 1 "nvptx_register_operand" "R")) + (match_dup 0) + (const_int 2)))] + "" + "%.\\tmov%t1\\t%0.y, %1;") + +(define_insn "*vec_set_2" + [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R") + (vec_merge:VECIM + (vec_duplicate:VECIM + (match_operand: 1 "nvptx_register_operand" "R")) + (match_dup 0) + (const_int 4)))] + "" + "%.\\tmov%t1\\t%0.z, %1;") + +(define_insn "*vec_set_3" + [(set (match_operand:VECIM 0 "nvptx_register_operand" "=R") + (vec_merge:VECIM + (vec_duplicate:VECIM + (match_operand: 1 "nvptx_register_operand" "R")) + (match_dup 0) + (const_int 8)))] + "" + "%.\\tmov%t1\\t%0.w, %1;") + +(define_expand "vec_set" + [(match_operand:VECIM 0 "nvptx_register_operand") + (match_operand: 1 "nvptx_register_operand") + (match_operand:SI 2 "nvptx_vector_index_operand")] + "" +{ + enum machine_mode mode = GET_MODE (operands[0]); + int mask = 1 << INTVAL (operands[2]); + rtx tmp = gen_rtx_VEC_DUPLICATE (mode, operands[1]); + tmp = gen_rtx_VEC_MERGE (mode, tmp, operands[0], GEN_INT (mask)); + emit_insn (gen_rtx_SET (operands[0], tmp)); + DONE; +}) + +(define_insn "vec_extract" + [(set (match_operand: 0 "nvptx_register_operand" "=R") + (vec_select: + (match_operand:VECIM 1 "nvptx_register_operand" "R") + (parallel [(match_operand:SI 2 "nvptx_vector_index_operand" "")])))] + "" +{ + static const char *const asms[4] = { + "%.\\tmov%t0\\t%0, %1.x;", + "%.\\tmov%t0\\t%0, %1.y;", + "%.\\tmov%t0\\t%0, %1.z;", + "%.\\tmov%t0\\t%0, %1.w;" + }; + return asms[INTVAL (operands[2])]; +}) + ;; Miscellaneous (define_insn "nop" diff --git a/gcc/testsuite/gcc.target/nvptx/v2si-vec-set-extract.c b/gcc/testsuite/gcc.target/nvptx/v2si-vec-set-extract.c new file mode 100644 index 00000000000..a0709e50718 --- /dev/null +++ b/gcc/testsuite/gcc.target/nvptx/v2si-vec-set-extract.c @@ -0,0 +1,25 @@ +/* { dg-do assemble } */ +/* { dg-options "-O2 -save-temps" } */ + +typedef int __v2si __attribute__((__vector_size__(8))); + +int +foo (__v2si arg) +{ + return arg[0] + arg[1]; +} + +__v2si +foo2 (unsigned int a, unsigned int b) +{ + __v2si res; + res[0] = a; + res[1] = b; + return res; +} + +/* { dg-final { scan-assembler "mov.u32.*\\.x;" } } */ +/* { dg-final { scan-assembler "mov.u32.*\\.y;" } } * + +/* { dg-final { scan-assembler "mov.u32\[\t\]%r\[0-9\]\[0-9\]*\\.x, " } } */ +/* { dg-final { scan-assembler "mov.u32\[\t\]%r\[0-9\]\[0-9\]*\\.y, " } } */