aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2023-08-09 11:30:48 -0400
committerCarl Love <cel@us.ibm.com>2023-08-09 11:30:48 -0400
commit29e2bc5f9ab70c653c7190c3a5b9e94f10909b44 (patch)
tree2b12b57b7fc8ac5e8daf993175d327a1b0c0fd83
parentb3a2b307b9deea719fb725a86df43b82176fe459 (diff)
downloadgcc-29e2bc5f9ab70c653c7190c3a5b9e94f10909b44.zip
gcc-29e2bc5f9ab70c653c7190c3a5b9e94f10909b44.tar.gz
gcc-29e2bc5f9ab70c653c7190c3a5b9e94f10909b44.tar.bz2
rs6000: Fix __builtin_altivec_vcmpne{b,h,w} implementation
The current built-in definitions for vcmpneb, vcmpneh, vcmpnew are defined under the Power 9 section of r66000-builtins. This implies they are only supported on Power 9 and above when in fact they are defined and work with Altivec as well with the appropriate Altivec instruction generation. The vec_cmpne builtin should generate the vcmpequ{b,h,w} instruction with Altivec enabled and generate the vcmpne{b,h,w} on Power 9 and newer processors. This patch moves the definitions to the Altivec stanza to make it clear the built-ins are supported for all Altivec processors. The patch removes the confusion as to which processors support the vcmpequ{b,h,w} instructions. There is existing test coverage for the vec_cmpne built-in for vector bool char, vector bool short, vector bool int, vector bool long long in builtins-3-p9.c and p8vector-builtin-2.c. Coverage for vector signed int, vector unsigned int is in p8vector-builtin-2.c. Test vec-cmpne.c is updated to check the generation of the vcmpequ{b,h,w} instructions for Altivec. A new test vec-cmpne-runnable.c is added to verify the built-ins work as expected. Patch has been tested on Power 8 LE/BE, Power 9 LE/BE and Power 10 LE with no regressions. gcc/ChangeLog: * config/rs6000/rs6000-builtins.def (vcmpneb, vcmpneh, vcmpnew): Move definitions to Altivec stanza. * config/rs6000/altivec.md (vcmpneb, vcmpneh, vcmpnew): New define_expand. gcc/testsuite/ChangeLog: * gcc.target/powerpc/vec-cmpne-runnable.c: New execution test. * gcc.target/powerpc/vec-cmpne.c (define_test_functions, execute_test_functions): Move to vec-cmpne.h. Add scan-assembler-times for vcmpequb, vcmpequh, vcmpequw. * gcc.target/powerpc/vec-cmpne.h: New include file for vec-cmpne.c and vec-cmpne-runnable.c. Split define_test_functions definition into define_test_functions and define_init_verify_functions.
-rw-r--r--gcc/config/rs6000/altivec.md12
-rw-r--r--gcc/config/rs6000/rs6000-builtins.def18
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cmpne-runnable.c36
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cmpne.c112
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vec-cmpne.h90
5 files changed, 156 insertions, 112 deletions
diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md
index 70db5cf..e8a596f 100644
--- a/gcc/config/rs6000/altivec.md
+++ b/gcc/config/rs6000/altivec.md
@@ -2631,6 +2631,18 @@
"vcmpequq. %0,%1,%2"
[(set_attr "type" "veccmpfx")])
+;; Expand for builtin vcmpne{b,h,w}
+(define_expand "altivec_vcmpne_<mode>"
+ [(set (match_operand:VSX_EXTRACT_I 3 "altivec_register_operand" "=v")
+ (eq:VSX_EXTRACT_I (match_operand:VSX_EXTRACT_I 1 "altivec_register_operand" "v")
+ (match_operand:VSX_EXTRACT_I 2 "altivec_register_operand" "v")))
+ (set (match_operand:VSX_EXTRACT_I 0 "altivec_register_operand" "=v")
+ (not:VSX_EXTRACT_I (match_dup 3)))]
+ "TARGET_ALTIVEC"
+ {
+ operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
+ })
+
(define_insn "*altivec_vcmpgts<VI_char>_p"
[(set (reg:CC CR6_REGNO)
(unspec:CC [(gt:CC (match_operand:VI2 1 "register_operand" "v")
diff --git a/gcc/config/rs6000/rs6000-builtins.def b/gcc/config/rs6000/rs6000-builtins.def
index 35c4cdf..8a294d6 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -641,6 +641,15 @@
const int __builtin_altivec_vcmpgtuw_p (int, vsi, vsi);
VCMPGTUW_P vector_gtu_v4si_p {pred}
+ const vsc __builtin_altivec_vcmpneb (vsc, vsc);
+ VCMPNEB altivec_vcmpne_v16qi {}
+
+ const vss __builtin_altivec_vcmpneh (vss, vss);
+ VCMPNEH altivec_vcmpne_v8hi {}
+
+ const vsi __builtin_altivec_vcmpnew (vsi, vsi);
+ VCMPNEW altivec_vcmpne_v4si {}
+
const vsi __builtin_altivec_vctsxs (vf, const int<5>);
VCTSXS altivec_vctsxs {}
@@ -2599,9 +2608,6 @@
const signed int __builtin_altivec_vcmpaew_p (vsi, vsi);
VCMPAEW_P vector_ae_v4si_p {}
- const vsc __builtin_altivec_vcmpneb (vsc, vsc);
- VCMPNEB vcmpneb {}
-
const signed int __builtin_altivec_vcmpneb_p (vsc, vsc);
VCMPNEB_P vector_ne_v16qi_p {}
@@ -2614,15 +2620,9 @@
const signed int __builtin_altivec_vcmpnefp_p (vf, vf);
VCMPNEFP_P vector_ne_v4sf_p {}
- const vss __builtin_altivec_vcmpneh (vss, vss);
- VCMPNEH vcmpneh {}
-
const signed int __builtin_altivec_vcmpneh_p (vss, vss);
VCMPNEH_P vector_ne_v8hi_p {}
- const vsi __builtin_altivec_vcmpnew (vsi, vsi);
- VCMPNEW vcmpnew {}
-
const signed int __builtin_altivec_vcmpnew_p (vsi, vsi);
VCMPNEW_P vector_ne_v4si_p {}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cmpne-runnable.c b/gcc/testsuite/gcc.target/powerpc/vec-cmpne-runnable.c
new file mode 100644
index 0000000..c7fff12
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cmpne-runnable.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vmx_hw } */
+/* { dg-options "-maltivec -O2 " } */
+
+/* Test that the vec_cmpne builtin works as expected. */
+
+#include "vec-cmpne.h"
+
+define_test_functions (int, signed int, signed int, si);
+define_test_functions (int, unsigned int, unsigned int, ui);
+define_test_functions (short, signed short, signed short, ss);
+define_test_functions (short, unsigned short, unsigned short, us);
+define_test_functions (char, signed char, signed char, sc);
+define_test_functions (char, unsigned char, unsigned char, uc);
+define_test_functions (int, signed int, float, ff);
+
+define_init_verify_functions (int, signed int, signed int, si);
+define_init_verify_functions (int, unsigned int, unsigned int, ui);
+define_init_verify_functions (short, signed short, signed short, ss);
+define_init_verify_functions (short, unsigned short, unsigned short, us);
+define_init_verify_functions (char, signed char, signed char, sc);
+define_init_verify_functions (char, unsigned char, unsigned char, uc);
+define_init_verify_functions (int, signed int, float, ff);
+
+int main ()
+{
+ execute_test_functions (int, signed int, signed int, si);
+ execute_test_functions (int, unsigned int, unsigned int, ui);
+ execute_test_functions (short, signed short, signed short, ss);
+ execute_test_functions (short, unsigned short, unsigned short, us);
+ execute_test_functions (char, signed char, signed char, sc);
+ execute_test_functions (char, unsigned char, unsigned char, uc);
+ execute_test_functions (int, signed int, float, ff);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cmpne.c b/gcc/testsuite/gcc.target/powerpc/vec-cmpne.c
index edba9de..b57e0ac8 100644
--- a/gcc/testsuite/gcc.target/powerpc/vec-cmpne.c
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cmpne.c
@@ -1,94 +1,11 @@
-/* { dg-do run } */
-/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-mvsx -O3" } */
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -O2" } */
-/* Test that the vec_cmpne builtin works as expected. */
-
-#include "altivec.h"
-
-#define N 4096
-
-void abort ();
-
-#define define_test_functions(VBTYPE, RTYPE, STYPE, NAME) \
-\
-RTYPE result_ne_##NAME[N] __attribute__((aligned(16))); \
-RTYPE result_eq_##NAME[N] __attribute__((aligned(16))); \
-STYPE operand1_##NAME[N] __attribute__((aligned(16))); \
-STYPE operand2_##NAME[N] __attribute__((aligned(16))); \
-RTYPE expected_##NAME[N] __attribute__((aligned(16))); \
-\
-__attribute__((noinline)) void vector_tests_##NAME () \
-{ \
- vector STYPE v1_##NAME, v2_##NAME; \
- vector bool VBTYPE tmp_##NAME; \
- int i; \
- for (i = 0; i < N; i+=16/sizeof (STYPE)) \
- { \
- /* result_ne = operand1!=operand2. */ \
- v1_##NAME = vec_vsx_ld (0, (const vector STYPE*)&operand1_##NAME[i]); \
- v2_##NAME = vec_vsx_ld (0, (const vector STYPE*)&operand2_##NAME[i]); \
-\
- tmp_##NAME = vec_cmpeq (v1_##NAME, v2_##NAME); \
- vec_vsx_st (tmp_##NAME, 0, &result_eq_##NAME[i]); \
-\
- tmp_##NAME = vec_cmpne (v1_##NAME, v2_##NAME); \
- vec_vsx_st (tmp_##NAME, 0, &result_ne_##NAME[i]); \
- } \
-} \
-\
-__attribute__((noinline)) void init_##NAME () \
-{ \
- int i; \
- for (i = 0; i < N; ++i) \
- { \
- result_ne_##NAME[i] = 7; \
- result_eq_##NAME[i] = 15; \
- if (i%3 == 0) \
- { \
- /* op1 < op2. */ \
- operand1_##NAME[i] = 1; \
- operand2_##NAME[i] = 2; \
- } \
- else if (i%3 == 1) \
- { \
- /* op1 > op2. */ \
- operand1_##NAME[i] = 2; \
- operand2_##NAME[i] = 1; \
- } \
- else if (i%3 == 2) \
- { \
- /* op1 == op2. */ \
- operand1_##NAME[i] = 3; \
- operand2_##NAME[i] = 3; \
- } \
- /* For vector comparisons: "For each element of the result_ne, the \
- value of each bit is 1 if the corresponding elements of ARG1 and \
- ARG2 are equal." {or whatever the comparison is} "Otherwise, the \
- value of each bit is 0." */ \
- expected_##NAME[i] = -1 * (RTYPE)(operand1_##NAME[i] != operand2_##NAME[i]); \
- } \
-} \
-\
-__attribute__((noinline)) void verify_results_##NAME () \
-{ \
- int i; \
- for (i = 0; i < N; ++i) \
- { \
- if ( ((result_ne_##NAME[i] != expected_##NAME[i]) || \
- (result_ne_##NAME[i] == result_eq_##NAME[i]))) \
- abort (); \
- } \
-}
-
-
-#define execute_test_functions(VBTYPE, RTYPE, STYPE, NAME) \
-{ \
- init_##NAME (); \
- vector_tests_##NAME (); \
- verify_results_##NAME (); \
-}
+/* Test that the vec_cmpne builtin generates the expected Altivec
+ instructions. */
+#include "vec-cmpne.h"
define_test_functions (int, signed int, signed int, si);
define_test_functions (int, unsigned int, unsigned int, ui);
@@ -98,17 +15,6 @@ define_test_functions (char, signed char, signed char, sc);
define_test_functions (char, unsigned char, unsigned char, uc);
define_test_functions (int, signed int, float, ff);
-int main ()
-{
- execute_test_functions (int, signed int, signed int, si);
- execute_test_functions (int, unsigned int, unsigned int, ui);
- execute_test_functions (short, signed short, signed short, ss);
- execute_test_functions (short, unsigned short, unsigned short, us);
- execute_test_functions (char, signed char, signed char, sc);
- execute_test_functions (char, unsigned char, unsigned char, uc);
- execute_test_functions (int, signed int, float, ff);
-
- return 0;
-}
-
-
+/* { dg-final { scan-assembler-times {\mvcmpequb\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequh\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mvcmpequw\M} 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vec-cmpne.h b/gcc/testsuite/gcc.target/powerpc/vec-cmpne.h
new file mode 100644
index 0000000..a304de0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vec-cmpne.h
@@ -0,0 +1,90 @@
+#include "altivec.h"
+
+#define N 4096
+
+void abort ();
+
+#define PRAGMA(X) _Pragma (#X)
+#define UNROLL0 PRAGMA (GCC unroll 0)
+
+#define define_test_functions(VBTYPE, RTYPE, STYPE, NAME) \
+\
+RTYPE result_ne_##NAME[N] __attribute__((aligned(16))); \
+RTYPE result_eq_##NAME[N] __attribute__((aligned(16))); \
+STYPE operand1_##NAME[N] __attribute__((aligned(16))); \
+STYPE operand2_##NAME[N] __attribute__((aligned(16))); \
+RTYPE expected_##NAME[N] __attribute__((aligned(16))); \
+\
+__attribute__((noinline)) void vector_tests_##NAME () \
+{ \
+ vector STYPE v1_##NAME, v2_##NAME; \
+ vector bool VBTYPE tmp_##NAME; \
+ int i; \
+ UNROLL0 \
+ for (i = 0; i < N; i+=16/sizeof (STYPE)) \
+ { \
+ /* result_ne = operand1!=operand2. */ \
+ v1_##NAME = vec_vsx_ld (0, (const vector STYPE*)&operand1_##NAME[i]); \
+ v2_##NAME = vec_vsx_ld (0, (const vector STYPE*)&operand2_##NAME[i]); \
+\
+ tmp_##NAME = vec_cmpeq (v1_##NAME, v2_##NAME); \
+ vec_vsx_st (tmp_##NAME, 0, &result_eq_##NAME[i]); \
+\
+ tmp_##NAME = vec_cmpne (v1_##NAME, v2_##NAME); \
+ vec_vsx_st (tmp_##NAME, 0, &result_ne_##NAME[i]); \
+ } \
+} \
+
+#define define_init_verify_functions(VBTYPE, RTYPE, STYPE, NAME) \
+__attribute__((noinline)) void init_##NAME () \
+{ \
+ int i; \
+ for (i = 0; i < N; ++i) \
+ { \
+ result_ne_##NAME[i] = 7; \
+ result_eq_##NAME[i] = 15; \
+ if (i%3 == 0) \
+ { \
+ /* op1 < op2. */ \
+ operand1_##NAME[i] = 1; \
+ operand2_##NAME[i] = 2; \
+ } \
+ else if (i%3 == 1) \
+ { \
+ /* op1 > op2. */ \
+ operand1_##NAME[i] = 2; \
+ operand2_##NAME[i] = 1; \
+ } \
+ else if (i%3 == 2) \
+ { \
+ /* op1 == op2. */ \
+ operand1_##NAME[i] = 3; \
+ operand2_##NAME[i] = 3; \
+ } \
+ /* For vector comparisons: "For each element of the result_ne, the \
+ value of each bit is 1 if the corresponding elements of ARG1 and \
+ ARG2 are equal." {or whatever the comparison is} "Otherwise, the \
+ value of each bit is 0." */ \
+ expected_##NAME[i] = -1 * (RTYPE)(operand1_##NAME[i] != operand2_##NAME[i]); \
+ } \
+} \
+\
+__attribute__((noinline)) void verify_results_##NAME () \
+{ \
+ int i; \
+ for (i = 0; i < N; ++i) \
+ { \
+ if ( ((result_ne_##NAME[i] != expected_##NAME[i]) || \
+ (result_ne_##NAME[i] == result_eq_##NAME[i]))) \
+ abort (); \
+ } \
+}
+
+
+#define execute_test_functions(VBTYPE, RTYPE, STYPE, NAME) \
+{ \
+ init_##NAME (); \
+ vector_tests_##NAME (); \
+ verify_results_##NAME (); \
+}
+