[clang] [compiler-rt] [X86] Remove x86 PDEP/PEXT clang intrinsics and rely on generic elementwise implementations (PR #204969)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 25 06:52:48 PDT 2026
https://github.com/RKSimon updated https://github.com/llvm/llvm-project/pull/204969
>From fde1d39b4d7771580bc5a4bf531c2f89782853d1 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Sun, 21 Jun 2026 10:37:57 +0100
Subject: [PATCH] [X86] Remove x86 PDEP/PEXT clang intrinsics and rely on
generic elementwise implementations
---
clang/include/clang/Basic/BuiltinsX86.td | 2 -
clang/include/clang/Basic/BuiltinsX86_64.td | 2 -
clang/lib/AST/ByteCode/InterpBuiltin.cpp | 9 +++
clang/lib/AST/ExprConstant.cpp | 5 +-
clang/lib/CodeGen/TargetBuiltins/X86.cpp | 10 ---
clang/lib/Headers/bmi2intrin.h | 8 +--
compiler-rt/lib/msan/tests/msan_test.cpp | 71 +++++++++++----------
7 files changed, 50 insertions(+), 57 deletions(-)
diff --git a/clang/include/clang/Basic/BuiltinsX86.td b/clang/include/clang/Basic/BuiltinsX86.td
index b0f95d98b8471..7d42209e959de 100644
--- a/clang/include/clang/Basic/BuiltinsX86.td
+++ b/clang/include/clang/Basic/BuiltinsX86.td
@@ -817,8 +817,6 @@ let Attributes = [NoThrow, Const, Constexpr] in {
let Features = "bmi2", Attributes = [NoThrow, Const, Constexpr] in {
def bzhi_si : X86Builtin<"unsigned int(unsigned int, unsigned int)">;
- def pdep_si : X86Builtin<"unsigned int(unsigned int, unsigned int)">;
- def pext_si : X86Builtin<"unsigned int(unsigned int, unsigned int)">;
}
let Features = "tbm", Attributes = [NoThrow, Const, Constexpr] in {
diff --git a/clang/include/clang/Basic/BuiltinsX86_64.td b/clang/include/clang/Basic/BuiltinsX86_64.td
index baba21d47f93f..02b48674bac51 100644
--- a/clang/include/clang/Basic/BuiltinsX86_64.td
+++ b/clang/include/clang/Basic/BuiltinsX86_64.td
@@ -137,8 +137,6 @@ let Attributes = [NoThrow, Const, Constexpr] in {
let Features = "bmi2", Attributes = [NoThrow, Const, Constexpr] in {
def bzhi_di : X86Builtin<"unsigned long long int(unsigned long long int, unsigned long long int)">;
- def pdep_di : X86Builtin<"unsigned long long int(unsigned long long int, unsigned long long int)">;
- def pext_di : X86Builtin<"unsigned long long int(unsigned long long int, unsigned long long int)">;
}
let Features = "tbm", Attributes = [NoThrow, Const, Constexpr] in {
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index b76f13833da14..4abaa02dd8f00 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -5336,6 +5336,15 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
});
+
+ case Builtin::BI__builtin_elementwise_pdep:
+ return interp__builtin_elementwise_int_binop(S, OpPC, Call,
+ llvm::APIntOps::pdep);
+
+ case Builtin::BI__builtin_elementwise_pext:
+ return interp__builtin_elementwise_int_binop(S, OpPC, Call,
+ llvm::APIntOps::pext);
+
case X86::BI__builtin_ia32_extract128i256:
case X86::BI__builtin_ia32_vextractf128_pd256:
case X86::BI__builtin_ia32_vextractf128_ps256:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 1d359339b9104..3e22edf124879 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -18029,8 +18029,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(Val.countTrailingZeros(), E);
}
- case clang::X86::BI__builtin_ia32_pdep_si:
- case clang::X86::BI__builtin_ia32_pdep_di:
case Builtin::BI__builtin_elementwise_pdep: {
APSInt Val, Msk;
if (!EvaluateInteger(E->getArg(0), Val, Info) ||
@@ -18039,8 +18037,6 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return Success(llvm::APIntOps::pdep(Val, Msk), E);
}
- case clang::X86::BI__builtin_ia32_pext_si:
- case clang::X86::BI__builtin_ia32_pext_di:
case Builtin::BI__builtin_elementwise_pext: {
APSInt Val, Msk;
if (!EvaluateInteger(E->getArg(0), Val, Info) ||
@@ -18048,6 +18044,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
return false;
return Success(llvm::APIntOps::pext(Val, Msk), E);
}
+
case X86::BI__builtin_ia32_ptestz128:
case X86::BI__builtin_ia32_ptestz256:
case X86::BI__builtin_ia32_vtestzps:
diff --git a/clang/lib/CodeGen/TargetBuiltins/X86.cpp b/clang/lib/CodeGen/TargetBuiltins/X86.cpp
index 50125a71fcd5f..acfeb9967cd2f 100644
--- a/clang/lib/CodeGen/TargetBuiltins/X86.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/X86.cpp
@@ -976,16 +976,6 @@ Value *CodeGenFunction::EmitX86BuiltinExpr(unsigned BuiltinID,
Function *F = CGM.getIntrinsic(Intrinsic::cttz, Ops[0]->getType());
return Builder.CreateCall(F, {Ops[0], Builder.getInt1(false)});
}
- case X86::BI__builtin_ia32_pdep_si:
- case X86::BI__builtin_ia32_pdep_di: {
- Function *F = CGM.getIntrinsic(Intrinsic::pdep, Ops[0]->getType());
- return Builder.CreateCall(F, Ops);
- }
- case X86::BI__builtin_ia32_pext_si:
- case X86::BI__builtin_ia32_pext_di: {
- Function *F = CGM.getIntrinsic(Intrinsic::pext, Ops[0]->getType());
- return Builder.CreateCall(F, Ops);
- }
case X86::BI__builtin_ia32_undef128:
case X86::BI__builtin_ia32_undef256:
case X86::BI__builtin_ia32_undef512:
diff --git a/clang/lib/Headers/bmi2intrin.h b/clang/lib/Headers/bmi2intrin.h
index bdb61b13fb83b..38e6d1d28da8b 100644
--- a/clang/lib/Headers/bmi2intrin.h
+++ b/clang/lib/Headers/bmi2intrin.h
@@ -74,7 +74,7 @@ _bzhi_u32(unsigned int __X, unsigned int __Y) {
/// \returns The 32-bit result.
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_pdep_u32(unsigned int __X, unsigned int __Y) {
- return __builtin_ia32_pdep_si(__X, __Y);
+ return __builtin_elementwise_pdep(__X, __Y);
}
/// Extract (gather) bits from the unsigned 32-bit integer \a __X into the
@@ -103,7 +103,7 @@ _pdep_u32(unsigned int __X, unsigned int __Y) {
/// \returns The 32-bit result.
static __inline__ unsigned int __DEFAULT_FN_ATTRS
_pext_u32(unsigned int __X, unsigned int __Y) {
- return __builtin_ia32_pext_si(__X, __Y);
+ return __builtin_elementwise_pext(__X, __Y);
}
/// Multiplies the unsigned 32-bit integers \a __X and \a __Y to form a
@@ -186,7 +186,7 @@ _bzhi_u64(unsigned long long __X, unsigned long long __Y) {
/// \returns The 64-bit result.
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_pdep_u64(unsigned long long __X, unsigned long long __Y) {
- return __builtin_ia32_pdep_di(__X, __Y);
+ return __builtin_elementwise_pdep(__X, __Y);
}
/// Extract (gather) bits from the unsigned 64-bit integer \a __X into the
@@ -215,7 +215,7 @@ _pdep_u64(unsigned long long __X, unsigned long long __Y) {
/// \returns The 64-bit result.
static __inline__ unsigned long long __DEFAULT_FN_ATTRS
_pext_u64(unsigned long long __X, unsigned long long __Y) {
- return __builtin_ia32_pext_di(__X, __Y);
+ return __builtin_elementwise_pext(__X, __Y);
}
/// Multiplies the unsigned 64-bit integers \a __X and \a __Y to form a
diff --git a/compiler-rt/lib/msan/tests/msan_test.cpp b/compiler-rt/lib/msan/tests/msan_test.cpp
index b0d8409d97ffc..5db99fbc967a3 100644
--- a/compiler-rt/lib/msan/tests/msan_test.cpp
+++ b/compiler-rt/lib/msan/tests/msan_test.cpp
@@ -4827,57 +4827,58 @@ static void TestBEXTR() {
0xABCDABCD, Poisoned<U8>(bextr_imm(7, 800), 0x80000000)));
}
-__attribute__((target("bmi,bmi2")))
+TEST(MemorySanitizer, Bmi) {
+ if (HaveBmi()) {
+ TestBZHI();
+ TestBEXTR();
+ }
+}
+#endif // defined(__x86_64__)
+
static void TestPDEP() {
U4 x = Poisoned<U4>(0, 0xFF00);
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_si(x, 0xFF));
- EXPECT_POISONED(__builtin_ia32_pdep_si(x, 0x1FF));
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_si(x, 0xFF00));
- EXPECT_POISONED(__builtin_ia32_pdep_si(x, 0x1FF00));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(x, 0xFFu));
+ EXPECT_POISONED(__builtin_elementwise_pdep(x, 0x1FFu));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(x, 0xFF00u));
+ EXPECT_POISONED(__builtin_elementwise_pdep(x, 0x1FF00u));
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_si(x, 0x1FF00) & 0xFF);
- EXPECT_POISONED(__builtin_ia32_pdep_si(0, Poisoned<U4>(0xF, 1)));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(x, 0x1FF00) & 0xFFu);
+ EXPECT_POISONED(__builtin_elementwise_pdep(0ull, Poisoned<U4>(0xF, 1)));
U8 y = Poisoned<U8>(0, 0xFF00);
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_di(y, 0xFF));
- EXPECT_POISONED(__builtin_ia32_pdep_di(y, 0x1FF));
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_di(y, 0xFF0000000000));
- EXPECT_POISONED(__builtin_ia32_pdep_di(y, 0x1FF000000000000));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(y, 0xFFull));
+ EXPECT_POISONED(__builtin_elementwise_pdep(y, 0x1FFull));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(y, 0xFF0000000000ull));
+ EXPECT_POISONED(__builtin_elementwise_pdep(y, 0x1FF000000000000ull));
- EXPECT_NOT_POISONED(__builtin_ia32_pdep_di(y, 0x1FF00) & 0xFF);
- EXPECT_POISONED(__builtin_ia32_pdep_di(0, Poisoned<U4>(0xF, 1)));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pdep(y, 0x1FF00ull) & 0xFF);
+ EXPECT_POISONED(__builtin_elementwise_pdep(0u, Poisoned<U4>(0xF, 1ull)));
}
-__attribute__((target("bmi,bmi2")))
static void TestPEXT() {
U4 x = Poisoned<U4>(0, 0xFF00);
- EXPECT_NOT_POISONED(__builtin_ia32_pext_si(x, 0xFF));
- EXPECT_POISONED(__builtin_ia32_pext_si(x, 0x1FF));
- EXPECT_POISONED(__builtin_ia32_pext_si(x, 0x100));
- EXPECT_POISONED(__builtin_ia32_pext_si(x, 0x1000));
- EXPECT_NOT_POISONED(__builtin_ia32_pext_si(x, 0x10000));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pext(x, 0xFFu));
+ EXPECT_POISONED(__builtin_elementwise_pext(x, 0x1FFu));
+ EXPECT_POISONED(__builtin_elementwise_pext(x, 0x100u));
+ EXPECT_POISONED(__builtin_elementwise_pext(x, 0x1000u));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pext(x, 0x10000u));
- EXPECT_POISONED(__builtin_ia32_pext_si(0xFF00, Poisoned<U4>(0xFF, 1)));
+ EXPECT_POISONED(__builtin_elementwise_pext(0xFF00u, Poisoned<U4>(0xFF, 1)));
- U8 y = Poisoned<U8>(0, 0xFF0000000000);
- EXPECT_NOT_POISONED(__builtin_ia32_pext_di(y, 0xFF00000000));
- EXPECT_POISONED(__builtin_ia32_pext_di(y, 0x1FF00000000));
- EXPECT_POISONED(__builtin_ia32_pext_di(y, 0x10000000000));
- EXPECT_POISONED(__builtin_ia32_pext_di(y, 0x100000000000));
- EXPECT_NOT_POISONED(__builtin_ia32_pext_di(y, 0x1000000000000));
+ U8 y = Poisoned<U8>(0, 0xFF0000000000ull);
+ EXPECT_NOT_POISONED(__builtin_elementwise_pext(y, 0xFF00000000ull));
+ EXPECT_POISONED(__builtin_elementwise_pext(y, 0x1FF00000000ull));
+ EXPECT_POISONED(__builtin_elementwise_pext(y, 0x10000000000ull));
+ EXPECT_POISONED(__builtin_elementwise_pext(y, 0x100000000000ull));
+ EXPECT_NOT_POISONED(__builtin_elementwise_pext(y, 0x1000000000000ull));
- EXPECT_POISONED(__builtin_ia32_pext_di(0xFF00, Poisoned<U8>(0xFF, 1)));
+ EXPECT_POISONED(__builtin_elementwise_pext(0xFF00ull, Poisoned<U8>(0xFF, 1ull)));
}
-TEST(MemorySanitizer, Bmi) {
- if (HaveBmi()) {
- TestBZHI();
- TestBEXTR();
- TestPDEP();
- TestPEXT();
- }
+TEST(MemorySanitizer, PackedBits) {
+ TestPDEP();
+ TestPEXT();
}
-#endif // defined(__x86_64__)
namespace {
volatile long z;
More information about the llvm-commits
mailing list