[vect] : when REALPART/IMAGPART also check their def stmts [PR126593]

Message ID patch-20769-rb-rev-unknown-tamar@arm.com
State New
Headers
Series [vect] : when REALPART/IMAGPART also check their def stmts [PR126593] |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-arm-bootstrap success Build passed
linaro-tcwg-bot/tcwg_simplebootstrap_build--master-aarch64-bootstrap fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-arm fail Patch failed to apply
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 fail Patch failed to apply

Commit Message

Tamar Christina Aug. 4, 2026, 12:22 p.m. UTC
  The check in compatible_complex_nodes_p is a bit too loose in that we assumed
that when we see a REAL/IMAG pair of statement in a TWO_OPERANDS they must have
come from the same defining statement. 

This is of course too loose and the operands should be checked explicitly.

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

Pushed.

Thanks,
Tamar

gcc/ChangeLog:

	PR tree-optimization/126593
	* tree-vect-slp-patterns.cc (compatible_complex_nodes_p): Check def
	stmts of real and imag pairs.

gcc/testsuite/ChangeLog:

	PR tree-optimization/126593
	* gcc.target/aarch64/pr126593.c: New test.

---


--
  

Comments

Richard Biener Aug. 4, 2026, 12:48 p.m. UTC | #1
On Tue, 4 Aug 2026, Tamar Christina wrote:

> The check in compatible_complex_nodes_p is a bit too loose in that we assumed
> that when we see a REAL/IMAG pair of statement in a TWO_OPERANDS they must have
> come from the same defining statement. 
> 
> This is of course too loose and the operands should be checked explicitly.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu,
> arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
> -m32, -m64 and no issues.
> 
> Pushed.
> 
> Thanks,
> Tamar
> 
> gcc/ChangeLog:
> 
> 	PR tree-optimization/126593
> 	* tree-vect-slp-patterns.cc (compatible_complex_nodes_p): Check def
> 	stmts of real and imag pairs.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/126593
> 	* gcc.target/aarch64/pr126593.c: New test.
> 
> ---
> diff --git a/gcc/testsuite/gcc.target/aarch64/pr126593.c b/gcc/testsuite/gcc.target/aarch64/pr126593.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..fce64d4d3393dc8456f37c5d7ecdc10d9fd23a04
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/pr126593.c
> @@ -0,0 +1,37 @@
> +/* { dg-do run { target arm_v8_3a_complex_neon_hw } } */
> +/* { dg-require-effective-target aarch64_little_endian } */
> +/* { dg-options "-O3 -march=armv8.3-a -ffast-math" } */
> +
> +#define N 64
> +_Complex float a[N], b[N], d[N], c[N];
> +
> +__attribute__((noipa))
> +void
> +mix (int n)
> +{
> +  for (int i = 0; i < n; i++)
> +    {
> +      __real__ c[i] = __real__ a[i] * __real__ b[i] - __imag__ a[i] * __imag__ d[i];
> +      __imag__ c[i] = __real__ a[i] * __imag__ b[i] + __imag__ a[i] * __real__ d[i];
> +    }
> +}
> +
> +int
> +main (void)
> +{
> +  for (int i = 0; i < N; i++)
> +    {
> +      a[i] = 1.0f + 2.0fi;
> +      b[i] = 3.0f + 4.0fi;
> +      d[i] = 5.0f + 6.0fi;
> +    }
> +
> +  mix (N);
> +
> +  /* scalar: re = 1*3 - 2*6 = -9, im = 1*4 + 2*5 = 14.
> +     vectorized as a*b: re = -5, im = 10.  */
> +  if (__real__ c[0] != -9.0f || __imag__ c[0] != 14.0f)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
> diff --git a/gcc/tree-vect-slp-patterns.cc b/gcc/tree-vect-slp-patterns.cc
> index 3e2c0fe2c099348e055c2e08a7d899c9cbf71d49..2136329645cad8f26f672ac5ad7d7f225bb08b7f 100644
> --- a/gcc/tree-vect-slp-patterns.cc
> +++ b/gcc/tree-vect-slp-patterns.cc
> @@ -801,7 +801,10 @@ compatible_complex_nodes_p (slp_compat_nodes_map_t *compat_cache,
>        tree_code acode = gimple_assign_rhs_code (a_stmt);
>        tree_code bcode = gimple_assign_rhs_code (b_stmt);
>        if ((acode == REALPART_EXPR || acode == IMAGPART_EXPR)
> -	  && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR))
> +	  && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR)
> +	  && operand_equal_p (TREE_OPERAND (gimple_assign_rhs1 (a_stmt), 0),
> +			      TREE_OPERAND (gimple_assign_rhs1 (b_stmt), 0),
> +			      0))

Minor nit - you cal elide the last 0 argument to operand_equal_p.

OK.

Thanks,
Richard.

>  	return true;
>  
>        if (acode != bcode)
> 
> 
>
  

Patch

diff --git a/gcc/testsuite/gcc.target/aarch64/pr126593.c b/gcc/testsuite/gcc.target/aarch64/pr126593.c
new file mode 100644
index 0000000000000000000000000000000000000000..fce64d4d3393dc8456f37c5d7ecdc10d9fd23a04
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr126593.c
@@ -0,0 +1,37 @@ 
+/* { dg-do run { target arm_v8_3a_complex_neon_hw } } */
+/* { dg-require-effective-target aarch64_little_endian } */
+/* { dg-options "-O3 -march=armv8.3-a -ffast-math" } */
+
+#define N 64
+_Complex float a[N], b[N], d[N], c[N];
+
+__attribute__((noipa))
+void
+mix (int n)
+{
+  for (int i = 0; i < n; i++)
+    {
+      __real__ c[i] = __real__ a[i] * __real__ b[i] - __imag__ a[i] * __imag__ d[i];
+      __imag__ c[i] = __real__ a[i] * __imag__ b[i] + __imag__ a[i] * __real__ d[i];
+    }
+}
+
+int
+main (void)
+{
+  for (int i = 0; i < N; i++)
+    {
+      a[i] = 1.0f + 2.0fi;
+      b[i] = 3.0f + 4.0fi;
+      d[i] = 5.0f + 6.0fi;
+    }
+
+  mix (N);
+
+  /* scalar: re = 1*3 - 2*6 = -9, im = 1*4 + 2*5 = 14.
+     vectorized as a*b: re = -5, im = 10.  */
+  if (__real__ c[0] != -9.0f || __imag__ c[0] != 14.0f)
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/tree-vect-slp-patterns.cc b/gcc/tree-vect-slp-patterns.cc
index 3e2c0fe2c099348e055c2e08a7d899c9cbf71d49..2136329645cad8f26f672ac5ad7d7f225bb08b7f 100644
--- a/gcc/tree-vect-slp-patterns.cc
+++ b/gcc/tree-vect-slp-patterns.cc
@@ -801,7 +801,10 @@  compatible_complex_nodes_p (slp_compat_nodes_map_t *compat_cache,
       tree_code acode = gimple_assign_rhs_code (a_stmt);
       tree_code bcode = gimple_assign_rhs_code (b_stmt);
       if ((acode == REALPART_EXPR || acode == IMAGPART_EXPR)
-	  && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR))
+	  && (bcode == REALPART_EXPR || bcode == IMAGPART_EXPR)
+	  && operand_equal_p (TREE_OPERAND (gimple_assign_rhs1 (a_stmt), 0),
+			      TREE_OPERAND (gimple_assign_rhs1 (b_stmt), 0),
+			      0))
 	return true;
 
       if (acode != bcode)