[clang] [CIR][X86] Lower pmulhw/pmulhuw builtins to smulh/umulh (PR #231978)

Arseniy Obolenskiy via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 14 09:55:36 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/231978

>From 9c660149450a674a156a9b3dd5ab5a47bd247a5b Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 14 Oct 2026 18:22:21 +0200
Subject: [PATCH] [CIR][X86] Lower pmulhw/pmulhuw builtins to smulh/umulh

The x86 pmulh intrinsics were removed in #227663, so CIR hit NYI on these builtins
---
 clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp    | 10 ++++++++
 .../CIR/CodeGenBuiltins/X86/avx2-builtins.c   | 24 +++++++++++++++++++
 .../CodeGenBuiltins/X86/avx512bw-builtins.c   | 24 +++++++++++++++++++
 .../CIR/CodeGenBuiltins/X86/sse2-builtins.c   | 24 +++++++++++++++++++
 4 files changed, 82 insertions(+)

diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index febcaa7459edb0..2bec45883554fc 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -2365,6 +2365,16 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
     mlir::Value arg = ops[0];
     return cir::SqrtOp::create(builder, loc, arg).getResult();
   }
+  case X86::BI__builtin_ia32_pmulhw128:
+  case X86::BI__builtin_ia32_pmulhw256:
+  case X86::BI__builtin_ia32_pmulhw512:
+    return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "smulh",
+                                       ops[0].getType(), ops);
+  case X86::BI__builtin_ia32_pmulhuw128:
+  case X86::BI__builtin_ia32_pmulhuw256:
+  case X86::BI__builtin_ia32_pmulhuw512:
+    return builder.emitIntrinsicCallOp(getLoc(expr->getExprLoc()), "umulh",
+                                       ops[0].getType(), ops);
   case X86::BI__builtin_ia32_pmuludq128:
   case X86::BI__builtin_ia32_pmuludq256:
   case X86::BI__builtin_ia32_pmuludq512: {
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx2-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx2-builtins.c
index c6225d47671f2f..c5c807aaa5d7aa 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx2-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx2-builtins.c
@@ -176,6 +176,30 @@ __m256i test_mm256_mul_epi32(__m256i a, __m256i b) {
   return _mm256_mul_epi32(a, b);
 }
 
+__m256i test_mm256_mulhi_epi16(__m256i a, __m256i b) {
+  // CIR-LABEL: _mm256_mulhi_epi16
+  // CIR: cir.call_llvm_intrinsic "smulh" %{{.*}}, %{{.*}} : (!cir.vector<16 x !s16i>, !cir.vector<16 x !s16i>) -> !cir.vector<16 x !s16i>
+
+  // LLVM-LABEL: test_mm256_mulhi_epi16
+  // LLVM: call <16 x i16> @llvm.smulh.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm256_mulhi_epi16
+  // OGCG: call <16 x i16> @llvm.smulh.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  return _mm256_mulhi_epi16(a, b);
+}
+
+__m256i test_mm256_mulhi_epu16(__m256i a, __m256i b) {
+  // CIR-LABEL: _mm256_mulhi_epu16
+  // CIR: cir.call_llvm_intrinsic "umulh" %{{.*}}, %{{.*}} : (!cir.vector<16 x !u16i>, !cir.vector<16 x !u16i>) -> !cir.vector<16 x !u16i>
+
+  // LLVM-LABEL: test_mm256_mulhi_epu16
+  // LLVM: call <16 x i16> @llvm.umulh.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm256_mulhi_epu16
+  // OGCG: call <16 x i16> @llvm.umulh.v16i16(<16 x i16> %{{.*}}, <16 x i16> %{{.*}})
+  return _mm256_mulhi_epu16(a, b);
+}
+
 __m256i test_mm256_alignr_epi8(__m256i a, __m256i b) {
   // CIR-LABEL: _mm256_alignr_epi8
   // CIR: {{.*}} = cir.vec.shuffle(%{{.*}}, {{.*}} : !cir.vector<32 x {{![us]8i}}>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i, #cir.int<8> : !s32i, #cir.int<9> : !s32i, #cir.int<10> : !s32i, #cir.int<11> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i, #cir.int<32> : !s32i, #cir.int<33> : !s32i, #cir.int<18> : !s32i, #cir.int<19> : !s32i, #cir.int<20> : !s32i, #cir.int<21> : !s32i, #cir.int<22> : !s32i, #cir.int<23> : !s32i, #cir.int<24> : !s32i, #cir.int<25> : !s32i, #cir.int<26> : !s32i, #cir.int<27> : !s32i, #cir.int<28> : !s32i, #cir.int<29> : !s32i, #cir.int<30> : !s32i, #cir.int<31> : !s32i, #cir.int<48> : !s32i, #cir.int<49> : !s32i] : !cir.vector<32 x {{![us]8i}}>
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx512bw-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx512bw-builtins.c
index 525e703eabe2bd..6a872f4e9dccfa 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx512bw-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx512bw-builtins.c
@@ -866,6 +866,30 @@ __m256i test_mm512_maskz_cvtepi16_epi8(__mmask32 __M, __m512i __A) {
   return _mm512_maskz_cvtepi16_epi8(__M, __A);
 }
 
+__m512i test_mm512_mulhi_epi16(__m512i __A, __m512i __B) {
+  // CIR-LABEL: _mm512_mulhi_epi16
+  // CIR: cir.call_llvm_intrinsic "smulh" %{{.*}}, %{{.*}} : (!cir.vector<32 x !s16i>, !cir.vector<32 x !s16i>) -> !cir.vector<32 x !s16i>
+
+  // LLVM-LABEL: test_mm512_mulhi_epi16
+  // LLVM: call <32 x i16> @llvm.smulh.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm512_mulhi_epi16
+  // OGCG: call <32 x i16> @llvm.smulh.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+  return _mm512_mulhi_epi16(__A, __B);
+}
+
+__m512i test_mm512_mulhi_epu16(__m512i __A, __m512i __B) {
+  // CIR-LABEL: _mm512_mulhi_epu16
+  // CIR: cir.call_llvm_intrinsic "umulh" %{{.*}}, %{{.*}} : (!cir.vector<32 x !u16i>, !cir.vector<32 x !u16i>) -> !cir.vector<32 x !u16i>
+
+  // LLVM-LABEL: test_mm512_mulhi_epu16
+  // LLVM: call <32 x i16> @llvm.umulh.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm512_mulhi_epu16
+  // OGCG: call <32 x i16> @llvm.umulh.v32i16(<32 x i16> %{{.*}}, <32 x i16> %{{.*}})
+  return _mm512_mulhi_epu16(__A, __B);
+}
+
 __m512i test_mm512_alignr_epi8(__m512i __A,__m512i __B) {
   // CIR-LABEL: _mm512_alignr_epi8
   // CIR: %{{.*}} = cir.vec.shuffle(%{{.*}}, %{{.*}} : !cir.vector<64 x {{!s8i|!u8i}}>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i, #cir.int<8> : !s32i, #cir.int<9> : !s32i, #cir.int<10> : !s32i, #cir.int<11> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i, #cir.int<64> : !s32i, #cir.int<65> : !s32i, #cir.int<18> : !s32i, #cir.int<19> : !s32i, #cir.int<20> : !s32i, #cir.int<21> : !s32i, #cir.int<22> : !s32i, #cir.int<23> : !s32i, #cir.int<24> : !s32i, #cir.int<25> : !s32i, #cir.int<26> : !s32i, #cir.int<27> : !s32i, #cir.int<28> : !s32i, #cir.int<29> : !s32i, #cir.int<30> : !s32i, #cir.int<31> : !s32i, #cir.int<80> : !s32i, #cir.int<81> : !s32i, #cir.int<34> : !s32i, #cir.int<35> : !s32i, #cir.int<36> : !s32i, #cir.int<37> : !s32i, #cir.int<38> : !s32i, #cir.int<39> : !s32i, #cir.int<40> : !s32i, #cir.int<41> : !s32i, #cir.int<42> : !s32i, #cir.int<43> : !s32i, #cir.int<44> : !s32i, #cir.int<45> : !s32i, #cir.int<46> : !s32i, #cir.int<47> : !s32i, #cir.int<96> : !s32i, #cir.int<97> : !s32i, #cir.int<50> : !s32i, #cir.int<51> : !s32i, #cir.int<52> : !s32i, #cir.int<53> : !s32i, #cir.int<54> : !s32i, #cir.int<55> : !s32i, #cir.int<56> : !s32i, #cir.int<57> : !s32i, #cir.int<58> : !s32i, #cir.int<59> : !s32i, #cir.int<60> : !s32i, #cir.int<61> : !s32i, #cir.int<62> : !s32i, #cir.int<63> : !s32i, #cir.int<112> : !s32i, #cir.int<113> : !s32i] : !cir.vector<64 x {{!s8i|!u8i}}>
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/sse2-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/sse2-builtins.c
index 112407689cf7b8..652fa103970781 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/sse2-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/sse2-builtins.c
@@ -182,3 +182,27 @@ __m128i test_mm_mul_epu32(__m128i A, __m128i B) {
 
   return _mm_mul_epu32(A, B);
 }
+
+__m128i test_mm_mulhi_epi16(__m128i A, __m128i B) {
+  // CIR-LABEL: _mm_mulhi_epi16
+  // CIR: cir.call_llvm_intrinsic "smulh" %{{.*}}, %{{.*}} : (!cir.vector<8 x !s16i>, !cir.vector<8 x !s16i>) -> !cir.vector<8 x !s16i>
+
+  // LLVM-LABEL: test_mm_mulhi_epi16
+  // LLVM: call <8 x i16> @llvm.smulh.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm_mulhi_epi16
+  // OGCG: call <8 x i16> @llvm.smulh.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+  return _mm_mulhi_epi16(A, B);
+}
+
+__m128i test_mm_mulhi_epu16(__m128i A, __m128i B) {
+  // CIR-LABEL: _mm_mulhi_epu16
+  // CIR: cir.call_llvm_intrinsic "umulh" %{{.*}}, %{{.*}} : (!cir.vector<8 x !u16i>, !cir.vector<8 x !u16i>) -> !cir.vector<8 x !u16i>
+
+  // LLVM-LABEL: test_mm_mulhi_epu16
+  // LLVM: call <8 x i16> @llvm.umulh.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+
+  // OGCG-LABEL: test_mm_mulhi_epu16
+  // OGCG: call <8 x i16> @llvm.umulh.v8i16(<8 x i16> %{{.*}}, <8 x i16> %{{.*}})
+  return _mm_mulhi_epu16(A, B);
+}



More information about the cfe-commits mailing list