[llvm] [TTI] Add basic costs for llvm.[su]mulh. (PR #224002)

Ricardo Jesus via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 16 05:55:18 PDT 2026


https://github.com/rj-jesus created https://github.com/llvm/llvm-project/pull/224002

Defaults to the expansion (trunc ((ext(A) * ext(B)) >> BW)).

>From e83b92d2b755926726abbc931f483b443cfd7076 Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Fri, 21 Aug 2026 08:54:03 -0700
Subject: [PATCH] [TTI] Add basic costs for llvm.[su]mulh.

For non-legal/custom/promote operations, the cost assumes the expansion
(trunc ((ext(A) * ext(B)) >> BW)).
---
 llvm/include/llvm/CodeGen/BasicTTIImpl.h      |  25 ++
 .../CostModel/AArch64/mulh-scalable.ll        |  36 +++
 llvm/test/Analysis/CostModel/AArch64/mulh.ll  | 125 ++++++++
 llvm/test/Analysis/CostModel/RISCV/mulh.ll    | 267 ++++++++++++++++
 llvm/test/Analysis/CostModel/X86/mulh.ll      | 300 ++++++++++++++++++
 5 files changed, 753 insertions(+)
 create mode 100644 llvm/test/Analysis/CostModel/AArch64/mulh-scalable.ll
 create mode 100644 llvm/test/Analysis/CostModel/AArch64/mulh.ll
 create mode 100644 llvm/test/Analysis/CostModel/RISCV/mulh.ll
 create mode 100644 llvm/test/Analysis/CostModel/X86/mulh.ll

diff --git a/llvm/include/llvm/CodeGen/BasicTTIImpl.h b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
index 9723016ca23b4..cb01ef4028217 100644
--- a/llvm/include/llvm/CodeGen/BasicTTIImpl.h
+++ b/llvm/include/llvm/CodeGen/BasicTTIImpl.h
@@ -2755,6 +2755,12 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
     case Intrinsic::clmul:
       ISD = ISD::CLMUL;
       break;
+    case Intrinsic::smulh:
+      ISD = ISD::MULHS;
+      break;
+    case Intrinsic::umulh:
+      ISD = ISD::MULHU;
+      break;
     case Intrinsic::masked_udiv:
     case Intrinsic::masked_sdiv:
     case Intrinsic::masked_urem:
@@ -3141,6 +3147,25 @@ class BasicTTIImplBase : public TargetTransformInfoImplCRTPBase<T> {
       InstructionCost PerBitCost = std::min(PerBitCostMul, PerBitCostBittest);
       return BW * PerBitCost;
     }
+    case Intrinsic::smulh:
+    case Intrinsic::umulh: {
+      unsigned BW = RetTy->getScalarSizeInBits();
+      Type *WideTy = RetTy->getWithNewBitWidth(BW * 2);
+      bool IsSigned = IID == Intrinsic::smulh;
+      unsigned ExtOp = IsSigned ? Instruction::SExt : Instruction::ZExt;
+      InstructionCost Cost = 0;
+      Cost +=
+          2 * thisT()->getCastInstrCost(ExtOp, WideTy, RetTy,
+                                        TTI::CastContextHint::None, CostKind);
+      Cost +=
+          thisT()->getArithmeticInstrCost(Instruction::Mul, WideTy, CostKind);
+      Cost += thisT()->getArithmeticInstrCost(
+          Instruction::LShr, WideTy, CostKind, {TTI::OK_AnyValue, TTI::OP_None},
+          {TTI::OK_UniformConstantValue, TTI::OP_None});
+      Cost += thisT()->getCastInstrCost(Instruction::Trunc, RetTy, WideTy,
+                                        TTI::CastContextHint::None, CostKind);
+      return Cost;
+    }
     default:
       break;
     }
diff --git a/llvm/test/Analysis/CostModel/AArch64/mulh-scalable.ll b/llvm/test/Analysis/CostModel/AArch64/mulh-scalable.ll
new file mode 100644
index 0000000000000..62d355bf1f4c4
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/AArch64/mulh-scalable.ll
@@ -0,0 +1,36 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -mtriple=aarch64 -mattr=+sve -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,SVE
+; RUN: opt < %s -mtriple=aarch64 -mattr=+sve2 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,SVE2
+
+define void @smulh_scalable() {
+; CHECK-LABEL: 'smulh_scalable'
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv16i8 = call <vscale x 16 x i8> @llvm.smulh.nxv16i8(<vscale x 16 x i8> poison, <vscale x 16 x i8> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv8i16 = call <vscale x 8 x i16> @llvm.smulh.nxv8i16(<vscale x 8 x i16> poison, <vscale x 8 x i16> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv4i32 = call <vscale x 4 x i32> @llvm.smulh.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv2i64 = call <vscale x 2 x i64> @llvm.smulh.nxv2i64(<vscale x 2 x i64> poison, <vscale x 2 x i64> poison)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %nxv16i8 = call <vscale x 16 x i8> @llvm.smulh(<vscale x 16 x i8> poison, <vscale x 16 x i8> poison)
+  %nxv8i16 = call <vscale x 8 x i16> @llvm.smulh(<vscale x 8 x i16> poison, <vscale x 8 x i16> poison)
+  %nxv4i32 = call <vscale x 4 x i32> @llvm.smulh(<vscale x 4 x i32> poison, <vscale x 4 x i32> poison)
+  %nxv2i64 = call <vscale x 2 x i64> @llvm.smulh(<vscale x 2 x i64> poison, <vscale x 2 x i64> poison)
+  ret void
+}
+
+define void @umulh_scalable() {
+; CHECK-LABEL: 'umulh_scalable'
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv16i8 = call <vscale x 16 x i8> @llvm.umulh.nxv16i8(<vscale x 16 x i8> poison, <vscale x 16 x i8> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv8i16 = call <vscale x 8 x i16> @llvm.umulh.nxv8i16(<vscale x 8 x i16> poison, <vscale x 8 x i16> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv4i32 = call <vscale x 4 x i32> @llvm.umulh.nxv4i32(<vscale x 4 x i32> poison, <vscale x 4 x i32> poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %nxv2i64 = call <vscale x 2 x i64> @llvm.umulh.nxv2i64(<vscale x 2 x i64> poison, <vscale x 2 x i64> poison)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %nxv16i8 = call <vscale x 16 x i8> @llvm.umulh(<vscale x 16 x i8> poison, <vscale x 16 x i8> poison)
+  %nxv8i16 = call <vscale x 8 x i16> @llvm.umulh(<vscale x 8 x i16> poison, <vscale x 8 x i16> poison)
+  %nxv4i32 = call <vscale x 4 x i32> @llvm.umulh(<vscale x 4 x i32> poison, <vscale x 4 x i32> poison)
+  %nxv2i64 = call <vscale x 2 x i64> @llvm.umulh(<vscale x 2 x i64> poison, <vscale x 2 x i64> poison)
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; SVE: {{.*}}
+; SVE2: {{.*}}
diff --git a/llvm/test/Analysis/CostModel/AArch64/mulh.ll b/llvm/test/Analysis/CostModel/AArch64/mulh.ll
new file mode 100644
index 0000000000000..eabcbc64acbd8
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/AArch64/mulh.ll
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -mtriple=aarch64 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,NEON
+; RUN: opt < %s -mtriple=aarch64 -mattr=+sve -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,SVE
+
+define void @smulh() {
+; CHECK-LABEL: 'smulh'
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 1 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.smulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.smulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.smulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.smulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.smulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @umulh() {
+; CHECK-LABEL: 'umulh'
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 2 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 1 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; CHECK-NEXT:  Cost Model: Found costs of 4 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; CHECK-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.umulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.umulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.umulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.umulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.umulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @smulh_64() {
+; NEON-LABEL: 'smulh_64'
+; NEON-NEXT:  Cost Model: Found costs of 5 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; NEON-NEXT:  Cost Model: Found costs of 5 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:18 CodeSize:12 Lat:18 SizeLat:18 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:12 CodeSize:10 Lat:12 SizeLat:12 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; SVE-LABEL: 'smulh_64'
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; SVE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.smulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.smulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.smulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.smulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @umulh_64() {
+; NEON-LABEL: 'umulh_64'
+; NEON-NEXT:  Cost Model: Found costs of 5 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; NEON-NEXT:  Cost Model: Found costs of 5 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:18 CodeSize:12 Lat:18 SizeLat:18 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:12 CodeSize:10 Lat:12 SizeLat:12 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; SVE-LABEL: 'umulh_64'
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; SVE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.umulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.umulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.umulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.umulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @smulh_128() {
+; NEON-LABEL: 'smulh_128'
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:25 CodeSize:21 Lat:25 SizeLat:25 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; SVE-LABEL: 'smulh_128'
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; SVE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.smulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.smulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.smulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.smulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
+
+define void @umulh_128() {
+; NEON-LABEL: 'umulh_128'
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; NEON-NEXT:  Cost Model: Found costs of 1 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:25 CodeSize:21 Lat:25 SizeLat:25 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; NEON-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; SVE-LABEL: 'umulh_128'
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; SVE-NEXT:  Cost Model: Found costs of 2 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; SVE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.umulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.umulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.umulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.umulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
diff --git a/llvm/test/Analysis/CostModel/RISCV/mulh.ll b/llvm/test/Analysis/CostModel/RISCV/mulh.ll
new file mode 100644
index 0000000000000..68b823a62d8e4
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/RISCV/mulh.ll
@@ -0,0 +1,267 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -mtriple=riscv32 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-I,RV32I
+; RUN: opt < %s -mtriple=riscv64 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-I,RV64I
+; RUN: opt < %s -mtriple=riscv32 -mattr=+m -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-M,RV32M,RV32IM
+; RUN: opt < %s -mtriple=riscv64 -mattr=+m -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-M,RV64M,RV64IM
+; RUN: opt < %s -mtriple=riscv32 -mattr=+m,+v -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-M,RV32M,CHECK-V,RV32V
+; RUN: opt < %s -mtriple=riscv64 -mattr=+m,+v -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-M,RV64M,CHECK-V,RV64V
+
+define void @smulh() {
+; RV32I-LABEL: 'smulh'
+; RV32I-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; RV32I-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:12 CodeSize:5 Lat:5 SizeLat:5 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'smulh'
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32M-LABEL: 'smulh'
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 4 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 8 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; RV32M-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64M-LABEL: 'smulh'
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 4 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; RV64M-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.smulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.smulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.smulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.smulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.smulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @umulh() {
+; RV32I-LABEL: 'umulh'
+; RV32I-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; RV32I-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:12 CodeSize:5 Lat:5 SizeLat:5 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'umulh'
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; RV64I-NEXT:  Cost Model: Found costs of 4 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32M-LABEL: 'umulh'
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 1 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 4 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; RV32M-NEXT:  Cost Model: Found costs of 8 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; RV32M-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64M-LABEL: 'umulh'
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 1 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; RV64M-NEXT:  Cost Model: Found costs of 4 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; RV64M-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.umulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.umulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.umulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.umulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.umulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @smulh_64() {
+; RV32I-LABEL: 'smulh_64'
+; RV32I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:6 Lat:6 SizeLat:6 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'smulh_64'
+; RV64I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:6 Lat:6 SizeLat:6 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32IM-LABEL: 'smulh_64'
+; RV32IM-NEXT:  Cost Model: Found costs of 16 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 4 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 4 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64IM-LABEL: 'smulh_64'
+; RV64IM-NEXT:  Cost Model: Found costs of 16 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 8 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 4 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 1 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; CHECK-V-LABEL: 'smulh_64'
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.smulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.smulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.smulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.smulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @umulh_64() {
+; RV32I-LABEL: 'umulh_64'
+; RV32I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:6 Lat:6 SizeLat:6 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:5 SizeLat:5 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'umulh_64'
+; RV64I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:6 Lat:6 SizeLat:6 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:4 SizeLat:4 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32IM-LABEL: 'umulh_64'
+; RV32IM-NEXT:  Cost Model: Found costs of 16 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 4 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 4 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64IM-LABEL: 'umulh_64'
+; RV64IM-NEXT:  Cost Model: Found costs of 16 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 8 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 4 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 1 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; CHECK-V-LABEL: 'umulh_64'
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.umulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.umulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.umulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.umulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @smulh_128() {
+; RV32I-LABEL: 'smulh_128'
+; RV32I-NEXT:  Cost Model: Found costs of RThru:64 CodeSize:34 Lat:34 SizeLat:34 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:20 CodeSize:10 Lat:10 SizeLat:10 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:8 Lat:8 SizeLat:8 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'smulh_128'
+; RV64I-NEXT:  Cost Model: Found costs of RThru:64 CodeSize:34 Lat:34 SizeLat:34 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:6 Lat:6 SizeLat:6 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32IM-LABEL: 'smulh_128'
+; RV32IM-NEXT:  Cost Model: Found costs of 32 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 16 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64IM-LABEL: 'smulh_128'
+; RV64IM-NEXT:  Cost Model: Found costs of 32 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 16 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 8 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 4 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; CHECK-V-LABEL: 'smulh_128'
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.smulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.smulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.smulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.smulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
+
+define void @umulh_128() {
+; RV32I-LABEL: 'umulh_128'
+; RV32I-NEXT:  Cost Model: Found costs of RThru:64 CodeSize:34 Lat:34 SizeLat:34 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:20 CodeSize:10 Lat:10 SizeLat:10 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:8 Lat:8 SizeLat:8 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV32I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64I-LABEL: 'umulh_128'
+; RV64I-NEXT:  Cost Model: Found costs of RThru:64 CodeSize:34 Lat:34 SizeLat:34 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:32 CodeSize:18 Lat:18 SizeLat:18 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:16 CodeSize:10 Lat:10 SizeLat:10 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:6 Lat:6 SizeLat:6 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV64I-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV32IM-LABEL: 'umulh_128'
+; RV32IM-NEXT:  Cost Model: Found costs of 32 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 16 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of 8 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV32IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; RV64IM-LABEL: 'umulh_128'
+; RV64IM-NEXT:  Cost Model: Found costs of 32 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 16 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 8 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of 4 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; RV64IM-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; CHECK-V-LABEL: 'umulh_128'
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of 2 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; CHECK-V-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.umulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.umulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.umulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.umulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
+; CHECK-I: {{.*}}
+; CHECK-M: {{.*}}
+; RV32V: {{.*}}
+; RV64V: {{.*}}
diff --git a/llvm/test/Analysis/CostModel/X86/mulh.ll b/llvm/test/Analysis/CostModel/X86/mulh.ll
new file mode 100644
index 0000000000000..86c393a318c94
--- /dev/null
+++ b/llvm/test/Analysis/CostModel/X86/mulh.ll
@@ -0,0 +1,300 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -mtriple=x86_64-- -mcpu=x86-64 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,SSE,SSE2
+; RUN: opt < %s -mtriple=x86_64-- -mcpu=x86-64-v2 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,SSE,SSE42
+; RUN: opt < %s -mtriple=x86_64-- -mcpu=x86-64-v3 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,AVX,AVX2
+; RUN: opt < %s -mtriple=x86_64-- -mcpu=x86-64-v4 -passes="print<cost-model>" -cost-kind=all -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,AVX,AVX512
+
+define void @smulh() {
+; SSE-LABEL: 'smulh'
+; SSE-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:9 SizeLat:5 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'smulh'
+; AVX2-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:9 SizeLat:5 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'smulh'
+; AVX512-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.smulh.i8(i8 poison, i8 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.smulh.i16(i16 poison, i16 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:9 SizeLat:5 for: %i32 = call i32 @llvm.smulh.i32(i32 poison, i32 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:6 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.smulh.i64(i64 poison, i64 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.smulh.i128(i128 poison, i128 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.smulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.smulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.smulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.smulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.smulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @umulh() {
+; SSE-LABEL: 'umulh'
+; SSE-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:3 CodeSize:2 Lat:7 SizeLat:3 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'umulh'
+; AVX2-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:3 CodeSize:2 Lat:7 SizeLat:3 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:14 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'umulh'
+; AVX512-NEXT:  Cost Model: Found costs of RThru:5 CodeSize:4 Lat:7 SizeLat:4 for: %i8 = call i8 @llvm.umulh.i8(i8 poison, i8 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:4 CodeSize:4 Lat:7 SizeLat:4 for: %i16 = call i16 @llvm.umulh.i16(i16 poison, i16 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:2 CodeSize:2 Lat:7 SizeLat:3 for: %i32 = call i32 @llvm.umulh.i32(i32 poison, i32 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:6 CodeSize:5 Lat:15 SizeLat:7 for: %i64 = call i64 @llvm.umulh.i64(i64 poison, i64 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:10 CodeSize:7 Lat:27 SizeLat:11 for: %i128 = call i128 @llvm.umulh.i128(i128 poison, i128 poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %i8 = call i8 @llvm.umulh(i8 poison, i8 poison)
+  %i16 = call i16 @llvm.umulh(i16 poison, i16 poison)
+  %i32 = call i32 @llvm.umulh(i32 poison, i32 poison)
+  %i64 = call i64 @llvm.umulh(i64 poison, i64 poison)
+  %i128 = call i128 @llvm.umulh(i128 poison, i128 poison)
+  ret void
+}
+
+define void @smulh_64() {
+; SSE-LABEL: 'smulh_64'
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'smulh_64'
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'smulh_64'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.smulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.smulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.smulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:6 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.smulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.smulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.smulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.smulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.smulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @umulh_64() {
+; SSE-LABEL: 'umulh_64'
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'umulh_64'
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:8 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'umulh_64'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v8i8 = call <8 x i8> @llvm.umulh.v8i8(<8 x i8> poison, <8 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v4i16 = call <4 x i16> @llvm.umulh.v4i16(<4 x i16> poison, <4 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v2i32 = call <2 x i32> @llvm.umulh.v2i32(<2 x i32> poison, <2 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:6 CodeSize:5 Lat:15 SizeLat:7 for: %v1i64 = call <1 x i64> @llvm.umulh.v1i64(<1 x i64> poison, <1 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v8i8 = call <8 x i8> @llvm.umulh(<8 x i8> poison, <8 x i8> poison)
+  %v4i16 = call <4 x i16> @llvm.umulh(<4 x i16> poison, <4 x i16> poison)
+  %v2i32 = call <2 x i32> @llvm.umulh(<2 x i32> poison, <2 x i32> poison)
+  %v1i64 = call <1 x i64> @llvm.umulh(<1 x i64> poison, <1 x i64> poison)
+  ret void
+}
+
+define void @smulh_128() {
+; SSE-LABEL: 'smulh_128'
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:19 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'smulh_128'
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:19 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'smulh_128'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.smulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.smulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.smulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:15 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.smulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.smulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.smulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.smulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.smulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
+
+define void @umulh_128() {
+; SSE-LABEL: 'umulh_128'
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:19 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'umulh_128'
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:19 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'umulh_128'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v16i8 = call <16 x i8> @llvm.umulh.v16i8(<16 x i8> poison, <16 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v8i16 = call <8 x i16> @llvm.umulh.v8i16(<8 x i16> poison, <8 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v4i32 = call <4 x i32> @llvm.umulh.v4i32(<4 x i32> poison, <4 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:15 CodeSize:8 Lat:28 SizeLat:12 for: %v2i64 = call <2 x i64> @llvm.umulh.v2i64(<2 x i64> poison, <2 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v16i8 = call <16 x i8> @llvm.umulh(<16 x i8> poison, <16 x i8> poison)
+  %v8i16 = call <8 x i16> @llvm.umulh(<8 x i16> poison, <8 x i16> poison)
+  %v4i32 = call <4 x i32> @llvm.umulh(<4 x i32> poison, <4 x i32> poison)
+  %v2i64 = call <2 x i64> @llvm.umulh(<2 x i64> poison, <2 x i64> poison)
+  ret void
+}
+
+define void @smulh_256() {
+; SSE-LABEL: 'smulh_256'
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v32i8 = call <32 x i8> @llvm.smulh.v32i8(<32 x i8> poison, <32 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v16i16 = call <16 x i16> @llvm.smulh.v16i16(<16 x i16> poison, <16 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v8i32 = call <8 x i32> @llvm.smulh.v8i32(<8 x i32> poison, <8 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:38 CodeSize:12 Lat:52 SizeLat:20 for: %v4i64 = call <4 x i64> @llvm.smulh.v4i64(<4 x i64> poison, <4 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'smulh_256'
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v32i8 = call <32 x i8> @llvm.smulh.v32i8(<32 x i8> poison, <32 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 1 for: %v16i16 = call <16 x i16> @llvm.smulh.v16i16(<16 x i16> poison, <16 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 2 for: %v8i32 = call <8 x i32> @llvm.smulh.v8i32(<8 x i32> poison, <8 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:41 CodeSize:12 Lat:52 SizeLat:20 for: %v4i64 = call <4 x i64> @llvm.smulh.v4i64(<4 x i64> poison, <4 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'smulh_256'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v32i8 = call <32 x i8> @llvm.smulh.v32i8(<32 x i8> poison, <32 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v16i16 = call <16 x i16> @llvm.smulh.v16i16(<16 x i16> poison, <16 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v8i32 = call <8 x i32> @llvm.smulh.v8i32(<8 x i32> poison, <8 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v4i64 = call <4 x i64> @llvm.smulh.v4i64(<4 x i64> poison, <4 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v32i8 = call <32 x i8> @llvm.smulh(<32 x i8> poison, <32 x i8> poison)
+  %v16i16 = call <16 x i16> @llvm.smulh(<16 x i16> poison, <16 x i16> poison)
+  %v8i32 = call <8 x i32> @llvm.smulh(<8 x i32> poison, <8 x i32> poison)
+  %v4i64 = call <4 x i64> @llvm.smulh(<4 x i64> poison, <4 x i64> poison)
+  ret void
+}
+
+define void @umulh_256() {
+; SSE-LABEL: 'umulh_256'
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v32i8 = call <32 x i8> @llvm.umulh.v32i8(<32 x i8> poison, <32 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v16i16 = call <16 x i16> @llvm.umulh.v16i16(<16 x i16> poison, <16 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 4 for: %v8i32 = call <8 x i32> @llvm.umulh.v8i32(<8 x i32> poison, <8 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:38 CodeSize:12 Lat:52 SizeLat:20 for: %v4i64 = call <4 x i64> @llvm.umulh.v4i64(<4 x i64> poison, <4 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX-LABEL: 'umulh_256'
+; AVX-NEXT:  Cost Model: Found costs of 2 for: %v32i8 = call <32 x i8> @llvm.umulh.v32i8(<32 x i8> poison, <32 x i8> poison)
+; AVX-NEXT:  Cost Model: Found costs of 1 for: %v16i16 = call <16 x i16> @llvm.umulh.v16i16(<16 x i16> poison, <16 x i16> poison)
+; AVX-NEXT:  Cost Model: Found costs of 2 for: %v8i32 = call <8 x i32> @llvm.umulh.v8i32(<8 x i32> poison, <8 x i32> poison)
+; AVX-NEXT:  Cost Model: Found costs of 2 for: %v4i64 = call <4 x i64> @llvm.umulh.v4i64(<4 x i64> poison, <4 x i64> poison)
+; AVX-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v32i8 = call <32 x i8> @llvm.umulh(<32 x i8> poison, <32 x i8> poison)
+  %v16i16 = call <16 x i16> @llvm.umulh(<16 x i16> poison, <16 x i16> poison)
+  %v8i32 = call <8 x i32> @llvm.umulh(<8 x i32> poison, <8 x i32> poison)
+  %v4i64 = call <4 x i64> @llvm.umulh(<4 x i64> poison, <4 x i64> poison)
+  ret void
+}
+
+define void @smulh_512() {
+; SSE-LABEL: 'smulh_512'
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v64i8 = call <64 x i8> @llvm.smulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v32i16 = call <32 x i16> @llvm.smulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v16i32 = call <16 x i32> @llvm.smulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:76 CodeSize:20 Lat:100 SizeLat:36 for: %v8i64 = call <8 x i64> @llvm.smulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'smulh_512'
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v64i8 = call <64 x i8> @llvm.smulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v32i16 = call <32 x i16> @llvm.smulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v16i32 = call <16 x i32> @llvm.smulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:82 CodeSize:20 Lat:100 SizeLat:36 for: %v8i64 = call <8 x i64> @llvm.smulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'smulh_512'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v64i8 = call <64 x i8> @llvm.smulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v32i16 = call <32 x i16> @llvm.smulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v16i32 = call <16 x i32> @llvm.smulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v8i64 = call <8 x i64> @llvm.smulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v64i8 = call <64 x i8> @llvm.smulh(<64 x i8> poison, <64 x i8> poison)
+  %v32i16 = call <32 x i16> @llvm.smulh(<32 x i16> poison, <32 x i16> poison)
+  %v16i32 = call <16 x i32> @llvm.smulh(<16 x i32> poison, <16 x i32> poison)
+  %v8i64 = call <8 x i64> @llvm.smulh(<8 x i64> poison, <8 x i64> poison)
+  ret void
+}
+
+define void @umulh_512() {
+; SSE-LABEL: 'umulh_512'
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v64i8 = call <64 x i8> @llvm.umulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v32i16 = call <32 x i16> @llvm.umulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; SSE-NEXT:  Cost Model: Found costs of 8 for: %v16i32 = call <16 x i32> @llvm.umulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:76 CodeSize:20 Lat:100 SizeLat:36 for: %v8i64 = call <8 x i64> @llvm.umulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; SSE-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX2-LABEL: 'umulh_512'
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v64i8 = call <64 x i8> @llvm.umulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v32i16 = call <32 x i16> @llvm.umulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v16i32 = call <16 x i32> @llvm.umulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; AVX2-NEXT:  Cost Model: Found costs of 4 for: %v8i64 = call <8 x i64> @llvm.umulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; AVX2-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+; AVX512-LABEL: 'umulh_512'
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v64i8 = call <64 x i8> @llvm.umulh.v64i8(<64 x i8> poison, <64 x i8> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 1 for: %v32i16 = call <32 x i16> @llvm.umulh.v32i16(<32 x i16> poison, <32 x i16> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v16i32 = call <16 x i32> @llvm.umulh.v16i32(<16 x i32> poison, <16 x i32> poison)
+; AVX512-NEXT:  Cost Model: Found costs of 2 for: %v8i64 = call <8 x i64> @llvm.umulh.v8i64(<8 x i64> poison, <8 x i64> poison)
+; AVX512-NEXT:  Cost Model: Found costs of RThru:0 CodeSize:1 Lat:1 SizeLat:1 for: ret void
+;
+  %v64i8 = call <64 x i8> @llvm.umulh(<64 x i8> poison, <64 x i8> poison)
+  %v32i16 = call <32 x i16> @llvm.umulh(<32 x i16> poison, <32 x i16> poison)
+  %v16i32 = call <16 x i32> @llvm.umulh(<16 x i32> poison, <16 x i32> poison)
+  %v8i64 = call <8 x i64> @llvm.umulh(<8 x i64> poison, <8 x i64> poison)
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
+; SSE2: {{.*}}
+; SSE42: {{.*}}



More information about the llvm-commits mailing list