aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorseurer <seurer@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-28 16:01:52 +0000
committerseurer <seurer@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-28 16:01:52 +0000
commite40e5340c842f97ef0a3442575325967bebc00da (patch)
tree815b7ca188aec3bf1ebe9db84f4fcf2eaac04a32
parentcf977d50a042b22d767b6316cbcf75d6511398d9 (diff)
This patch adds support for the signed and unsigned int versions of the
vec_adde altivec builtins from the Power Architecture 64-Bit ELF V2 ABI OpenPOWER ABI for Linux Supplement (16 July 2015 Version 1.1). There are many of the builtins that are missing and this is the first of a series of patches to add them. There aren't instructions for the int versions of vec_adde so the output code is built from other built-ins that do have instructions which in this case is just two vec_adds with a vec_and to ensure the carry vector is comprised of only the values 0 or 1. The new test cases are executable tests which verify that the generated code produces expected values. C macros were used so that the same test case could be used for both the signed and unsigned versions. An extra executable test case is also included to ensure that the modified support for the __int128 versions of vec_adde is not broken. The same test case could not be used for both int and __int128 because of some differences in loading and storing the vectors. Bootstrapped and tested on powerpc64le-unknown-linux-gnu with no regressions. Is this ok for trunk? [gcc] 2016-04-28 Bill Seurer <seurer@linux.vnet.ibm.com> * config/rs6000/rs6000-builtin.def (vec_adde): Change vec_adde to a special case builtin. * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Remove ALTIVEC_BUILTIN_VEC_ADDE. * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Add support for ALTIVEC_BUILTIN_VEC_ADDE. * config/rs6000/rs6000.c (altivec_init_builtins): Add definition for __builtin_vec_adde. [gcc/testsuite] 2016-04-28 Bill Seurer <seurer@linux.vnet.ibm.com> * gcc.target/powerpc/vec-adde.c: New test. * gcc.target/powerpc/vec-adde-int128.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@235577 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/rs6000/rs6000-builtin.def2
-rw-r--r--gcc/config/rs6000/rs6000-c.c64
-rw-r--r--gcc/config/rs6000/rs6000.c7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-adde-int128.c77
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-adde.c77
7 files changed, 237 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3f99dbdad61..c5cfea6bf9b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2016-04-28 Bill Seurer <seurer@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000-builtin.def (vec_adde): Change vec_adde to a
+ special case builtin.
+ * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Remove
+ ALTIVEC_BUILTIN_VEC_ADDE.
+ * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Add
+ support for ALTIVEC_BUILTIN_VEC_ADDE.
+ * config/rs6000/rs6000.c (altivec_init_builtins): Add definition
+ for __builtin_vec_adde.
+
2016-04-28 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.md (sse4_1_round<mode>2): Add avx512f alternative.
diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def
index 891d2402676..930d778c941 100644
--- a/gcc/config/rs6000/rs6000-builtin.def
+++ b/gcc/config/rs6000/rs6000-builtin.def
@@ -951,7 +951,6 @@ BU_ALTIVEC_X (VEC_EXT_V4SF, "vec_ext_v4sf", CONST)
before we get to the point about classifying the builtin type. */
/* 3 argument Altivec overloaded builtins. */
-BU_ALTIVEC_OVERLOAD_3 (ADDE, "adde")
BU_ALTIVEC_OVERLOAD_3 (ADDEC, "addec")
BU_ALTIVEC_OVERLOAD_3 (MADD, "madd")
BU_ALTIVEC_OVERLOAD_3 (MADDS, "madds")
@@ -1137,6 +1136,7 @@ BU_ALTIVEC_OVERLOAD_P (VCMPGT_P, "vcmpgt_p")
BU_ALTIVEC_OVERLOAD_P (VCMPGE_P, "vcmpge_p")
/* Overloaded Altivec builtins that are handled as special cases. */
+BU_ALTIVEC_OVERLOAD_X (ADDE, "adde")
BU_ALTIVEC_OVERLOAD_X (CTF, "ctf")
BU_ALTIVEC_OVERLOAD_X (CTS, "cts")
BU_ALTIVEC_OVERLOAD_X (CTU, "ctu")
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index 55751a670de..5d20e035636 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -842,11 +842,6 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = {
RS6000_BTI_unsigned_V1TI, 0 },
{ ALTIVEC_BUILTIN_VEC_ADDC, P8V_BUILTIN_VADDCUQ,
RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, 0 },
- { ALTIVEC_BUILTIN_VEC_ADDE, P8V_BUILTIN_VADDEUQM,
- RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
- RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI },
- { ALTIVEC_BUILTIN_VEC_ADDE, P8V_BUILTIN_VADDEUQM,
- RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI, RS6000_BTI_V1TI },
{ ALTIVEC_BUILTIN_VEC_ADDEC, P8V_BUILTIN_VADDECUQ,
RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI,
RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V1TI },
@@ -4515,6 +4510,65 @@ assignment for unaligned loads and stores");
warning (OPT_Wdeprecated, "vec_lvsr is deprecated for little endian; use \
assignment for unaligned loads and stores");
+ if (fcode == ALTIVEC_BUILTIN_VEC_ADDE)
+ {
+ /* vec_adde needs to be special cased because there is no instruction
+ for the {un}signed int version. */
+ if (nargs != 3)
+ {
+ error ("vec_adde only accepts 3 arguments");
+ return error_mark_node;
+ }
+
+ tree arg0 = (*arglist)[0];
+ tree arg0_type = TREE_TYPE (arg0);
+ tree arg1 = (*arglist)[1];
+ tree arg1_type = TREE_TYPE (arg1);
+ tree arg2 = (*arglist)[2];
+ tree arg2_type = TREE_TYPE (arg2);
+
+ /* All 3 arguments must be vectors of (signed or unsigned) (int or
+ __int128) and the types must match. */
+ if ((arg0_type != arg1_type) || (arg1_type != arg2_type))
+ goto bad;
+ if (TREE_CODE (arg0_type) != VECTOR_TYPE)
+ goto bad;
+
+ switch (TYPE_MODE (TREE_TYPE (arg0_type)))
+ {
+ /* For {un}signed ints,
+ vec_adde (va, vb, carryv) == vec_add (vec_add (va, vb),
+ vec_and (carryv, 0x1)). */
+ case SImode:
+ {
+ vec<tree, va_gc> *params = make_tree_vector();
+ vec_safe_push (params, arg0);
+ vec_safe_push (params, arg1);
+ tree call = altivec_resolve_overloaded_builtin
+ (loc, rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD], params);
+ tree const1 = build_vector_from_val (arg0_type,
+ build_int_cstu(TREE_TYPE (arg0_type), 1));
+ tree and_expr = fold_build2_loc (loc, BIT_AND_EXPR,
+ arg0_type, arg2, const1);
+ params = make_tree_vector();
+ vec_safe_push (params, call);
+ vec_safe_push (params, and_expr);
+ return altivec_resolve_overloaded_builtin
+ (loc, rs6000_builtin_decls[ALTIVEC_BUILTIN_VEC_ADD], params);
+ }
+ /* For {un}signed __int128s use the vaddeuqm instruction
+ directly. */
+ case TImode:
+ return altivec_resolve_overloaded_builtin
+ (loc, rs6000_builtin_decls[P8V_BUILTIN_VEC_VADDEUQM], arglist);
+
+ /* Types other than {un}signed int and {un}signed __int128
+ are errors. */
+ default:
+ goto bad;
+ }
+ }
+
/* For now treat vec_splats and vec_promote as the same. */
if (fcode == ALTIVEC_BUILTIN_VEC_SPLATS
|| fcode == ALTIVEC_BUILTIN_VEC_PROMOTE)
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index fba4f9ea71a..0e6923483e0 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -15690,6 +15690,10 @@ altivec_init_builtins (void)
= build_function_type_list (opaque_V4SI_type_node,
opaque_V4SI_type_node, opaque_V4SI_type_node,
integer_type_node, NULL_TREE);
+ tree opaque_ftype_opaque_opaque_opaque
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, opaque_V4SI_type_node,
+ opaque_V4SI_type_node, NULL_TREE);
tree int_ftype_int_opaque_opaque
= build_function_type_list (integer_type_node,
integer_type_node, opaque_V4SI_type_node,
@@ -15926,6 +15930,9 @@ altivec_init_builtins (void)
def_builtin ("__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS);
def_builtin ("__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU);
+ def_builtin ("__builtin_vec_adde", opaque_ftype_opaque_opaque_opaque,
+ ALTIVEC_BUILTIN_VEC_ADDE);
+
/* Cell builtins. */
def_builtin ("__builtin_altivec_lvlx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLX);
def_builtin ("__builtin_altivec_lvlxl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_LVLXL);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6aef47cc753..00616c895e1 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-04-28 Bill Seurer <seurer@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vec-adde.c: New test.
+ * gcc.target/powerpc/vec-adde-int128.c: New test.
+
2016-04-28 Jakub Jelinek <jakub@redhat.com>
* gcc.target/i386/avx-vround-1.c: New test.
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-adde-int128.c b/gcc/testsuite/gcc.target/powerpc/vec-adde-int128.c
new file mode 100644
index 00000000000..f78622f11f2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-adde-int128.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target { powerpc64-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3" } */
+
+/* Test that the vec_adde builtin works as expected. */
+
+#include "altivec.h"
+
+#define N 4096
+
+void abort ();
+
+#define define_test_functions(STYPE, NAMESUFFIX) \
+\
+STYPE result_##NAMESUFFIX[N]; \
+STYPE addend1_##NAMESUFFIX[N]; \
+STYPE addend2_##NAMESUFFIX[N]; \
+STYPE carry_##NAMESUFFIX[N]; \
+STYPE expected_##NAMESUFFIX[N]; \
+\
+__attribute__((noinline)) void vector_tests_##NAMESUFFIX () \
+{ \
+ int i; \
+ vector STYPE v1, v2, v3, tmp; \
+ for (i = 0; i < N; i+=16/sizeof(STYPE)) { \
+ /* result=addend1+addend2+(carry & 0x1) */ \
+ v1 = (vector STYPE) { addend1_##NAMESUFFIX[i] }; \
+ v2 = (vector STYPE) { addend2_##NAMESUFFIX[i] }; \
+ v3 = (vector STYPE) { carry_##NAMESUFFIX[i] }; \
+\
+ tmp = vec_adde (v1, v2, v3); \
+ result_##NAMESUFFIX[i] = tmp[0]; \
+ } \
+} \
+\
+__attribute__((noinline)) void init_##NAMESUFFIX () \
+{ \
+ int i; \
+ for (i = 0; i < N; ++i) { \
+ result_##NAMESUFFIX[i] = 0; \
+ addend1_##NAMESUFFIX[i] = 1; \
+ addend2_##NAMESUFFIX[i] = 2; \
+ carry_##NAMESUFFIX[i] = (i%12); \
+ expected_##NAMESUFFIX[i] = addend1_##NAMESUFFIX[i] + \
+ addend2_##NAMESUFFIX[i] + (carry_##NAMESUFFIX[i] & 0x1); \
+ } \
+} \
+\
+__attribute__((noinline)) void verify_results_##NAMESUFFIX () \
+{ \
+ for (int i = 0; i < N; ++i) { \
+ if (result_##NAMESUFFIX[i] != expected_##NAMESUFFIX[i]) \
+ abort(); \
+ } \
+}
+
+
+#define execute_test_functions(STYPE, NAMESUFFIX) \
+{ \
+ init_##NAMESUFFIX (); \
+ vector_tests_##NAMESUFFIX (); \
+ verify_results_##NAMESUFFIX (); \
+}
+
+
+define_test_functions(signed __int128, si128);
+define_test_functions(unsigned __int128, ui128);
+
+int main ()
+{
+ execute_test_functions(signed __int128, si128);
+ execute_test_functions(unsigned __int128, ui128);
+
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-adde.c b/gcc/testsuite/gcc.target/powerpc/vec-adde.c
new file mode 100644
index 00000000000..b7d5b44b7a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-adde.c
@@ -0,0 +1,77 @@
+/* { dg-do run { target { powerpc64-*-* } } } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-mcpu=power8 -O3" } */
+
+/* Test that the vec_adde builtin works as expected. */
+
+#include "altivec.h"
+
+#define N 4096
+
+void abort ();
+
+#define define_test_functions(STYPE, NAMESUFFIX) \
+\
+STYPE result_##NAMESUFFIX[N]; \
+STYPE addend1_##NAMESUFFIX[N]; \
+STYPE addend2_##NAMESUFFIX[N]; \
+STYPE carry_##NAMESUFFIX[N]; \
+STYPE expected_##NAMESUFFIX[N]; \
+\
+__attribute__((noinline)) void vector_tests_##NAMESUFFIX () \
+{ \
+ int i; \
+ vector STYPE v1, v2, v3, tmp; \
+ for (i = 0; i < N; i+=16/sizeof(STYPE)) { \
+ /* result=addend1+addend2+(carry & 0x1) */ \
+ v1 = vec_vsx_ld (0, &addend1_##NAMESUFFIX[i]); \
+ v2 = vec_vsx_ld (0, &addend2_##NAMESUFFIX[i]); \
+ v3 = vec_vsx_ld (0, &carry_##NAMESUFFIX[i]); \
+\
+ tmp = vec_adde (v1, v2, v3); \
+ vec_vsx_st (tmp, 0, &result_##NAMESUFFIX[i]); \
+ } \
+} \
+\
+__attribute__((noinline)) void init_##NAMESUFFIX () \
+{ \
+ int i; \
+ for (i = 0; i < N; ++i) { \
+ result_##NAMESUFFIX[i] = 0; \
+ addend1_##NAMESUFFIX[i] = 1; \
+ addend2_##NAMESUFFIX[i] = 2; \
+ carry_##NAMESUFFIX[i] = (i%12); \
+ expected_##NAMESUFFIX[i] = addend1_##NAMESUFFIX[i] + \
+ addend2_##NAMESUFFIX[i] + (carry_##NAMESUFFIX[i] & 0x1); \
+ } \
+} \
+\
+__attribute__((noinline)) void verify_results_##NAMESUFFIX () \
+{ \
+ for (int i = 0; i < N; ++i) { \
+ if (result_##NAMESUFFIX[i] != expected_##NAMESUFFIX[i]) \
+ abort(); \
+ } \
+}
+
+
+#define execute_test_functions(STYPE, NAMESUFFIX) \
+{ \
+ init_##NAMESUFFIX (); \
+ vector_tests_##NAMESUFFIX (); \
+ verify_results_##NAMESUFFIX (); \
+}
+
+
+define_test_functions(signed int, si);
+define_test_functions(unsigned int, ui);
+
+int main ()
+{
+ execute_test_functions(signed int, si);
+ execute_test_functions(unsigned int, ui);
+
+ return 0;
+}
+
+