[llvm] 0a984ed - [Hexagon] Optimize sext + mul pattern to use vmpyh instruction (#190316)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 08:17:42 PDT 2026


Author: Chandana Mudda
Date: 2026-04-16T20:47:36+05:30
New Revision: 0a984edbcd2e2f094f45e5ec009d444a947aea18

URL: https://github.com/llvm/llvm-project/commit/0a984edbcd2e2f094f45e5ec009d444a947aea18
DIFF: https://github.com/llvm/llvm-project/commit/0a984edbcd2e2f094f45e5ec009d444a947aea18.diff

LOG: [Hexagon] Optimize sext + mul pattern to use vmpyh instruction (#190316)

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

Co-authored-by: Santanu Das <quic_santdas at quicinc.com>

Added: 
    llvm/test/CodeGen/Hexagon/sext-mul-v2i16.ll

Modified: 
    llvm/lib/Target/Hexagon/HexagonPatterns.td

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td
index 0c9650585b613..bd79ae2c1a1a8 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