[llvm] [ComplexDeinterleaving] Add missing negated fcmla matches (PR #217901)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 21 05:30:08 PDT 2026
https://github.com/matteo-rm created https://github.com/llvm/llvm-project/pull/217901
`identifyNodeWithImplicitAdd` currently only matches float Neg ops for 1 out of 4 possible angles, thus missing potential fcmla matches. This PR fixes it by using the already present `isNeg` util for all 4 cases. This also makes the checks more consistent.
Followup of #217650
>From 8654a1984505b005d13a82a4b92e7d3633035f24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Matt=C3=A9o=20Rizza=20Murgier?=
<matteo.rizza-murgier at sipearl.com>
Date: Fri, 21 Aug 2026 08:58:12 +0200
Subject: [PATCH] [ComplexDeinterleaving] Add missing negated fcmla matches
---
.../lib/CodeGen/ComplexDeinterleavingPass.cpp | 13 ++++-----
.../complex-deinterleaving-negation.ll | 28 +++++++++++++++++++
2 files changed, 34 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
index b02987dec3776..38e1043aa9614 100644
--- a/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
+++ b/llvm/lib/CodeGen/ComplexDeinterleavingPass.cpp
@@ -656,23 +656,22 @@ ComplexDeinterleavingGraph::identifyNodeWithImplicitAdd(
// A +/+ has a rotation of 0. If any of the operands are fneg, we flip the
// rotations and use the operand.
unsigned Negs = 0;
- Value *Op;
- if (match(R0, m_Neg(m_Value(Op)))) {
+ if (isNeg(R0)) {
Negs |= 1;
- R0 = Op;
- } else if (match(R1, m_Neg(m_Value(Op)))) {
+ R0 = getNegOperand(R0);
+ } else if (isNeg(R1)) {
Negs |= 1;
- R1 = Op;
+ R1 = getNegOperand(R1);
}
if (isNeg(I0)) {
Negs |= 2;
Negs ^= 1;
I0 = getNegOperand(I0);
- } else if (match(I1, m_Neg(m_Value(Op)))) {
+ } else if (isNeg(I1)) {
Negs |= 2;
Negs ^= 1;
- I1 = Op;
+ I1 = getNegOperand(I1);
}
ComplexDeinterleavingRotation Rotation = (ComplexDeinterleavingRotation)Negs;
diff --git a/llvm/test/CodeGen/AArch64/complex-deinterleaving-negation.ll b/llvm/test/CodeGen/AArch64/complex-deinterleaving-negation.ll
index f590805fd9ed5..c635f9d59c4e2 100644
--- a/llvm/test/CodeGen/AArch64/complex-deinterleaving-negation.ll
+++ b/llvm/test/CodeGen/AArch64/complex-deinterleaving-negation.ll
@@ -32,3 +32,31 @@ entry:
%interleaved = shufflevector <2 x double> %real, <2 x double> %imag, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
ret <4 x double> %interleaved
}
+
+define <4 x double> @complex_mul_negated_real_operand(<4 x double> %a, <4 x double> %b) {
+; CHECK-LABEL: complex_mul_negated_real_operand:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: movi v4.2d, #0000000000000000
+; CHECK-NEXT: movi v5.2d, #0000000000000000
+; CHECK-NEXT: fcmla v5.2d, v2.2d, v0.2d, #90
+; CHECK-NEXT: fcmla v4.2d, v3.2d, v1.2d, #90
+; CHECK-NEXT: fcmla v5.2d, v2.2d, v0.2d, #0
+; CHECK-NEXT: fcmla v4.2d, v3.2d, v1.2d, #0
+; CHECK-NEXT: mov v0.16b, v5.16b
+; CHECK-NEXT: mov v1.16b, v4.16b
+; CHECK-NEXT: ret
+entry:
+ %a.real = shufflevector <4 x double> %a, <4 x double> poison, <2 x i32> <i32 0, i32 2>
+ %a.imag = shufflevector <4 x double> %a, <4 x double> poison, <2 x i32> <i32 1, i32 3>
+ %b.real = shufflevector <4 x double> %b, <4 x double> poison, <2 x i32> <i32 0, i32 2>
+ %b.imag = shufflevector <4 x double> %b, <4 x double> poison, <2 x i32> <i32 1, i32 3>
+ %neg.a.imag = fneg contract <2 x double> %a.imag
+ %real.0 = fmul contract <2 x double> %neg.a.imag, %b.imag
+ %real.1 = fmul contract <2 x double> %a.real, %b.real
+ %real = fadd contract <2 x double> %real.0, %real.1
+ %imag.0 = fmul contract <2 x double> %a.real, %b.imag
+ %imag.1 = fmul contract <2 x double> %a.imag, %b.real
+ %imag = fadd contract <2 x double> %imag.0, %imag.1
+ %interleaved = shufflevector <2 x double> %real, <2 x double> %imag, <4 x i32> <i32 0, i32 2, i32 1, i32 3>
+ ret <4 x double> %interleaved
+}
More information about the llvm-commits
mailing list