[llvm] [RISCV][GlobalISel] Lower G_SMULFIX (PR #196636)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 14:05:15 PDT 2026


https://github.com/spaits updated https://github.com/llvm/llvm-project/pull/196636

>From e83e716ed1b083f19a8071058359becdfcee4d1c Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 8 May 2026 22:28:19 +0200
Subject: [PATCH 1/2] [RISCV][GlobalISel] Lower G_SMULFIX

The G_SMULFIX operator was added, but no lowering was defined for it.
---
 .../llvm/CodeGen/GlobalISel/LegalizerHelper.h |  1 +
 .../CodeGen/GlobalISel/LegalizerHelper.cpp    | 31 ++++++
 .../Target/RISCV/GISel/RISCVLegalizerInfo.cpp |  2 +
 .../legalizer/legalize-smulfix-rv32.mir       | 97 +++++++++++++++++++
 .../legalizer/legalize-smulfix-rv64.mir       | 59 +++++++++++
 .../RISCV/GlobalISel/smulfix-intrinsics.ll    | 82 ++++++++++++++++
 6 files changed, 272 insertions(+)
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv32.mir
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv64.mir
 create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/smulfix-intrinsics.ll

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 8bcae5d15ad2c..9858f5e92de7a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -576,6 +576,7 @@ class LegalizerHelper {
   LLVM_ABI LegalizeResult lowerMemCpyFamily(MachineInstr &MI,
                                             unsigned MaxLen = 0);
   LLVM_ABI LegalizeResult lowerVAArg(MachineInstr &MI);
+  LLVM_ABI LegalizeResult lowerSmulfix(MachineInstr &MI);
 };
 
 } // End namespace llvm.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 71cda8a480dd7..d6554e4f47f47 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4968,6 +4968,8 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
     MI.eraseFromParent();
     return Legalized;
   }
+  case G_SMULFIX:
+    return lowerSmulfix(MI);
   }
 }
 
@@ -10656,6 +10658,35 @@ LegalizerHelper::LegalizeResult LegalizerHelper::lowerVAArg(MachineInstr &MI) {
   return Legalized;
 }
 
+LegalizerHelper::LegalizeResult
+LegalizerHelper::lowerSmulfix(MachineInstr &MI) {
+  auto [Dst, LHS, RHS] = MI.getFirst3Regs();
+  LLT Ty = MRI.getType(Dst);
+  if (Ty != MRI.getType(LHS) || Ty != MRI.getType(RHS) || !Ty.isScalar())
+    return UnableToLegalize;
+
+  unsigned Scale = MI.getOperand(3).getImm();
+  if (Scale >= Ty.getSizeInBits())
+    return UnableToLegalize;
+
+  if (Scale == 0) {
+    MIRBuilder.buildMul(Dst, LHS, RHS);
+    MI.eraseFromParent();
+    return Legalized;
+  }
+
+  LLT WideTy = LLT::scalar(Ty.getSizeInBits() * 2);
+  auto SExtLHS = MIRBuilder.buildSExt(WideTy, LHS);
+  auto SExtRHS = MIRBuilder.buildSExt(WideTy, RHS);
+  auto Mul = MIRBuilder.buildMul(WideTy, SExtLHS, SExtRHS);
+  auto ShiftAmt = MIRBuilder.buildConstant(WideTy, Scale);
+  auto Shifted = MIRBuilder.buildAShr(WideTy, Mul, ShiftAmt);
+  MIRBuilder.buildTrunc(Dst, Shifted);
+
+  MI.eraseFromParent();
+  return Legalized;
+}
+
 static bool shouldLowerMemFuncForSize(const MachineFunction &MF) {
   // On Darwin, -Os means optimize for size without hurting performance, so
   // only really optimize for size when -Oz (MinSize) is used.
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index b7efee8bf4c83..6788e8112cd2b 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -156,6 +156,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
       .minScalar(0, sXLen)
       .lower();
 
+  getActionDefinitionsBuilder(G_SMULFIX).lower();
+
   // TODO: Use Vector Single-Width Saturating Instructions for vector types.
   getActionDefinitionsBuilder(
       {G_UADDSAT, G_SADDSAT, G_USUBSAT, G_SSUBSAT, G_SSHLSAT, G_USHLSAT})
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv32.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv32.mir
new file mode 100644
index 0000000000000..bbbb87197d0b3
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv32.mir
@@ -0,0 +1,97 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv32 -mattr=+m -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+
+---
+name:            smul_i32
+body:             |
+  bb.0.entry:
+    ; CHECK-LABEL: name: smul_i32
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C]](s32)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[COPY1]], [[C]](s32)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[ASHR1]]
+    ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
+    ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ADD]], [[UMULH]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C1]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 17
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD1]], [[C2]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: $x10 = COPY [[OR]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %0:_(s32) = COPY $x10
+    %1:_(s32) = COPY $x11
+    %2:_(s32) = G_SMULFIX %0:_, %1:_, 15
+    $x10 = COPY %2:_(s32)
+    PseudoRET implicit $x10
+...
+---
+name:            smul_i64
+body:             |
+  bb.0.entry:
+    ; CHECK-LABEL: name: smul_i64
+    ; CHECK: [[COPY:%[0-9]+]]:_(s32) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $x11
+    ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $x12
+    ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $x13
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY1]], [[C]](s32)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[COPY3]], [[C]](s32)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY2]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s32) = G_MUL [[COPY1]], [[COPY2]]
+    ; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[COPY3]]
+    ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s32) = G_UMULH [[COPY]], [[COPY2]]
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[MUL1]], [[MUL2]]
+    ; CHECK-NEXT: [[ICMP:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD]](s32), [[MUL2]]
+    ; CHECK-NEXT: [[COPY4:%[0-9]+]]:_(s32) = COPY [[ADD]](s32)
+    ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[COPY4]], [[UMULH]]
+    ; CHECK-NEXT: [[ICMP1:%[0-9]+]]:_(s32) = G_ICMP intpred(ult), [[ADD1]](s32), [[UMULH]]
+    ; CHECK-NEXT: [[COPY5:%[0-9]+]]:_(s32) = COPY [[ADD1]](s32)
+    ; CHECK-NEXT: [[ADD2:%[0-9]+]]:_(s32) = G_ADD [[ICMP]], [[ICMP1]]
+    ; CHECK-NEXT: [[MUL3:%[0-9]+]]:_(s32) = G_MUL [[ASHR]], [[COPY2]]
+    ; CHECK-NEXT: [[MUL4:%[0-9]+]]:_(s32) = G_MUL [[COPY1]], [[COPY3]]
+    ; CHECK-NEXT: [[MUL5:%[0-9]+]]:_(s32) = G_MUL [[COPY]], [[ASHR1]]
+    ; CHECK-NEXT: [[UMULH1:%[0-9]+]]:_(s32) = G_UMULH [[COPY1]], [[COPY2]]
+    ; CHECK-NEXT: [[UMULH2:%[0-9]+]]:_(s32) = G_UMULH [[COPY]], [[COPY3]]
+    ; CHECK-NEXT: [[ADD3:%[0-9]+]]:_(s32) = G_ADD [[MUL3]], [[MUL4]]
+    ; CHECK-NEXT: [[COPY6:%[0-9]+]]:_(s32) = COPY [[ADD3]](s32)
+    ; CHECK-NEXT: [[ADD4:%[0-9]+]]:_(s32) = G_ADD [[COPY6]], [[MUL5]]
+    ; CHECK-NEXT: [[COPY7:%[0-9]+]]:_(s32) = COPY [[ADD4]](s32)
+    ; CHECK-NEXT: [[ADD5:%[0-9]+]]:_(s32) = G_ADD [[COPY7]], [[UMULH1]]
+    ; CHECK-NEXT: [[COPY8:%[0-9]+]]:_(s32) = COPY [[ADD5]](s32)
+    ; CHECK-NEXT: [[ADD6:%[0-9]+]]:_(s32) = G_ADD [[COPY8]], [[UMULH2]]
+    ; CHECK-NEXT: [[COPY9:%[0-9]+]]:_(s32) = COPY [[ADD6]](s32)
+    ; CHECK-NEXT: [[ADD7:%[0-9]+]]:_(s32) = G_ADD [[COPY9]], [[ADD2]]
+    ; CHECK-NEXT: [[COPY10:%[0-9]+]]:_(s32) = COPY [[ADD7]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[MUL]], [[C2]](s32)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 17
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[COPY5]], [[C3]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[COPY5]], [[C2]](s32)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY10]], [[C3]](s32)
+    ; CHECK-NEXT: [[OR1:%[0-9]+]]:_(s32) = G_OR [[OR]], [[C1]]
+    ; CHECK-NEXT: [[OR2:%[0-9]+]]:_(s32) = G_OR [[LSHR1]], [[SHL1]]
+    ; CHECK-NEXT: $x10 = COPY [[OR1]](s32)
+    ; CHECK-NEXT: $x11 = COPY [[OR2]](s32)
+    ; CHECK-NEXT: PseudoRET implicit $x10, implicit $x11
+    %2:_(s32) = COPY $x10
+    %3:_(s32) = COPY $x11
+    %0:_(s64) = G_MERGE_VALUES %2:_(s32), %3:_(s32)
+    %4:_(s32) = COPY $x12
+    %5:_(s32) = COPY $x13
+    %1:_(s64) = G_MERGE_VALUES %4:_(s32), %5:_(s32)
+    %6:_(s64) = G_SMULFIX %0:_, %1:_, 15
+    %7:_(s32), %8:_(s32) = G_UNMERGE_VALUES %6:_(s64)
+    $x10 = COPY %7:_(s32)
+    $x11 = COPY %8:_(s32)
+    PseudoRET implicit $x10, implicit $x11
+...
+
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv64.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv64.mir
new file mode 100644
index 0000000000000..9e20932cef300
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-smulfix-rv64.mir
@@ -0,0 +1,59 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=riscv64 -mattr=+m -run-pass=legalizer %s -o - \
+# RUN: | FileCheck %s
+
+---
+name:            smul_i32
+body:             |
+  bb.0.entry:
+    ; CHECK-LABEL: name: smul_i32
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY]], 32
+    ; CHECK-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s64) = G_SEXT_INREG [[COPY1]], 32
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[SEXT_INREG]], [[SEXT_INREG1]]
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[MUL]], [[C]](s64)
+    ; CHECK-NEXT: $x10 = COPY [[ASHR]](s64)
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %2:_(s64) = COPY $x10
+    %0:_(s32) = G_TRUNC %2:_(s64)
+    %3:_(s64) = COPY $x11
+    %1:_(s32) = G_TRUNC %3:_(s64)
+    %4:_(s32) = G_SMULFIX %0:_, %1:_, 15
+    %5:_(s64) = G_ANYEXT %4:_(s32)
+    $x10 = COPY %5:_(s64)
+    PseudoRET implicit $x10
+
+...
+
+---
+name:            smul_i64
+body:             |
+  bb.0.entry:
+    ; CHECK-LABEL: name: smul_i64
+    ; CHECK: [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+    ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x11
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY]], [[C]](s64)
+    ; CHECK-NEXT: [[ASHR1:%[0-9]+]]:_(s64) = G_ASHR [[COPY1]], [[C]](s64)
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(s64) = G_MUL [[ASHR]], [[COPY1]]
+    ; CHECK-NEXT: [[MUL2:%[0-9]+]]:_(s64) = G_MUL [[COPY]], [[ASHR1]]
+    ; CHECK-NEXT: [[UMULH:%[0-9]+]]:_(s64) = G_UMULH [[COPY]], [[COPY1]]
+    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[MUL1]], [[MUL2]]
+    ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[ADD]], [[UMULH]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 15
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[MUL]], [[C1]](s64)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 49
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ADD1]], [[C2]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: $x10 = COPY [[OR]](s64)
+    ; CHECK-NEXT: PseudoRET implicit $x10
+    %0:_(s64) = COPY $x10
+    %1:_(s64) = COPY $x11
+    %2:_(s64) = G_SMULFIX %0:_, %1:_, 15
+    $x10 = COPY %2:_(s64)
+    PseudoRET implicit $x10
+...
+
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/smulfix-intrinsics.ll b/llvm/test/CodeGen/RISCV/GlobalISel/smulfix-intrinsics.ll
new file mode 100644
index 0000000000000..3fce674bcf69a
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/smulfix-intrinsics.ll
@@ -0,0 +1,82 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -O3 -mtriple=riscv32 -mattr=+m -verify-machineinstrs -global-isel < %s \
+; RUN:   | FileCheck %s -check-prefix=RV32I
+; RUN: llc -O3 -mtriple=riscv64 -mattr=+m -verify-machineinstrs -global-isel < %s \
+; RUN:   | FileCheck %s -check-prefix=RV64I
+
+define i32 @smulfix_i32(i32 %1, i32 %2) {
+; RV32I-LABEL: smulfix_i32:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srai a2, a0, 31
+; RV32I-NEXT:    srai a3, a1, 31
+; RV32I-NEXT:    mul a4, a0, a1
+; RV32I-NEXT:    mul a2, a2, a1
+; RV32I-NEXT:    mulhu a1, a0, a1
+; RV32I-NEXT:    mul a0, a0, a3
+; RV32I-NEXT:    add a0, a2, a0
+; RV32I-NEXT:    add a0, a0, a1
+; RV32I-NEXT:    srli a4, a4, 15
+; RV32I-NEXT:    slli a0, a0, 17
+; RV32I-NEXT:    or a0, a4, a0
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: smulfix_i32:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    sext.w a0, a0
+; RV64I-NEXT:    sext.w a1, a1
+; RV64I-NEXT:    mul a0, a0, a1
+; RV64I-NEXT:    srai a0, a0, 15
+; RV64I-NEXT:    ret
+  %m = call i32 @llvm.smul.fix.i32(i32 %1, i32 %2, i32 15)
+  ret i32 %m
+}
+
+define i64 @smulfix_i64(i64 %1, i64 %2) {
+; RV32I-LABEL: smulfix_i64:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    srai a4, a1, 31
+; RV32I-NEXT:    srai a5, a3, 31
+; RV32I-NEXT:    mul a6, a0, a2
+; RV32I-NEXT:    mul a7, a1, a2
+; RV32I-NEXT:    mul t0, a0, a3
+; RV32I-NEXT:    mulhu t1, a0, a2
+; RV32I-NEXT:    mul a4, a4, a2
+; RV32I-NEXT:    mulhu a2, a1, a2
+; RV32I-NEXT:    mul a1, a1, a3
+; RV32I-NEXT:    mulhu a3, a0, a3
+; RV32I-NEXT:    add a7, a7, t0
+; RV32I-NEXT:    mul a0, a0, a5
+; RV32I-NEXT:    srli a5, a6, 15
+; RV32I-NEXT:    sltu a6, a7, t0
+; RV32I-NEXT:    add a7, a7, t1
+; RV32I-NEXT:    add a1, a4, a1
+; RV32I-NEXT:    add a0, a0, a2
+; RV32I-NEXT:    sltu a2, a7, t1
+; RV32I-NEXT:    add a0, a1, a0
+; RV32I-NEXT:    slli a1, a7, 17
+; RV32I-NEXT:    add a2, a6, a2
+; RV32I-NEXT:    add a3, a0, a3
+; RV32I-NEXT:    or a0, a5, a1
+; RV32I-NEXT:    add a2, a3, a2
+; RV32I-NEXT:    srli a1, a7, 15
+; RV32I-NEXT:    slli a2, a2, 17
+; RV32I-NEXT:    or a1, a1, a2
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: smulfix_i64:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    srai a2, a0, 63
+; RV64I-NEXT:    srai a3, a1, 63
+; RV64I-NEXT:    mul a4, a0, a1
+; RV64I-NEXT:    mul a2, a2, a1
+; RV64I-NEXT:    mulhu a1, a0, a1
+; RV64I-NEXT:    mul a0, a0, a3
+; RV64I-NEXT:    add a0, a2, a0
+; RV64I-NEXT:    add a0, a0, a1
+; RV64I-NEXT:    srli a4, a4, 15
+; RV64I-NEXT:    slli a0, a0, 49
+; RV64I-NEXT:    or a0, a4, a0
+; RV64I-NEXT:    ret
+  %m = call i64 @llvm.smul.fix.i64(i64 %1, i64 %2, i32 15)
+  ret i64 %m
+}

>From a4979976f9adaad7766634e6611c0b32a2e447da Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gaborspaits1 at gmail.com>
Date: Fri, 8 May 2026 23:05:01 +0200
Subject: [PATCH 2/2] Update leg. inf. valid.

---
 .../CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir    | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index f3e00ed6521c4..32f547ecdd7b6 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -484,8 +484,8 @@
 # DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: G_SMULFIX (opcode {{[0-9]+}}): 1 type index, 1 imm index
-# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
-# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
 # DEBUG-NEXT: G_UMULFIX (opcode {{[0-9]+}}): 1 type index, 1 imm index
 # DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
 # DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined



More information about the llvm-commits mailing list