[llvm] ff51870 - [Hexagon] Optimize sext + mul pattern for splatted scalar sext i16 (#206893)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 7 01:20:58 PDT 2026


Author: Chandana Mudda
Date: 2026-07-07T13:50:53+05:30
New Revision: ff518705c4c5d1e6e7a94d6ab7819618708d5bcd

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

LOG: [Hexagon] Optimize sext + mul pattern for splatted scalar sext i16 (#206893)

Extend the existing vmpyh pattern to handle the case where one operand
of a v2i32 nsw mul is a splatted scalar sext i16 value. When the splat
is hoisted out of a loop, it arrives as assertsext v2i32, i16 in the DAG
rather than sext v2i16. The existing pattern did not match this form,
causing the multiply to expand to two scalar mpyi instructions.

Add a PatFrag assertsext_v2i32_i16 to match assertsext nodes of type
v2i32 extended from i16, and two new patterns (both operand orderings)
that recover the v2i16 using A2_combine_ll before feeding into
M2_vmpy2s_s0.

Added: 
    llvm/test/CodeGen/Hexagon/sext-mul-splat-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 63e94b302c117..dbaa6c1fef572 100644
--- a/llvm/lib/Target/Hexagon/HexagonPatterns.td
+++ b/llvm/lib/Target/Hexagon/HexagonPatterns.td
@@ -1764,6 +1764,28 @@ def: Pat<(mul I32:$Rs, n8_0ImmPred:$n8),
 def: Pat<(v2i32 (mulnsw (sext V2I16:$Rs), (sext V2I16:$Rt))),
          (M2_vmpy2s_s0 V2I16:$Rs, V2I16:$Rt)>;
 
+// PatFrag matching assertsext of a v2i32 from i16, produced when a scalar
+// sext i16 is splatted into a v2i32 vector and the splat is hoisted out of
+// the loop into an earlier block, arriving as a live-in v2i32 register.
+def assertsext_v2i32_i16 : PatFrag<(ops node:$Rs),
+                                    (assertsext node:$Rs), [{
+  auto *T = cast<VTSDNode>(N->getOperand(1));
+  return N->getValueType(0) == MVT::v2i32 && T->getVT() == MVT::i16;
+}]>;
+
+// Handle sext v2i16 multiplied by a splatted scalar sext i16, where the
+// splat was hoisted and arrives as assertsext v2i32. Recover the v2i16
+// by combining the low halfwords of both elements.
+def: Pat<(v2i32 (mulnsw (sext V2I16:$Rs),
+                         (assertsext_v2i32_i16 V2I32:$Rt))),
+         (M2_vmpy2s_s0 V2I16:$Rs,
+                       (A2_combine_ll (HiReg $Rt), (LoReg $Rt)))>;
+
+def: Pat<(v2i32 (mulnsw (assertsext_v2i32_i16 V2I32:$Rs),
+                         (sext V2I16:$Rt))),
+         (M2_vmpy2s_s0 (A2_combine_ll (HiReg $Rs), (LoReg $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-splat-v2i16.ll b/llvm/test/CodeGen/Hexagon/sext-mul-splat-v2i16.ll
new file mode 100644
index 0000000000000..5c8f3356e305e
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/sext-mul-splat-v2i16.ll
@@ -0,0 +1,31 @@
+; RUN: llc -O2 -mtriple=hexagon < %s | FileCheck %s
+
+; Test that sext v2i16 multiplied by a splatted scalar sext i16 (where the
+; splat is hoisted and arrives as assertsext v2i32) is optimized to vmpyh.
+
+; CHECK-LABEL: test_sext_mul_splat:
+; CHECK-NOT: vsxthw
+; CHECK-NOT: mpyi
+; CHECK: vmpyh
+define void @test_sext_mul_splat(ptr %src, ptr %dst, i16 signext %scale, i32 %n) {
+entry:
+  %scale32 = sext i16 %scale to i32
+  %ins0 = insertelement <2 x i32> poison, i32 %scale32, i32 0
+  %splat = insertelement <2 x i32> %ins0, i32 %scale32, i32 1
+  br label %loop
+
+loop:
+  %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
+  %ptr = getelementptr <2 x i16>, ptr %src, i32 %i
+  %v = load <2 x i16>, ptr %ptr, align 4
+  %ext = sext <2 x i16> %v to <2 x i32>
+  %mul = mul nsw <2 x i32> %ext, %splat
+  %dptr = getelementptr <2 x i32>, ptr %dst, i32 %i
+  store <2 x i32> %mul, ptr %dptr, align 8
+  %i.next = add i32 %i, 1
+  %done = icmp eq i32 %i.next, %n
+  br i1 %done, label %exit, label %loop
+
+exit:
+  ret void
+}


        


More information about the llvm-commits mailing list