[clang] [clang][clangIR]: X86 vperm2f128 builtin implementation (PR #208851)
Lucas Ribeiro Lima via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 18 16:13:43 PDT 2026
https://github.com/lucaslive974 updated https://github.com/llvm/llvm-project/pull/208851
>From c6c41770f079ee6c7736c8d0264563d1ebc34f3a Mon Sep 17 00:00:00 2001
From: Lucas-Ribeiro-Lima <lucasribeirolima974 at gmail.com>
Date: Thu, 9 Jul 2026 16:56:33 -0300
Subject: [PATCH 1/6] [clang][clangIR]: X86 vperm2f128 builtin implementation
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 53 +++++-
.../CIR/CodeGenBuiltins/X86/avx-vperm2f128 | 171 ++++++++++++++++++
2 files changed, 220 insertions(+), 4 deletions(-)
create mode 100644 clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 1b9a07ba10b04..02ad9c5eb6edd 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -811,6 +811,53 @@ static mlir::Value emitX86MaskedLoad(CIRGenBuilderTy &builder,
return builder.createMaskedLoad(loc, ty, ptr, alignment, maskVec, ops[1]);
}
+static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
+ mlir::Location loc, mlir::Type resType,
+ llvm::SmallVector<mlir::Value> ops) {
+ auto inputType = cast<cir::VectorType>(ops[0].getType());
+ const unsigned imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]);
+ const uint8_t zeroMask = 0x08, controlMask = 0x0F;
+
+ // Mirror hardware and OGCG behaviour returning a zero vector
+ if ((imm & zeroMask) && (imm & zeroMask << 4))
+ return builder.getZero(loc, resType);
+
+ mlir::Value lanes[2];
+ llvm::SmallVector<int64_t, 64> mask;
+ const unsigned numElts = inputType.getSize();
+
+ // We must evaluated each lane(128 bits) separetely
+ for (auto lane : llvm::seq(0, 2)) {
+ uint8_t controlBits = (imm >> (lane * 4)) & controlMask;
+
+ llvm::Boolean isZeroBit = controlBits & zeroMask;
+ llvm::Boolean isSourceA = controlBits <= 1;
+ llvm::Boolean isLowerHalf = controlBits % 2 == 0;
+
+ // Determine the source for this lane
+ if (isZeroBit)
+ lanes[lane] = builder.getZero(loc, resType);
+ else
+ lanes[lane] = isSourceA ? ops[0] : ops[1];
+
+ // We need to built the shuffle mask selecting the right half
+ for (auto elt : llvm::seq(0u, numElts / 2u)) {
+ unsigned idx = (lane * numElts) + elt;
+ if (!isLowerHalf)
+ idx += numElts / 2;
+ mask.push_back(idx);
+ }
+ }
+
+ mlir::Value shuffleResult =
+ builder.createVecShuffle(loc, lanes[0], lanes[1], mask);
+
+ if (inputType != resType)
+ builder.createBitcast(shuffleResult, resType);
+
+ return shuffleResult;
+}
+
static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder,
unsigned builtinID,
mlir::Location loc,
@@ -1855,10 +1902,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_vperm2f128_ps256:
case X86::BI__builtin_ia32_vperm2f128_si256:
case X86::BI__builtin_ia32_permti256:
- cgm.errorNYI(expr->getSourceRange(),
- std::string("unimplemented X86 builtin call: ") +
- getContext().BuiltinInfo.getName(builtinID));
- return mlir::Value{};
+ return emitX86VPerm2f128(builder, getLoc(expr->getExprLoc()),
+ this->convertType(expr->getType()), ops);
case X86::BI__builtin_ia32_pslldqi128_byteshift:
case X86::BI__builtin_ia32_pslldqi256_byteshift:
case X86::BI__builtin_ia32_pslldqi512_byteshift:
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128 b/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128
new file mode 100644
index 0000000000000..e46e4d342df98
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128
@@ -0,0 +1,171 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -target-feature +avx
+// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -target-feature +avx
+// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.og.ll -target-feature +avx
+// RUN: FileCheck --input-file=%t.og.ll %s -check-prefix=OGCG
+
+// Tests perm2f128 byte permutation intrinsics implementation in ClangIR
+// Compares CIR emission, LLVM lowering, and original CodeGen output
+
+typedef float __m256 __attribute__((__vector_size__(32)));
+typedef int __m256i __attribute__((__vector_size__(32)));
+typedef double __m256d __attribute__((__vector_size__(32)));
+
+//First operand sources half lane(64 bits)
+#define A_LOW 0x00
+#define A_HIGH 0x01
+
+//Second operand sources half lane(64 bits)
+#define B_LOW 0x02
+#define B_HIGH 0x03
+
+//Zero overwritte bit
+#define ZERO_BIT 0x08
+
+//Macro helpers to set control bits
+#define LANES(low, high) (((low) | ((high) << 4)))
+
+//The test will be named following this convention for selected lanes
+// test_perm2f128pd_a_{{lane/zero}}_b_{{lane/zero}}
+
+__m256d test_perm2f128pd_a_low_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_low_b_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, B_LOW));
+}
+
+__m256d test_perm2f128pd_a_low_b_high(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_low_b_high
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, B_HIGH));
+}
+
+__m256d test_perm2f128pd_a_high_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_high_b_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, B_LOW));
+}
+
+__m256d test_perm2f128pd_a_high_b_high(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_high_b_high
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, B_HIGH));
+}
+
+__m256d test_perm2f128pd_b_high_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_b_high_b_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(B_HIGH, B_LOW));
+}
+
+__m256d test_perm2f128pd_a_high_a_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_high_a_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, A_LOW));
+}
+
+
+__m256d test_perm2f128pd_a_low_a_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_low_a_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, A_LOW));
+}
+
+__m256d test_perm2f128pd_a_high_a_high(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_high_a_high
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, A_LOW));
+}
+
+//Zero bit tests
+__m256d test_perm2f128pd_a_zero_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_zero_b_low
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT, B_LOW));
+}
+
+//Zero bit tests
+__m256d test_perm2f128pd_a_low_b_zero(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_low_b_zero
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, ZERO_BIT));
+}
+
+//Zero bit overwrittes control bits
+__m256d test_perm2f128pd_a_zero_overwritte(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_zero_overwritte
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT | A_LOW, B_LOW));
+}
+
+__m256d test_perm2f128pd_b_zero_overwritte(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_b_zero_overwritte
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, ZERO_BIT | B_LOW));
+}
+
+__m256d test_perm2f128pd_ab_zero_overwritte(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_ab_zero_overwritte
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
+ //LLVM: store <4 x double> zeroinitializer
+ //OGCG: ret <4 x double> zeroinitializer
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT | A_LOW, ZERO_BIT | B_LOW));
+}
+
+__m256d test_perm2f128pd_a_zero_b_zero(__m256d a, __m256d b) {
+ //CIR-LABEL: test_perm2f128pd_a_zero_b_zero
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
+ //LLVM: store <4 x double> zeroinitializer
+ //OGCG: ret <4 x double> zeroinitializer
+ return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT, ZERO_BIT));
+}
+
+__m256 test_perm2f128ps_bitcast(__m256 a, __m256 b) {
+ //CIR-LABEL: test_perm2f128ps_bitcast
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !cir.float>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !cir.float>
+ //LLVM: {{.*}} = shufflevector <8 x float> {{.*}}, <8 x float> {{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
+ //OGCG: {{.*}} = shufflevector <8 x float> {{.*}}, <8 x float> {{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
+ return __builtin_ia32_vperm2f128_ps256(a, b, LANES(A_LOW, B_HIGH));
+}
+
+__m256 test_perm2f128si_bitcast(__m256 a, __m256 b) {
+ //CIR-LABEL: test_perm2f128si_bitcast
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !s32i>
+ //CIR: {{.*}} = cir.cast bitcast {{.*}} : !cir.vector<8 x !s32i> -> !cir.vector<8 x !cir.float>
+ //LLVM: {{.*}} = shufflevector <8 x i32> {{.*}} <8 x i32> {{.*}} <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
+ //LLVM: {{.*}} = bitcast <8 x i32> {{.*}} to <8 x float>
+ //OGCG: {{.*}} = shufflevector <8 x i32> {{.*}} <8 x i32> {{.*}} <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
+ //OGCG: {{.*}} = bitcast <8 x i32> {{.*}} to <8 x float>
+ return __builtin_ia32_vperm2f128_si256(a, b, LANES(A_LOW, B_HIGH));
+}
>From 24d0a5fdbd7e3d3e1dab2d555b09b6a601e11e12 Mon Sep 17 00:00:00 2001
From: Lucas-Ribeiro-Lima <lucasribeirolima974 at gmail.com>
Date: Sun, 12 Jul 2026 21:23:37 -0300
Subject: [PATCH 2/6] [clang][ClangIR][style]: modernize-macro-to-enum
clang-tidy
---
.../X86/{avx-vperm2f128 => avx-vperm2f128.c} | 20 +++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
rename clang/test/CIR/CodeGenBuiltins/X86/{avx-vperm2f128 => avx-vperm2f128.c} (98%)
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128 b/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
similarity index 98%
rename from clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128
rename to clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
index e46e4d342df98..a2c546885f3d6 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
@@ -12,16 +12,16 @@ typedef float __m256 __attribute__((__vector_size__(32)));
typedef int __m256i __attribute__((__vector_size__(32)));
typedef double __m256d __attribute__((__vector_size__(32)));
-//First operand sources half lane(64 bits)
-#define A_LOW 0x00
-#define A_HIGH 0x01
-
-//Second operand sources half lane(64 bits)
-#define B_LOW 0x02
-#define B_HIGH 0x03
-
-//Zero overwritte bit
-#define ZERO_BIT 0x08
+enum VPerm2F128LaneControl {
+ //First operand 128 bits lane
+ A_LOW= 0x00,
+ A_HIGH = 0x01,
+ //Second operand 128 bits lane
+ B_LOW = 0x02,
+ B_HIGH = 0x03,
+ //Zero overwritte bit
+ ZERO_BIT = 0x08,
+};
//Macro helpers to set control bits
#define LANES(low, high) (((low) | ((high) << 4)))
>From 1cd4242b4bad0d398e54eb07573c80792f0932fe Mon Sep 17 00:00:00 2001
From: lucaslive974 <lucasribeirolima974 at gmail.com>
Date: Fri, 17 Jul 2026 09:23:13 -0300
Subject: [PATCH 3/6] [clang][ClangIR]: Refactor x86 permutate2f128 builtin to
mirror original codegen.
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 38 ++--
.../CIR/CodeGenBuiltins/X86/avx-builtins.c | 36 ++++
.../X86/avx-shuffle-builtins.c | 181 ++++++++++++++++++
.../CIR/CodeGenBuiltins/X86/avx-vperm2f128.c | 171 -----------------
4 files changed, 233 insertions(+), 193 deletions(-)
delete mode 100644 clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 02ad9c5eb6edd..3e23c5e21b209 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -812,15 +812,18 @@ static mlir::Value emitX86MaskedLoad(CIRGenBuilderTy &builder,
}
static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
- mlir::Location loc, mlir::Type resType,
+ mlir::Location loc,
llvm::SmallVector<mlir::Value> ops) {
auto inputType = cast<cir::VectorType>(ops[0].getType());
- const unsigned imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]);
- const uint8_t zeroMask = 0x08, controlMask = 0x0F;
+ assert(!inputType.getIsScalable() &&
+ "This is only intended for fixed-width vectors");
+
+ const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]) & 0xFF;
+ mlir::Value zeroVec = builder.getZero(loc, inputType);
// Mirror hardware and OGCG behaviour returning a zero vector
- if ((imm & zeroMask) && (imm & zeroMask << 4))
- return builder.getZero(loc, resType);
+ if ((imm & 0x80) && (imm & 0x08))
+ return zeroVec;
mlir::Value lanes[2];
llvm::SmallVector<int64_t, 64> mask;
@@ -828,34 +831,26 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
// We must evaluated each lane(128 bits) separetely
for (auto lane : llvm::seq(0, 2)) {
- uint8_t controlBits = (imm >> (lane * 4)) & controlMask;
-
- llvm::Boolean isZeroBit = controlBits & zeroMask;
- llvm::Boolean isSourceA = controlBits <= 1;
- llvm::Boolean isLowerHalf = controlBits % 2 == 0;
+ llvm::Boolean isZeroBit = imm & (1 << ((lane * 4) + 3)),
+ isSourceB = imm & (1 << ((lane * 4) + 1)),
+ isUpperHalf = imm & (1 << (lane * 4));
// Determine the source for this lane
if (isZeroBit)
- lanes[lane] = builder.getZero(loc, resType);
+ lanes[lane] = zeroVec;
else
- lanes[lane] = isSourceA ? ops[0] : ops[1];
+ lanes[lane] = isSourceB ? ops[1] : ops[0];
// We need to built the shuffle mask selecting the right half
for (auto elt : llvm::seq(0u, numElts / 2u)) {
unsigned idx = (lane * numElts) + elt;
- if (!isLowerHalf)
+ if (isUpperHalf)
idx += numElts / 2;
mask.push_back(idx);
}
}
- mlir::Value shuffleResult =
- builder.createVecShuffle(loc, lanes[0], lanes[1], mask);
-
- if (inputType != resType)
- builder.createBitcast(shuffleResult, resType);
-
- return shuffleResult;
+ return builder.createVecShuffle(loc, lanes[0], lanes[1], mask);
}
static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder,
@@ -1902,8 +1897,7 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) {
case X86::BI__builtin_ia32_vperm2f128_ps256:
case X86::BI__builtin_ia32_vperm2f128_si256:
case X86::BI__builtin_ia32_permti256:
- return emitX86VPerm2f128(builder, getLoc(expr->getExprLoc()),
- this->convertType(expr->getType()), ops);
+ return emitX86VPerm2f128(builder, getLoc(expr->getExprLoc()), ops);
case X86::BI__builtin_ia32_pslldqi128_byteshift:
case X86::BI__builtin_ia32_pslldqi256_byteshift:
case X86::BI__builtin_ia32_pslldqi512_byteshift:
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
index 01ca55994ce50..ff3a3f46f6807 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
@@ -215,3 +215,39 @@ __m256d test_mm256_permute_pd(__m256d A) {
// OGCG: shufflevector <4 x double> %{{.*}}, <4 x double> poison, <4 x i32> <i32 1, i32 0, i32 3, i32 2>
return _mm256_permute_pd(A, 0x5);
}
+
+__m256d test_mm256_permute2f128_pd(__m256d A, __m256d B) {
+ // CIR-LABEL: test_mm256_permute2f128_pd
+ // CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+
+ // LLVM-LABEL: test_mm256_permute2f128_pd
+ // LLVM: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+
+ // OGCG-LABEL: test_mm256_permute2f128_pd
+ // OGCG: shufflevector <4 x double> %{{.*}}, <4 x double> %{{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ return _mm256_permute2f128_pd(A, B, 0x31);
+}
+
+__m256 test_mm256_permute2f128_ps(__m256 A, __m256 B) {
+ // CIR-LABEL: test_mm256_permute2f128_ps
+ // CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !cir.float>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !cir.float>
+
+ // LLVM-LABEL: test_mm256_permute2f128_ps
+ // LLVM: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
+
+ // OGCG-LABEL: test_mm256_permute2f128_ps
+ // OGCG: shufflevector <8 x float> %{{.*}}, <8 x float> %{{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
+ return _mm256_permute2f128_ps(A, B, 0x13);
+}
+
+__m256i test_mm256_permute2f128_si256(__m256i A, __m256i B) {
+ // CIR-LABEL: test_mm256_permute2f128_si256
+ // CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<8> : !s32i, #cir.int<9> : !s32i, #cir.int<10> : !s32i, #cir.int<11> : !s32i] : !cir.vector<8 x !s32i>
+
+ // LLVM-LABEL: test_mm256_permute2f128_si256
+ // LLVM: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+
+ // OGCG-LABEL: test_mm256_permute2f128_si256
+ // OGCG: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ return _mm256_permute2f128_si256(A, B, 0x20);
+}
\ No newline at end of file
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-shuffle-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-shuffle-builtins.c
index 8e30ca93ef6cd..1e12a95e0f408 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-shuffle-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-shuffle-builtins.c
@@ -160,3 +160,184 @@ __m256i test1_mm256_insertf128_si256(__m256i a, __m128i b) {
// OGCG-NEXT: ret <4 x i64> [[TMP2]]
return _mm256_insertf128_si256(a, b, 1);
}
+
+__m256d test_mm256_permute2f128_pd(__m256d a, __m256d b) {
+ // CIR-LABEL: test_mm256_permute2f128_pd
+ // CIR: [[VPERM:%.*]] = cir.vec.shuffle({{.*}}, {{.*}}: !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+ // CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
+
+ // LLVM-LABEL: define dso_local <4 x double> @test_mm256_permute2f128_pd(
+ // LLVM: [[VPERM:%.*]] = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ // LLVM: ret <4 x double> {{.*}}
+
+ // OGCG-LABEL: define dso_local <4 x double> @test_mm256_permute2f128_pd(
+ // OGCG-SAME: <4 x double> noundef [[A:%.*]], <4 x double> noundef [[B:%.*]]) #[[ATTR0]] {
+ // OGCG-NEXT: [[ENTRY:.*:]]
+ // OGCG-NEXT: [[VPERM:%.*]] = shufflevector <4 x double> [[A]], <4 x double> [[B]], <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ // OGCG-NEXT: ret <4 x double> [[VPERM]]
+ return _mm256_permute2f128_pd(a, b, 0x31);
+}
+
+__m256 test_mm256_permute2f128_ps(__m256 a, __m256 b) {
+ // CIR-LABEL: test_mm256_permute2f128_ps
+ // CIR: [[VPERM:%.*]] = cir.vec.shuffle({{.*}}, {{.*}}: !cir.vector<8 x !cir.float>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !cir.float>
+ // CIR: cir.return {{.*}} : !cir.vector<8 x !cir.float>
+
+ // LLVM-LABEL: define dso_local <8 x float> @test_mm256_permute2f128_ps(
+ // LLVM: [[VPERM:%.*]] = shufflevector <8 x float> {{.*}}, <8 x float> {{.*}}, <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
+ // LLVM: ret <8 x float> {{.*}}
+
+ // OGCG-LABEL: define dso_local <8 x float> @test_mm256_permute2f128_ps(
+ // OGCG-SAME: <8 x float> noundef [[A:%.*]], <8 x float> noundef [[B:%.*]]) #[[ATTR0]] {
+ // OGCG-NEXT: [[ENTRY:.*:]]
+ // OGCG-NEXT: [[VPERM:%.*]] = shufflevector <8 x float> [[B]], <8 x float> [[A]], <8 x i32> <i32 4, i32 5, i32 6, i32 7, i32 12, i32 13, i32 14, i32 15>
+ // OGCG-NEXT: ret <8 x float> [[VPERM]]
+ return _mm256_permute2f128_ps(a, b, 0x13);
+}
+
+__m256i test_mm256_permute2f128_si256(__m256i a, __m256i b) {
+ // CIR-LABEL: test_mm256_permute2f128_si256
+ // CIR: [[TMP0:%.*]] = cir.cast bitcast {{.*}} : !cir.vector<4 x !s64i> -> !cir.vector<8 x !s32i>
+ // CIR: [[TMP1:%.*]] = cir.cast bitcast {{.*}} : !cir.vector<4 x !s64i> -> !cir.vector<8 x !s32i>
+ // CIR: [[VPERM:%.*]] = cir.vec.shuffle([[TMP0]], [[TMP1]] : !cir.vector<8 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<8> : !s32i, #cir.int<9> : !s32i, #cir.int<10> : !s32i, #cir.int<11> : !s32i] : !cir.vector<8 x !s32i>
+ // CIR: [[TMP2:%.*]] = cir.cast bitcast [[VPERM]] : !cir.vector<8 x !s32i> -> !cir.vector<4 x !s64i>
+ // CIR: cir.return {{.*}} : !cir.vector<4 x !s64i>
+
+ // LLVM-LABEL: define dso_local <4 x i64> @test_mm256_permute2f128_si256(
+ // LLVM: [[TMP0:%.*]] = bitcast <4 x i64> {{.*}} to <8 x i32>
+ // LLVM: [[TMP1:%.*]] = bitcast <4 x i64> {{.*}} to <8 x i32>
+ // LLVM: [[VPERM:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // LLVM: [[TMP2:%.*]] = bitcast <8 x i32> [[VPERM]] to <4 x i64>
+ // LLVM: ret <4 x i64> {{.*}}
+
+ // OGCG-LABEL: define dso_local <4 x i64> @test_mm256_permute2f128_si256(
+ // OGCG-SAME: <4 x i64> noundef [[A:%.*]], <4 x i64> noundef [[B:%.*]]) #[[ATTR0]] {
+ // OGCG-NEXT: [[ENTRY:.*:]]
+ // OGCG-NEXT: [[TMP0:%.*]] = bitcast <4 x i64> [[A]] to <8 x i32>
+ // OGCG-NEXT: [[TMP1:%.*]] = bitcast <4 x i64> [[B]] to <8 x i32>
+ // OGCG-NEXT: [[VPERM:%.*]] = shufflevector <8 x i32> [[TMP0]], <8 x i32> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
+ // OGCG-NEXT: [[TMP2:%.*]] = bitcast <8 x i32> [[VPERM]] to <4 x i64>
+ // OGCG-NEXT: ret <4 x i64> [[TMP2]]
+ return _mm256_permute2f128_si256(a, b, 0x20);
+}
+
+// The test will be named following this convention for selected lanes
+// test_mm_permute2f128_pd_[[low_half]]_{{lane/zero}}_[[high_half]]_{{lane/zero}}
+
+__m256d test_mm256_permute2f128_pd_a_low_b_high(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_low_b_high
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
+ return _mm256_permute2f128_pd(a, b, 0x30);
+}
+
+__m256d test_mm256_permute2f128_pd_a_high_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_high_b_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x21);
+}
+
+__m256d test_mm256_permute2f128_pd_b_high_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_b_high_b_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x23);
+}
+
+__m256d test_mm256_permute2f128_pd_a_high_a_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_high_a_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x01);
+}
+
+
+__m256d test_mm256_permute2f128_pd_a_low_a_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_low_a_low
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x00);
+}
+
+__m256d test_mm256_permute2f128_pd_a_high_a_high(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_high_a_high
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
+ return _mm256_permute2f128_pd(a, b, 0x11);
+}
+
+//zero bit tests
+__m256d test_mm256_permute2f128_pd_a_zero_b_low(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_zero_b_low
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x28);
+}
+
+//zero bit tests
+__m256d test_mm256_permute2f128_pd_a_low_b_zero(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_low_b_zero
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0x80);
+}
+
+__m256d test_mm256_permute2f128_pd_b_zero_overwritte(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_b_zero_overwritte
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
+
+ //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+
+ //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
+ return _mm256_permute2f128_pd(a, b, 0xA0);
+}
+
+__m256d test_mm256_permute2f128_pd_ab_zero_overwritte(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_ab_zero_overwritte
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
+
+ //LLVM: store <4 x double> zeroinitializer
+
+ //OGCG: ret <4 x double> zeroinitializer
+ return _mm256_permute2f128_pd(a, b, 0xA8);
+}
+
+__m256d test_mm256_permute2f128_pd_a_zero_b_zero(__m256d a, __m256d b) {
+ //CIR-LABEL: test_mm256_permute2f128_pd_a_zero_b_zero
+ //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
+ //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
+
+ //LLVM: store <4 x double> zeroinitializer
+
+ //OGCG: ret <4 x double> zeroinitializer
+ return _mm256_permute2f128_pd(a, b, 0x88);
+}
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
deleted file mode 100644
index a2c546885f3d6..0000000000000
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-vperm2f128.c
+++ /dev/null
@@ -1,171 +0,0 @@
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -target-feature +avx
-// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -target-feature +avx
-// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM
-// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.og.ll -target-feature +avx
-// RUN: FileCheck --input-file=%t.og.ll %s -check-prefix=OGCG
-
-// Tests perm2f128 byte permutation intrinsics implementation in ClangIR
-// Compares CIR emission, LLVM lowering, and original CodeGen output
-
-typedef float __m256 __attribute__((__vector_size__(32)));
-typedef int __m256i __attribute__((__vector_size__(32)));
-typedef double __m256d __attribute__((__vector_size__(32)));
-
-enum VPerm2F128LaneControl {
- //First operand 128 bits lane
- A_LOW= 0x00,
- A_HIGH = 0x01,
- //Second operand 128 bits lane
- B_LOW = 0x02,
- B_HIGH = 0x03,
- //Zero overwritte bit
- ZERO_BIT = 0x08,
-};
-
-//Macro helpers to set control bits
-#define LANES(low, high) (((low) | ((high) << 4)))
-
-//The test will be named following this convention for selected lanes
-// test_perm2f128pd_a_{{lane/zero}}_b_{{lane/zero}}
-
-__m256d test_perm2f128pd_a_low_b_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_low_b_low
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, B_LOW));
-}
-
-__m256d test_perm2f128pd_a_low_b_high(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_low_b_high
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 6, i32 7>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, B_HIGH));
-}
-
-__m256d test_perm2f128pd_a_high_b_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_high_b_low
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, B_LOW));
-}
-
-__m256d test_perm2f128pd_a_high_b_high(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_high_b_high
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 6, i32 7>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, B_HIGH));
-}
-
-__m256d test_perm2f128pd_b_high_b_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_b_high_b_low
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(B_HIGH, B_LOW));
-}
-
-__m256d test_perm2f128pd_a_high_a_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_high_a_low
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 2, i32 3, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_HIGH, A_LOW));
-}
-
-
-__m256d test_perm2f128pd_a_low_a_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_low_a_low
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, A_LOW));
-}
-
-__m256d test_perm2f128pd_a_high_a_high(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_high_a_high
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, A_LOW));
-}
-
-//Zero bit tests
-__m256d test_perm2f128pd_a_zero_b_low(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_zero_b_low
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT, B_LOW));
-}
-
-//Zero bit tests
-__m256d test_perm2f128pd_a_low_b_zero(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_low_b_zero
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, ZERO_BIT));
-}
-
-//Zero bit overwrittes control bits
-__m256d test_perm2f128pd_a_zero_overwritte(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_zero_overwritte
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> zeroinitializer, <4 x double> {{.*}}, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT | A_LOW, B_LOW));
-}
-
-__m256d test_perm2f128pd_b_zero_overwritte(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_b_zero_overwritte
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<4 x !cir.double>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<4> : !s32i, #cir.int<5> : !s32i] : !cir.vector<4 x !cir.double>
- //LLVM: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- //OGCG: {{.*}} = shufflevector <4 x double> {{.*}}, <4 x double> zeroinitializer, <4 x i32> <i32 0, i32 1, i32 4, i32 5>
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(A_LOW, ZERO_BIT | B_LOW));
-}
-
-__m256d test_perm2f128pd_ab_zero_overwritte(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_ab_zero_overwritte
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
- //LLVM: store <4 x double> zeroinitializer
- //OGCG: ret <4 x double> zeroinitializer
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT | A_LOW, ZERO_BIT | B_LOW));
-}
-
-__m256d test_perm2f128pd_a_zero_b_zero(__m256d a, __m256d b) {
- //CIR-LABEL: test_perm2f128pd_a_zero_b_zero
- //CIR: {{.*}} = cir.const #cir.zero : !cir.vector<4 x !cir.double>
- //CIR: cir.return {{.*}} : !cir.vector<4 x !cir.double>
- //LLVM: store <4 x double> zeroinitializer
- //OGCG: ret <4 x double> zeroinitializer
- return __builtin_ia32_vperm2f128_pd256(a, b, LANES(ZERO_BIT, ZERO_BIT));
-}
-
-__m256 test_perm2f128ps_bitcast(__m256 a, __m256 b) {
- //CIR-LABEL: test_perm2f128ps_bitcast
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !cir.float>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !cir.float>
- //LLVM: {{.*}} = shufflevector <8 x float> {{.*}}, <8 x float> {{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
- //OGCG: {{.*}} = shufflevector <8 x float> {{.*}}, <8 x float> {{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
- return __builtin_ia32_vperm2f128_ps256(a, b, LANES(A_LOW, B_HIGH));
-}
-
-__m256 test_perm2f128si_bitcast(__m256 a, __m256 b) {
- //CIR-LABEL: test_perm2f128si_bitcast
- //CIR: {{.*}} = cir.vec.shuffle({{.*}}, {{.*}} : !cir.vector<8 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i, #cir.int<2> : !s32i, #cir.int<3> : !s32i, #cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<8 x !s32i>
- //CIR: {{.*}} = cir.cast bitcast {{.*}} : !cir.vector<8 x !s32i> -> !cir.vector<8 x !cir.float>
- //LLVM: {{.*}} = shufflevector <8 x i32> {{.*}} <8 x i32> {{.*}} <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
- //LLVM: {{.*}} = bitcast <8 x i32> {{.*}} to <8 x float>
- //OGCG: {{.*}} = shufflevector <8 x i32> {{.*}} <8 x i32> {{.*}} <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 12, i32 13, i32 14, i32 15>
- //OGCG: {{.*}} = bitcast <8 x i32> {{.*}} to <8 x float>
- return __builtin_ia32_vperm2f128_si256(a, b, LANES(A_LOW, B_HIGH));
-}
>From abef45d38b0ddd0ab27dcc84b5745fc047a5d922 Mon Sep 17 00:00:00 2001
From: lucaslive974 <lucasribeirolima974 at gmail.com>
Date: Fri, 17 Jul 2026 09:24:15 -0300
Subject: [PATCH 4/6] fix missing line-feed
---
clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
index ff3a3f46f6807..a833970fff421 100644
--- a/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
+++ b/clang/test/CIR/CodeGenBuiltins/X86/avx-builtins.c
@@ -250,4 +250,4 @@ __m256i test_mm256_permute2f128_si256(__m256i A, __m256i B) {
// OGCG-LABEL: test_mm256_permute2f128_si256
// OGCG: shufflevector <8 x i32> %{{.*}}, <8 x i32> %{{.*}}, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 8, i32 9, i32 10, i32 11>
return _mm256_permute2f128_si256(A, B, 0x20);
-}
\ No newline at end of file
+}
>From a38f9f78f8d49fe60b9e21b281b322419646f755 Mon Sep 17 00:00:00 2001
From: lucaslive974 <lucasribeirolima974 at gmail.com>
Date: Sat, 18 Jul 2026 20:01:02 -0300
Subject: [PATCH 5/6] [clang][ClangIR]: Optimize createVecShuffle signature.
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 3e23c5e21b209..52312e907bf21 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -818,7 +818,7 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
assert(!inputType.getIsScalable() &&
"This is only intended for fixed-width vectors");
- const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]) & 0xFF;
+ const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]);
mlir::Value zeroVec = builder.getZero(loc, inputType);
// Mirror hardware and OGCG behaviour returning a zero vector
@@ -826,14 +826,15 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
return zeroVec;
mlir::Value lanes[2];
- llvm::SmallVector<int64_t, 64> mask;
- const unsigned numElts = inputType.getSize();
+ llvm::SmallVector<mlir::Attribute, 64> mask;
+ cir::IntType i32Ty = builder.getSInt32Ty();
+ const unsigned numElts = inputType.getSize();
// We must evaluated each lane(128 bits) separetely
for (auto lane : llvm::seq(0, 2)) {
- llvm::Boolean isZeroBit = imm & (1 << ((lane * 4) + 3)),
- isSourceB = imm & (1 << ((lane * 4) + 1)),
- isUpperHalf = imm & (1 << (lane * 4));
+ bool isZeroBit = imm & (1 << ((lane * 4) + 3)),
+ isSourceB = imm & (1 << ((lane * 4) + 1)),
+ isUpperHalf = imm & (1 << (lane * 4));
// Determine the source for this lane
if (isZeroBit)
@@ -846,7 +847,7 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
unsigned idx = (lane * numElts) + elt;
if (isUpperHalf)
idx += numElts / 2;
- mask.push_back(idx);
+ mask.push_back(cir::IntAttr::get(i32Ty, idx));
}
}
>From 7ade8b3ec2a151b3951cc208bdf117d96ead67e2 Mon Sep 17 00:00:00 2001
From: Lucas Ribeiro Lima <lucasribeirolima974 at gmail.com>
Date: Sat, 18 Jul 2026 20:13:32 -0300
Subject: [PATCH 6/6] [clang][clangIR][NFC]: Update comment
Co-authored-by: Andy Kaylor <akaylor at nvidia.com>
---
clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index 52312e907bf21..2369c654833cf 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -821,7 +821,7 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy &builder,
const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]);
mlir::Value zeroVec = builder.getZero(loc, inputType);
- // Mirror hardware and OGCG behaviour returning a zero vector
+ // If both lanes are zero, return a zero result.
if ((imm & 0x80) && (imm & 0x08))
return zeroVec;
More information about the cfe-commits
mailing list