[llvm] [AArch64][GlobalISel] Reassociate add sub mul. (PR #180753)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 10 07:21:48 PST 2026
https://github.com/davemgreen created https://github.com/llvm/llvm-project/pull/180753
This is a port of performSubAddMULCombine from D143143. The mid end will reassociate sub(sub(x, m1), m2) to sub(x, add(m1, m2)). This reassociates it back to allow the creation of more mls instructions.
>From e4cd8b65c70f32dd1721412e2e4073d0d540a547 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Tue, 10 Feb 2026 15:17:36 +0000
Subject: [PATCH] [AArch64][GlobalISel] Reassociate add sub mul.
This is a port of performSubAddMULCombine from D143143. The mid end will
reassociate sub(sub(x, m1), m2) to sub(x, add(m1, m2)). This reassociates it
back to allow the creation of more mls instructions.
---
llvm/lib/Target/AArch64/AArch64Combine.td | 13 +-
.../GISel/AArch64PostLegalizerCombiner.cpp | 34 ++++
llvm/test/CodeGen/AArch64/aarch64-smull.ll | 52 +++---
llvm/test/CodeGen/AArch64/reassocmls.ll | 159 ++++++------------
4 files changed, 117 insertions(+), 141 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td
index 278314792bfb9..6ddeb37f642f0 100644
--- a/llvm/lib/Target/AArch64/AArch64Combine.td
+++ b/llvm/lib/Target/AArch64/AArch64Combine.td
@@ -242,6 +242,16 @@ def extmultomull : GICombineRule<
(apply [{ applyExtMulToMULL(*${root}, MRI, B, Observer, ${matchinfo}); }])
>;
+// The mid end will reassociate sub(sub(x, m1), m2) to sub(x, add(m1, m2))
+// This reassociates it back to allow the creation of more mls instructions.
+def subaddmulreassoc : GICombineRule<
+ (defs root:$dst),
+ (match (G_ADD $tmp, $src1, $src2):$sub,
+ (G_SUB $dst, $src3, $tmp):$root,
+ [{ return matchSubAddMulReassoc(${src1}.getReg(), ${src2}.getReg(),
+ ${tmp}.getReg(), ${src3}.getReg(), MRI); }]),
+ (apply [{ applySubAddMulReassoc(*${root}, *${sub}, MRI, B, Observer); }])>;
+
def lower_mulv2s64 : GICombineRule<
(defs root:$root),
(match (G_MUL $dst, $src1, $src2):$root,
@@ -367,6 +377,7 @@ def AArch64PostLegalizerCombiner
commute_constant_to_rhs, extract_vec_elt_combines,
push_freeze_to_prevent_poison_from_propagating,
combine_mul_cmlt, combine_use_vector_truncate,
- extmultomull, truncsat_combines, lshr_of_trunc_of_lshr,
+ extmultomull, subaddmulreassoc, truncsat_combines,
+ lshr_of_trunc_of_lshr,
funnel_shift_from_or_shift_constants_are_legal]> {
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index fa7bb6ecc35ee..1502a3c871571 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -554,6 +554,40 @@ void applyExtMulToMULL(MachineInstr &MI, MachineRegisterInfo &MRI,
MI.eraseFromParent();
}
+static bool matchSubAddMulReassoc(Register Mul1, Register Mul2, Register Sub,
+ Register Src, MachineRegisterInfo &MRI) {
+ if (!MRI.hasOneUse(Sub))
+ return false;
+ if (getIConstantVRegValWithLookThrough(Src, MRI))
+ return false;
+ MachineInstr *M1 = getDefIgnoringCopies(Mul1, MRI);
+ if (M1->getOpcode() != AArch64::G_MUL &&
+ M1->getOpcode() != AArch64::G_SMULL &&
+ M1->getOpcode() != AArch64::G_UMULL)
+ return false;
+ MachineInstr *M2 = getDefIgnoringCopies(Mul2, MRI);
+ if (M2->getOpcode() != AArch64::G_MUL &&
+ M2->getOpcode() != AArch64::G_SMULL &&
+ M2->getOpcode() != AArch64::G_UMULL)
+ return false;
+ return true;
+}
+
+static void applySubAddMulReassoc(MachineInstr &MI, MachineInstr &Sub,
+ MachineRegisterInfo &MRI, MachineIRBuilder &B,
+ GISelChangeObserver &Observer) {
+ Register Src = MI.getOperand(1).getReg();
+ Register Tmp = MI.getOperand(2).getReg();
+ Register Mul1 = Sub.getOperand(1).getReg();
+ Register Mul2 = Sub.getOperand(2).getReg();
+ Observer.changingInstr(MI);
+ B.buildInstr(AArch64::G_SUB, {Tmp}, {Src, Mul1});
+ MI.getOperand(1).setReg(Tmp);
+ MI.getOperand(2).setReg(Mul2);
+ Sub.eraseFromParent();
+ Observer.changingInstr(MI);
+}
+
class AArch64PostLegalizerCombinerImpl : public Combiner {
protected:
const CombinerHelper Helper;
diff --git a/llvm/test/CodeGen/AArch64/aarch64-smull.ll b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
index a302ddf483caa..80fe2c898e8e5 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-smull.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-smull.ll
@@ -2074,14 +2074,13 @@ define void @smlsl_smlsl2_v8i16_uzp1(<16 x i8> %0, <8 x i16> %1, ptr %2, ptr %3,
;
; CHECK-GI-LABEL: smlsl_smlsl2_v8i16_uzp1:
; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldp q4, q2, [x1]
-; CHECK-GI-NEXT: mov d3, v0.d[1]
+; CHECK-GI-NEXT: ldp q2, q3, [x1]
+; CHECK-GI-NEXT: mov d4, v0.d[1]
; CHECK-GI-NEXT: xtn v2.8b, v2.8h
-; CHECK-GI-NEXT: xtn v4.8b, v4.8h
-; CHECK-GI-NEXT: smull v2.8h, v3.8b, v2.8b
-; CHECK-GI-NEXT: smlal v2.8h, v0.8b, v4.8b
-; CHECK-GI-NEXT: sub v0.8h, v1.8h, v2.8h
-; CHECK-GI-NEXT: str q0, [x0]
+; CHECK-GI-NEXT: xtn v3.8b, v3.8h
+; CHECK-GI-NEXT: smlsl v1.8h, v0.8b, v2.8b
+; CHECK-GI-NEXT: smlsl v1.8h, v4.8b, v3.8b
+; CHECK-GI-NEXT: str q1, [x0]
; CHECK-GI-NEXT: ret
entry:
%5 = load <8 x i16>, ptr %3, align 4
@@ -2120,14 +2119,13 @@ define void @umlsl_umlsl2_v8i16_uzp1(<16 x i8> %0, <8 x i16> %1, ptr %2, ptr %3,
;
; CHECK-GI-LABEL: umlsl_umlsl2_v8i16_uzp1:
; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldp q4, q2, [x1]
-; CHECK-GI-NEXT: mov d3, v0.d[1]
+; CHECK-GI-NEXT: ldp q2, q3, [x1]
+; CHECK-GI-NEXT: mov d4, v0.d[1]
; CHECK-GI-NEXT: xtn v2.8b, v2.8h
-; CHECK-GI-NEXT: xtn v4.8b, v4.8h
-; CHECK-GI-NEXT: umull v2.8h, v3.8b, v2.8b
-; CHECK-GI-NEXT: umlal v2.8h, v0.8b, v4.8b
-; CHECK-GI-NEXT: sub v0.8h, v1.8h, v2.8h
-; CHECK-GI-NEXT: str q0, [x0]
+; CHECK-GI-NEXT: xtn v3.8b, v3.8h
+; CHECK-GI-NEXT: umlsl v1.8h, v0.8b, v2.8b
+; CHECK-GI-NEXT: umlsl v1.8h, v4.8b, v3.8b
+; CHECK-GI-NEXT: str q1, [x0]
; CHECK-GI-NEXT: ret
entry:
%5 = load <8 x i16>, ptr %3, align 4
@@ -2166,14 +2164,13 @@ define void @smlsl_smlsl2_v4i32_uzp1(<8 x i16> %0, <4 x i32> %1, ptr %2, ptr %3,
;
; CHECK-GI-LABEL: smlsl_smlsl2_v4i32_uzp1:
; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldp q4, q2, [x1]
-; CHECK-GI-NEXT: mov d3, v0.d[1]
+; CHECK-GI-NEXT: ldp q2, q3, [x1]
+; CHECK-GI-NEXT: mov d4, v0.d[1]
; CHECK-GI-NEXT: xtn v2.4h, v2.4s
-; CHECK-GI-NEXT: xtn v4.4h, v4.4s
-; CHECK-GI-NEXT: smull v2.4s, v3.4h, v2.4h
-; CHECK-GI-NEXT: smlal v2.4s, v0.4h, v4.4h
-; CHECK-GI-NEXT: sub v0.4s, v1.4s, v2.4s
-; CHECK-GI-NEXT: str q0, [x0]
+; CHECK-GI-NEXT: xtn v3.4h, v3.4s
+; CHECK-GI-NEXT: smlsl v1.4s, v0.4h, v2.4h
+; CHECK-GI-NEXT: smlsl v1.4s, v4.4h, v3.4h
+; CHECK-GI-NEXT: str q1, [x0]
; CHECK-GI-NEXT: ret
entry:
%5 = load <4 x i32>, ptr %3, align 4
@@ -2212,14 +2209,13 @@ define void @umlsl_umlsl2_v4i32_uzp1(<8 x i16> %0, <4 x i32> %1, ptr %2, ptr %3,
;
; CHECK-GI-LABEL: umlsl_umlsl2_v4i32_uzp1:
; CHECK-GI: // %bb.0: // %entry
-; CHECK-GI-NEXT: ldp q4, q2, [x1]
-; CHECK-GI-NEXT: mov d3, v0.d[1]
+; CHECK-GI-NEXT: ldp q2, q3, [x1]
+; CHECK-GI-NEXT: mov d4, v0.d[1]
; CHECK-GI-NEXT: xtn v2.4h, v2.4s
-; CHECK-GI-NEXT: xtn v4.4h, v4.4s
-; CHECK-GI-NEXT: umull v2.4s, v3.4h, v2.4h
-; CHECK-GI-NEXT: umlal v2.4s, v0.4h, v4.4h
-; CHECK-GI-NEXT: sub v0.4s, v1.4s, v2.4s
-; CHECK-GI-NEXT: str q0, [x0]
+; CHECK-GI-NEXT: xtn v3.4h, v3.4s
+; CHECK-GI-NEXT: umlsl v1.4s, v0.4h, v2.4h
+; CHECK-GI-NEXT: umlsl v1.4s, v4.4h, v3.4h
+; CHECK-GI-NEXT: str q1, [x0]
; CHECK-GI-NEXT: ret
entry:
%5 = load <4 x i32>, ptr %3, align 4
diff --git a/llvm/test/CodeGen/AArch64/reassocmls.ll b/llvm/test/CodeGen/AArch64/reassocmls.ll
index 0909fbffc34de..5a769a577ce92 100644
--- a/llvm/test/CodeGen/AArch64/reassocmls.ll
+++ b/llvm/test/CodeGen/AArch64/reassocmls.ll
@@ -8,18 +8,11 @@
; CHECK-GI-NEXT: warning: Instruction selection used fallback path for mla_nxv8i16
define i64 @smlsl_i64(i64 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
-; CHECK-SD-LABEL: smlsl_i64:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: smsubl x8, w4, w3, x0
-; CHECK-SD-NEXT: smsubl x0, w2, w1, x8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: smlsl_i64:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: smull x8, w2, w1
-; CHECK-GI-NEXT: smaddl x8, w4, w3, x8
-; CHECK-GI-NEXT: sub x0, x0, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: smlsl_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: smsubl x8, w4, w3, x0
+; CHECK-NEXT: smsubl x0, w2, w1, x8
+; CHECK-NEXT: ret
%be = sext i32 %b to i64
%ce = sext i32 %c to i64
%de = sext i32 %d to i64
@@ -32,18 +25,11 @@ define i64 @smlsl_i64(i64 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
}
define i64 @umlsl_i64(i64 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
-; CHECK-SD-LABEL: umlsl_i64:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: umsubl x8, w4, w3, x0
-; CHECK-SD-NEXT: umsubl x0, w2, w1, x8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umlsl_i64:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: umull x8, w2, w1
-; CHECK-GI-NEXT: umaddl x8, w4, w3, x8
-; CHECK-GI-NEXT: sub x0, x0, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umlsl_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: umsubl x8, w4, w3, x0
+; CHECK-NEXT: umsubl x0, w2, w1, x8
+; CHECK-NEXT: ret
%be = zext i32 %b to i64
%ce = zext i32 %c to i64
%de = zext i32 %d to i64
@@ -56,18 +42,11 @@ define i64 @umlsl_i64(i64 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
}
define i64 @mls_i64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e) {
-; CHECK-SD-LABEL: mls_i64:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: msub x8, x4, x3, x0
-; CHECK-SD-NEXT: msub x0, x2, x1, x8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: mls_i64:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: mul x8, x2, x1
-; CHECK-GI-NEXT: madd x8, x4, x3, x8
-; CHECK-GI-NEXT: sub x0, x0, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: mls_i64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: msub x8, x4, x3, x0
+; CHECK-NEXT: msub x0, x2, x1, x8
+; CHECK-NEXT: ret
%m1.neg = mul i64 %c, %b
%m2.neg = mul i64 %e, %d
%reass.add = add i64 %m2.neg, %m1.neg
@@ -76,18 +55,11 @@ define i64 @mls_i64(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e) {
}
define i16 @mls_i16(i16 %a, i16 %b, i16 %c, i16 %d, i16 %e) {
-; CHECK-SD-LABEL: mls_i16:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: msub w8, w4, w3, w0
-; CHECK-SD-NEXT: msub w0, w2, w1, w8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: mls_i16:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: mul w8, w2, w1
-; CHECK-GI-NEXT: madd w8, w4, w3, w8
-; CHECK-GI-NEXT: sub w0, w0, w8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: mls_i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: msub w8, w4, w3, w0
+; CHECK-NEXT: msub w0, w2, w1, w8
+; CHECK-NEXT: ret
%m1.neg = mul i16 %c, %b
%m2.neg = mul i16 %e, %d
%reass.add = add i16 %m2.neg, %m1.neg
@@ -125,20 +97,12 @@ define i64 @mls_i64_C(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e) {
}
define i64 @umlsl_i64_muls(i64 %a, i32 %b, i32 %c, i32 %d, i32 %e) {
-; CHECK-SD-LABEL: umlsl_i64_muls:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: umull x8, w2, w3
-; CHECK-SD-NEXT: umsubl x8, w4, w3, x8
-; CHECK-SD-NEXT: umsubl x0, w2, w1, x8
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umlsl_i64_muls:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: umull x8, w2, w1
-; CHECK-GI-NEXT: umull x9, w2, w3
-; CHECK-GI-NEXT: umaddl x8, w4, w3, x8
-; CHECK-GI-NEXT: sub x0, x9, x8
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umlsl_i64_muls:
+; CHECK: // %bb.0:
+; CHECK-NEXT: umull x8, w2, w3
+; CHECK-NEXT: umsubl x8, w4, w3, x8
+; CHECK-NEXT: umsubl x0, w2, w1, x8
+; CHECK-NEXT: ret
%be = zext i32 %b to i64
%ce = zext i32 %c to i64
%de = zext i32 %d to i64
@@ -225,18 +189,11 @@ define i64 @mla_i64_mul(i64 %a, i64 %b, i64 %c, i64 %d, i64 %e) {
define <8 x i16> @smlsl_v8i16(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d, <8 x i8> %e) {
-; CHECK-SD-LABEL: smlsl_v8i16:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: smlsl v0.8h, v4.8b, v3.8b
-; CHECK-SD-NEXT: smlsl v0.8h, v2.8b, v1.8b
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: smlsl_v8i16:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: smull v1.8h, v2.8b, v1.8b
-; CHECK-GI-NEXT: smlal v1.8h, v4.8b, v3.8b
-; CHECK-GI-NEXT: sub v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: smlsl_v8i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: smlsl v0.8h, v4.8b, v3.8b
+; CHECK-NEXT: smlsl v0.8h, v2.8b, v1.8b
+; CHECK-NEXT: ret
%be = sext <8 x i8> %b to <8 x i16>
%ce = sext <8 x i8> %c to <8 x i16>
%de = sext <8 x i8> %d to <8 x i16>
@@ -249,18 +206,11 @@ define <8 x i16> @smlsl_v8i16(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %
}
define <8 x i16> @umlsl_v8i16(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %d, <8 x i8> %e) {
-; CHECK-SD-LABEL: umlsl_v8i16:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: umlsl v0.8h, v4.8b, v3.8b
-; CHECK-SD-NEXT: umlsl v0.8h, v2.8b, v1.8b
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: umlsl_v8i16:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: umull v1.8h, v2.8b, v1.8b
-; CHECK-GI-NEXT: umlal v1.8h, v4.8b, v3.8b
-; CHECK-GI-NEXT: sub v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: umlsl_v8i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: umlsl v0.8h, v4.8b, v3.8b
+; CHECK-NEXT: umlsl v0.8h, v2.8b, v1.8b
+; CHECK-NEXT: ret
%be = zext <8 x i8> %b to <8 x i16>
%ce = zext <8 x i8> %c to <8 x i16>
%de = zext <8 x i8> %d to <8 x i16>
@@ -273,18 +223,11 @@ define <8 x i16> @umlsl_v8i16(<8 x i16> %a, <8 x i8> %b, <8 x i8> %c, <8 x i8> %
}
define <8 x i16> @mls_v8i16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c, <8 x i16> %d, <8 x i16> %e) {
-; CHECK-SD-LABEL: mls_v8i16:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mls v0.8h, v4.8h, v3.8h
-; CHECK-SD-NEXT: mls v0.8h, v2.8h, v1.8h
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: mls_v8i16:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: mul v1.8h, v2.8h, v1.8h
-; CHECK-GI-NEXT: mla v1.8h, v4.8h, v3.8h
-; CHECK-GI-NEXT: sub v0.8h, v0.8h, v1.8h
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: mls_v8i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mls v0.8h, v4.8h, v3.8h
+; CHECK-NEXT: mls v0.8h, v2.8h, v1.8h
+; CHECK-NEXT: ret
%m1.neg = mul <8 x i16> %c, %b
%m2.neg = mul <8 x i16> %e, %d
%reass.add = add <8 x i16> %m2.neg, %m1.neg
@@ -307,20 +250,12 @@ define <8 x i16> @mla_v8i16(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c, <8 x i16>
}
define <8 x i16> @mls_v8i16_C(<8 x i16> %a, <8 x i16> %b, <8 x i16> %c, <8 x i16> %d, <8 x i16> %e) {
-; CHECK-SD-LABEL: mls_v8i16_C:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: movi v0.8h, #10
-; CHECK-SD-NEXT: mls v0.8h, v4.8h, v3.8h
-; CHECK-SD-NEXT: mls v0.8h, v2.8h, v1.8h
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: mls_v8i16_C:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: mul v0.8h, v2.8h, v1.8h
-; CHECK-GI-NEXT: movi v1.8h, #10
-; CHECK-GI-NEXT: mla v0.8h, v4.8h, v3.8h
-; CHECK-GI-NEXT: sub v0.8h, v1.8h, v0.8h
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: mls_v8i16_C:
+; CHECK: // %bb.0:
+; CHECK-NEXT: movi v0.8h, #10
+; CHECK-NEXT: mls v0.8h, v4.8h, v3.8h
+; CHECK-NEXT: mls v0.8h, v2.8h, v1.8h
+; CHECK-NEXT: ret
%m1.neg = mul <8 x i16> %c, %b
%m2.neg = mul <8 x i16> %e, %d
%reass.add = add <8 x i16> %m2.neg, %m1.neg
More information about the llvm-commits
mailing list