[llvm] [HEXAGON] Add AssertSext in sign-extended mpy (PR #149061)

Abinaya Saravanan via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 16 03:37:56 PDT 2025


https://github.com/quic-asaravan created https://github.com/llvm/llvm-project/pull/149061

The pattern i32xi32->i64, should be matched to the sign-extended multiply op, instead of explicit sign- extension of the operands followed by non-widening multiply (this takes 4 operations instead of one). Currently, if one of the operands of multiply inside a loop is a constant, the sign-extension of this
constant is hoisted out of the loop by LICM pass
and this pattern is not matched by the ISEL.

This change handles multiply operand with Opcode of the type AssertSext which is seen when the sign-extension is hoisted out-of the loop. Modifies the DetectUseSxtw() to check for this.

Co-authored-by: Shubham Pawar

>From 73259a490a22b69bfba6d3cb974dbbee77d8f1bf Mon Sep 17 00:00:00 2001
From: quic-asaravan <quic_asaravan at quicinc.com>
Date: Wed, 16 Jul 2025 03:26:54 -0700
Subject: [PATCH] [HEXAGON] Add AssertSext in sign-extended mpy

The pattern i32xi32->i64, should be matched to the
sign-extended multiply op, instead of explicit sign-
extension of the operands followed by non-widening
multiply (this takes 4 operations instead of one).
Currently, if one of the operands of multiply inside
a loop is a constant, the sign-extension of this
constant is hoisted out of the loop by LICM pass
and this pattern is not matched by the ISEL.

This change handles multiply operand with Opcode of
the type AssertSext which is seen when the sign-extension
is hoisted out-of the loop. Modifies the DetectUseSxtw()
to check for this.

Co-authored-by: Shubham Pawar
---
 .../Target/Hexagon/HexagonISelDAGToDAG.cpp    |  9 +++++
 .../test/CodeGen/Hexagon/mpy-operand-hoist.ll | 38 +++++++++++++++++++
 2 files changed, 47 insertions(+)
 create mode 100644 llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll

diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 53943de3bc597..e285e04543694 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -1640,6 +1640,15 @@ bool HexagonDAGToDAGISel::DetectUseSxtw(SDValue &N, SDValue &R) {
       R = N;
       break;
     }
+    case ISD::AssertSext: {
+      EVT T = cast<VTSDNode>(N.getOperand(1))->getVT();
+      if (T.getSizeInBits() == 32)
+        R = N.getOperand(0);
+      else
+        return false;
+      break;
+    }
+
     default:
       return false;
   }
diff --git a/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll b/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll
new file mode 100644
index 0000000000000..ff50f1abe5897
--- /dev/null
+++ b/llvm/test/CodeGen/Hexagon/mpy-operand-hoist.ll
@@ -0,0 +1,38 @@
+; RUN: llc -march=hexagon -verify-machineinstrs < %s | FileCheck %s
+
+; CHECK-NOT: r{{[0-9]+}} = asr(r{{[0-9]+}},#{{[0-9]+}})
+; CHECK-NOT: r{{[0-9]+}}:{{[0-9]+}} = mpyu(r{{[0-9]+}},r{{[0-9]+}})
+; CHECK-NOT: r{{[0-9]+}} += mpyi(r{{[0-9]+}},r{{[0-9]+}})
+; CHECK: r{{[0-9]+}}:{{[0-9]+}} = mpy(r{{[0-9]+}},r{{[0-9]+}})
+
+; ModuleID = '39544.c'
+source_filename = "39544.c"
+target datalayout = "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32:32-i16:16:16-i1:8:8-f32:32:32-f64:64:64-v32:32:32-v64:64:64-v512:512:512-v1024:1024:1024-v2048:2048:2048"
+target triple = "hexagon"
+
+define dso_local void @mul_n(i64* nocapture %p, i32* nocapture readonly %a, i32 %k, i32 %n) local_unnamed_addr {
+entry:
+  %cmp7 = icmp sgt i32 %n, 0
+  br i1 %cmp7, label %for.body.lr.ph, label %for.cond.cleanup
+
+for.body.lr.ph:                                   ; preds = %entry
+  %conv1 = sext i32 %k to i64
+  br label %for.body
+
+for.cond.cleanup:                                 ; preds = %for.body, %entry
+  ret void
+
+for.body:                                         ; preds = %for.body, %for.body.lr.ph
+  %arrayidx.phi = phi i32* [ %a, %for.body.lr.ph ], [ %arrayidx.inc, %for.body ]
+  %arrayidx2.phi = phi i64* [ %p, %for.body.lr.ph ], [ %arrayidx2.inc, %for.body ]
+  %i.08 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.body ]
+  %0 = load i32, i32* %arrayidx.phi, align 4
+  %conv = sext i32 %0 to i64
+  %mul = mul nsw i64 %conv, %conv1
+  store i64 %mul, i64* %arrayidx2.phi, align 8
+  %inc = add nuw nsw i32 %i.08, 1
+  %exitcond = icmp eq i32 %inc, %n
+  %arrayidx.inc = getelementptr i32, i32* %arrayidx.phi, i32 1
+  %arrayidx2.inc = getelementptr i64, i64* %arrayidx2.phi, i32 1
+  br i1 %exitcond, label %for.cond.cleanup, label %for.body
+}



More information about the llvm-commits mailing list