This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix VEC_COND_EXPR expansion ICE (PR middle-end/91623)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Sun, 1 Sep 2019 12:19:51 +0200
- Subject: [PATCH] Fix VEC_COND_EXPR expansion ICE (PR middle-end/91623)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase ICEs, because for SSE4.1 only VEC_COND_EXPRs with
EQ_EXPR/NE_EXPR are supported and vectorizer generates such VEC_COND_EXPR,
but later on the condition is folded into a VECTOR_CST and the VEC_COND_EXPR
expansion code expands non-comparison conditions as LT_EXPR against zero
vector.
I think the only problematic case is when the equality comparison is folded
into a constant; at that point, if both other VEC_COND_EXPR arguments are
constant, we could in theory fold it (but can't really rely on it during
expansion anyway), but if they aren't constant, just the condition is, there
is nothing to fold it into anyway. The patch verifies that LT_EXPR against
zero will behave the same as NE_EXPR by punting if there are non-canonical
elements (> 0), otherwise just tries to expand it as NE_EXPR if LT_EXPR
didn't work.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2019-09-01 Jakub Jelinek <jakub@redhat.com>
PR middle-end/91623
* optabs.c (expand_vec_cond_expr): If op0 is a VECTOR_CST and only
EQ_EXPR/NE_EXPR is supported, verify that op0 only contains
zeros or negative elements and use NE_EXPR instead of LT_EXPR against
zero vector.
* gcc.target/i386/pr91623.c: New test.
--- gcc/optabs.c.jj 2019-08-27 12:26:37.392912813 +0200
+++ gcc/optabs.c 2019-08-31 19:49:32.831430056 +0200
@@ -5868,6 +5868,25 @@ expand_vec_cond_expr (tree vec_cond_type
icode = get_vcond_icode (mode, cmp_op_mode, unsignedp);
if (icode == CODE_FOR_nothing)
{
+ if (tcode == LT_EXPR
+ && op0a == op0
+ && TREE_CODE (op0) == VECTOR_CST)
+ {
+ /* A VEC_COND_EXPR condition could be folded from EQ_EXPR/NE_EXPR
+ into a constant when only get_vcond_eq_icode is supported.
+ Verify < 0 and != 0 behave the same and change it to NE_EXPR. */
+ unsigned HOST_WIDE_INT nelts;
+ if (!VECTOR_CST_NELTS (op0).is_constant (&nelts))
+ {
+ if (VECTOR_CST_STEPPED_P (op0))
+ return 0;
+ nelts = vector_cst_encoded_nelts (op0);
+ }
+ for (unsigned int i = 0; i < nelts; ++i)
+ if (tree_int_cst_sgn (vector_cst_elt (op0, i)) == 1)
+ return 0;
+ tcode = NE_EXPR;
+ }
if (tcode == EQ_EXPR || tcode == NE_EXPR)
icode = get_vcond_eq_icode (mode, cmp_op_mode);
if (icode == CODE_FOR_nothing)
--- gcc/testsuite/gcc.target/i386/pr91623.c.jj 2019-08-31 19:55:02.470674149 +0200
+++ gcc/testsuite/gcc.target/i386/pr91623.c 2019-08-31 19:54:39.186010098 +0200
@@ -0,0 +1,32 @@
+/* PR middle-end/91623 */
+/* { dg-do compile } */
+/* { dg-options "-O3 -msse4.1 -mno-sse4.2" } */
+
+typedef long long V __attribute__((__vector_size__(16)));
+V e, h;
+int d;
+const int i;
+
+void foo (void);
+
+void
+bar (int k, int l)
+{
+ if (d && 0 <= k - 1 && l)
+ foo ();
+}
+
+void
+baz (void)
+{
+ V n = (V) { 1 };
+ V g = (V) {};
+ V o = g;
+ for (int f = 0; f < i; ++f)
+ {
+ V a = o == n;
+ h = a;
+ bar (f, i);
+ o = e;
+ }
+}
Jakub