From: Stefan Schulze Frielinghaus <[email protected]>
So far only for scalars a zero test was simplified. Now, do the same
for vector types, too.
Also document that .CLZ/.CTZ has an optional second argument which
describes the at-zero value.
gcc/ChangeLog:
* doc/ifn.texi (IFN_CLZ): Document optional second argument.
(IFN_CTZ): Ditto.
* match.pd: Fold zero test for .CLZ/.CTZ over vector modes, too.
gcc/testsuite/ChangeLog:
* gcc.target/s390/clz-ctz-1.c: Adapt after zero tests are
folded, now.
---
gcc/doc/ifn.texi | 10 ++++--
gcc/match.pd | 18 +++++-----
gcc/testsuite/gcc.target/s390/clz-ctz-1.c | 43 +++++++----------------
3 files changed, 30 insertions(+), 41 deletions(-)
diff --git a/gcc/doc/ifn.texi b/gcc/doc/ifn.texi
index 7cfc80eecf2..d80e089685a 100644
--- a/gcc/doc/ifn.texi
+++ b/gcc/doc/ifn.texi
@@ -1088,12 +1088,18 @@ instruction pattern for integer and integer vector
modes.
@cindex @code{IFN_CLZ} internal function
@item @samp{IFN_CLZ}
The @code{IFN_CLZ} internal function directly maps to the @code{clz}
-instruction pattern for integer and integer vector modes.
+instruction pattern for integer and integer vector modes. In case the value
+for zero is defined, then this is recorded in the optional second argument.
+Note, this is always a scalar value even for vector modes where it represents
+the scalar value of a lane.
@cindex @code{IFN_CTZ} internal function
@item @samp{IFN_CTZ}
The @code{IFN_CTZ} internal function directly maps to the @code{ctz}
-instruction pattern for integer and integer vector modes.
+instruction pattern for integer and integer vector modes. In case the value
+for zero is defined, then this is recorded in the optional second argument.
+Note, this is always a scalar value even for vector modes where it represents
+the scalar value of a lane.
@cindex @code{IFN_FFS} internal function
@item @samp{IFN_FFS}
diff --git a/gcc/match.pd b/gcc/match.pd
index 648bda9bf11..297b24bda24 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -11779,8 +11779,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
}
(if (ifn == IFN_CLZ && wi::to_widest (@2) == val)
(IFN_CLZ @3 @2)))))
-(simplify
- (cond (ne @0 integer_zerop@1) (IFN_CLZ (convert?@3 @0) INTEGER_CST@2) @2)
+(for cnd (cond vec_cond)
+ (simplify
+ (cnd (ne @0 integer_zerop@1) (IFN_CLZ (convert?@3 @0) INTEGER_CST@2)
uniform_integer_cst_p@4)
(with { int val;
internal_fn ifn = IFN_LAST;
if (BITINT_TYPE_P (TREE_TYPE (@3)))
@@ -11789,8 +11790,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
OPTIMIZE_FOR_BOTH))
ifn = IFN_CLZ;
}
- (if (ifn == IFN_CLZ)
- (IFN_CLZ @3 @2))))
+ (if (ifn == IFN_CLZ && tree_int_cst_equal (@2, uniform_integer_cst_p (@4)))
+ (IFN_CLZ @3 @2)))))
/* a != 0 ? CTZ(a) : CST -> .CTZ(a) where CST is the result of the internal
function for 0. */
(for func (CTZ)
@@ -11818,8 +11819,9 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
}
(if (ifn == IFN_CTZ && wi::to_widest (@2) == val)
(IFN_CTZ @3 @2)))))
-(simplify
- (cond (ne @0 integer_zerop@1) (IFN_CTZ (convert?@3 @0) INTEGER_CST@2) @2)
+(for cnd (cond vec_cond)
+ (simplify
+ (cnd (ne @0 integer_zerop@1) (IFN_CTZ (convert?@3 @0) INTEGER_CST@2)
uniform_integer_cst_p@4)
(with { int val;
internal_fn ifn = IFN_LAST;
if (BITINT_TYPE_P (TREE_TYPE (@3)))
@@ -11828,8 +11830,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
OPTIMIZE_FOR_BOTH))
ifn = IFN_CTZ;
}
- (if (ifn == IFN_CTZ)
- (IFN_CTZ @3 @2))))
+ (if (ifn == IFN_CTZ && tree_int_cst_equal (@2, uniform_integer_cst_p (@4)))
+ (IFN_CTZ @3 @2)))))
#endif
/* Common POPCOUNT/PARITY simplifications. */
diff --git a/gcc/testsuite/gcc.target/s390/clz-ctz-1.c
b/gcc/testsuite/gcc.target/s390/clz-ctz-1.c
index 523c089755c..4e81b205d68 100644
--- a/gcc/testsuite/gcc.target/s390/clz-ctz-1.c
+++ b/gcc/testsuite/gcc.target/s390/clz-ctz-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
/* { dg-final { check-function-bodies "**" "" "" } } */
-/* { dg-final { scan-assembler-times {\n\tvzero\t} 9 } } */
+/* { dg-final { scan-assembler-times {\n\tvzero\t} 3 } } */
typedef unsigned char __attribute__ ((vector_size (16))) v16qi;
typedef unsigned short __attribute__ ((vector_size (16))) v8hi;
@@ -172,14 +172,9 @@ v16qi clzv16qi_z13 (v16qi x)
return x;
}
-/* TODO: fold zero test.
-
+/*
** clzgv16qi_z13:
-** vzero (%v[0-9]+)
-** vceqb (%v[0-9]+),%v24,\1
-** vgm (%v[0-9]+),4,4,0
** vclzb %v24,%v24
-** vsel %v24,\3,%v24,\2
** br %r14
*/
@@ -210,14 +205,9 @@ v8hi clzv8hi_z13 (v8hi x)
return x;
}
-/* TODO: fold zero test.
-
+/*
** clzgv8hi_z13:
-** vzero (%v[0-9]+)
-** vceqh (%v[0-9]+),%v24,\1
-** vgm (%v[0-9]+),11,11,1
** vclzh %v24,%v24
-** vsel %v24,\3,%v24,\2
** br %r14
*/
@@ -354,6 +344,12 @@ void ctzsi_z13_autovec (unsigned int *x)
}
/* TODO: fold zero test.
+ In contrast to ctzsi_z13_autovec, vect-pattern recognition fails because
+ type precision differs for lhs and promoted rhs. Consequently no ctz ifn is
+ constructed which is required by match.pd in order to fold a zero test.
+ Furthermore, in contrast to ctzdi_z17_autovec where phiopt2 already folds
+ the zero test since starting with z17 ctzdi2 becomes available and
+ vect-patterns recog never sees a zero test.
** ctzdi_z13_autovec:
** ...
@@ -409,14 +405,9 @@ void ctzti_z17_autovec (int *x, unsigned __int128 *y)
}
-/* TODO: fold zero test.
-
+/*
** ctzv16qi_z13:
-** vzero (%v[0-9]+)
-** vceqb (%v[0-9]+),%v24,\1
-** vgm (%v[0-9]+),4,4,0
** vctzb %v24,%v24
-** vsel %v24,\3,%v24,\2
** br %r14
*/
@@ -428,14 +419,9 @@ v16qi ctzv16qi_z13 (v16qi x)
return x;
}
-/* TODO: fold zero test.
-
+/*
** ctzv8hi_z13:
-** vzero (%v[0-9]+)
-** vceqh (%v[0-9]+),%v24,\1
-** vgm (%v[0-9]+),11,11,1
** vctzh %v24,%v24
-** vsel %v24,\3,%v24,\2
** br %r14
*/
@@ -447,14 +433,9 @@ v8hi ctzv8hi_z13 (v8hi x)
return x;
}
-/* TODO: fold zero test.
-
+/*
** ctzv4si_z13:
-** vzero (%v[0-9]+)
-** vceqf (%v[0-9]+),%v24,\1
-** vgm (%v[0-9]+),26,26,2
** vctzf %v24,%v24
-** vsel %v24,\3,%v24,\2
** br %r14
*/
--
2.55.0