[llvm] [Hexagon] Optimize sext + mul pattern to use vmpyh instruction (PR #190316)
Santanu Das via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 13 01:02:53 PDT 2026
https://github.com/quic-santdas updated https://github.com/llvm/llvm-project/pull/190316
>From 39e2259bfd2718bec718540954315f7cbecf3cb5 Mon Sep 17 00:00:00 2001
From: Chandana Mudda <quic_csinderi at quicinc.com>
Date: Fri, 3 Apr 2026 00:17:03 -0700
Subject: [PATCH] Optimize sext + mul pattern to use vmpyh instruction
This patch adds TableGen patterns to recognize and optimize the pattern:
(v2i32 (mul (sext v2i16), (sext v2i16)))
And transforms it to use the M2_vmpy2s_s0 instruction which generates
the efficient vmpyh (vector multiply halfwords) instruction.
The transform is guarded by `nsw` because `M2_vmpy2s_s0` performs a
saturating signed multiply (`vmpyh(...):sat`), so the replacement is
only semantics-preserving when signed overflow is undefined in the IR.
Currently, this pattern expands to:
r3:2 = vsxthw(r0) // Sign extend
r1:0 = vsxthw(r1) // Sign extend
r1 = mpyi(r3,r1) // Scalar multiply
r0 = mpyi(r2,r0) // Scalar multiply
With this patch, it generates:
r1:0 = vmpyh(r0,r1):sat // Single vector multiply
---
llvm/lib/Target/Hexagon/HexagonPatterns.td | 8 ++++++++
llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll | 16 ++++++++++++++++
2 files changed, 24 insertions(+)
create mode 100644 llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll
diff --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index 3f836e8c1dbef..91f46a631d409 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -1747,10 +1747,18 @@ def n8_0ImmPred: PatLeaf<(i32 imm), [{
return -255 <= V && V <= 0;
}]>;
+def mulnsw : PatFrag<(ops node:$lhs, node:$rhs),
+ (mul node:$lhs, node:$rhs), [{
+ return N->getFlags().hasNoSignedWrap();
+}]>;
+
// Change the sign of the immediate for Rd=-mpyi(Rs,#u8)
def: Pat<(mul I32:$Rs, n8_0ImmPred:$n8),
(M2_mpysin I32:$Rs, (NegImm8 imm:$n8))>;
+def: Pat<(v2i32 (mulnsw (sext V2I16:$Rs), (sext V2I16:$Rt))),
+ (M2_vmpy2s_s0 V2I16:$Rs, V2I16:$Rt)>;
+
def: Pat<(add Sext64:$Rs, I64:$Rt),
(A2_addsp (LoReg Sext64:$Rs), I64:$Rt)>;
diff --git a/llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll b/llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll
new file mode 100644
index 0000000000000..a34a5faa9cc3b
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll
@@ -0,0 +1,16 @@
+; RUN: llc -O2 -mtriple=hexagon < %s | FileCheck %s
+
+; Test that we optimize sext + mul pattern to use vmpyh instruction
+; instead of expanding to scalar multiplies.
+
+; CHECK-LABEL: test_sext_mul_v2i16:
+; CHECK: vmpyh
+; CHECK-NOT: vsxthw
+; CHECK-NOT: mpyi
+define <2 x i32> @test_sext_mul_v2i16(<2 x i16> %a, <2 x i16> %b) {
+entry:
+ %ext_a = sext <2 x i16> %a to <2 x i32>
+ %ext_b = sext <2 x i16> %b to <2 x i32>
+ %mul = mul nsw <2 x i32> %ext_a, %ext_b
+ ret <2 x i32> %mul
+}
More information about the llvm-commits
mailing list