Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,27 @@ def CIR_ConstantOp : CIR_Op<"const", [
return boolAttr.getValue();
llvm_unreachable("Expected a BoolAttr in ConstantOp");
}
bool isAllOnesValue() {
Comment on lines 427 to +428
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
bool isAllOnesValue() {
}
bool isAllOnesValue() {

Comment on lines 427 to +428
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
bool isAllOnesValue() {
}
bool isAllOnesValue() {

// Check for -1 integers
if (auto intAttr = getValueAttr<cir::IntAttr>())
return intAttr.getValue().isAllOnes();

// Check for FP which are bitcasted from -1 integers
if (auto fpAttr = getValueAttr<cir::FPAttr>())
return fpAttr.getValue().bitcastToAPInt().isAllOnes();

// Check for constant vectors with splat values
if (cir::VectorType v = mlir::dyn_cast<cir::VectorType>(getType()))
if (auto vecAttr = getValueAttr<mlir::DenseElementsAttr>())
if (vecAttr.isSplat()) {
auto splatAttr = vecAttr.getSplatValue<mlir::Attribute>();
if (auto splatInt = mlir::dyn_cast<cir::IntAttr>(splatAttr)) {
return splatInt.getValue().isAllOnes();
}
}

return false;
}
}];

let hasFolder = 1;
Expand Down Expand Up @@ -1949,10 +1970,16 @@ def CIR_SelectOp : CIR_Op<"select", [
let summary = "Yield one of two values based on a boolean value";
let description = [{
The `cir.select` operation takes three operands. The first operand
`condition` is a boolean value of type `!cir.bool`. The second and the third
operand can be of any CIR types, but their types must be the same. If the
first operand is `true`, the operation yields its second operand. Otherwise,
the operation yields its third operand.
`condition` is either a boolean value of type `!cir.bool` or a boolean
vector of type `!cir.bool`. The second and the third operand can be of
any CIR types, but their types must be the same. If the first operand
is `true`, the operation yields its second operand. Otherwise, the
operation yields its third operand.

In the case where the first operand is a boolean vector, then the second
and third operand needs to also be of some vectors of the same type to
each other and that the number of elements of all three operands needs to
be the same as well.

Example:

Expand All @@ -1964,8 +1991,12 @@ def CIR_SelectOp : CIR_Op<"select", [
```
}];

let arguments = (ins CIR_BoolType:$condition, CIR_AnyType:$true_value,
CIR_AnyType:$false_value);
let arguments = (ins
CIR_ScalarOrVectorOf<CIR_BoolType>:$condition,
CIR_AnyType:$true_value,
CIR_AnyType:$false_value
);

let results = (outs CIR_AnyType:$result);

let assemblyFormat = [{
Expand All @@ -1978,6 +2009,7 @@ def CIR_SelectOp : CIR_Op<"select", [
}];

let hasFolder = 1;
let hasVerifier = 1;
}

//===----------------------------------------------------------------------===//
Expand Down
11 changes: 7 additions & 4 deletions clang/include/clang/CIR/Dialect/IR/CIRTypeConstraints.td
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,10 @@ def CIR_PtrToArray : CIR_PtrToType<CIR_AnyArrayType>;

def CIR_AnyVectorType : CIR_TypeBase<"::cir::VectorType", "vector type">;

def CIR_VectorElementType : AnyTypeOf<[CIR_AnyIntOrFloatType, CIR_AnyPtrType],
"any cir integer, floating point or pointer type"
> {
let cppFunctionName = "isValidVectorTypeElementType";
def CIR_VectorElementType
: AnyTypeOf<[CIR_AnyBoolType, CIR_AnyIntOrFloatType, CIR_AnyPtrType],
"any cir boolean, integer, floating point or pointer type"> {
let cppFunctionName = "isValidVectorTypeElementType";
}

class CIR_ElementTypePred<Pred pred> : SubstLeaves<"$_self",
Expand All @@ -266,6 +266,9 @@ class CIR_VectorTypeOf<list<Type> types, string summary = "">
"vector of " # CIR_TypeSummaries<types>.value,
summary)>;

// Type constraint accepting a either a type T or a vector of type T
class CIR_ScalarOrVectorOf<Type T> : AnyTypeOf<[T, CIR_VectorTypeOf<[T]>]>;

// Vector of integral type
def IntegerVector : Type<
And<[
Expand Down
62 changes: 61 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "clang/Basic/TargetBuiltins.h"
#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/ErrorHandling.h"

using namespace clang;
using namespace clang::CIRGen;
Expand Down Expand Up @@ -152,6 +153,41 @@ computeFullLaneShuffleMask(CIRGenFunction &cgf, const mlir::Value vec,
outIndices.resize(numElts);
}

static mlir::Value getBoolMaskVecValue(CIRGenBuilderTy &builder,
mlir::Location loc, mlir::Value mask,
unsigned numElems) {

cir::BoolType boolTy = builder.getBoolTy();
auto maskTy = cir::VectorType::get(
boolTy, cast<cir::IntType>(mask.getType()).getWidth());
mlir::Value maskVec = builder.createBitcast(mask, maskTy);

if (numElems < 8) {
SmallVector<mlir::Attribute> indices;
indices.reserve(numElems);
mlir::Type i32Ty = builder.getSInt32Ty();
for (auto i : llvm::seq<unsigned>(0, numElems))
indices.push_back(cir::IntAttr::get(i32Ty, i));

maskVec = builder.createVecShuffle(loc, maskVec, maskVec, indices);
}
return maskVec;
}

static mlir::Value emitX86Select(CIRGenBuilderTy &builder, mlir::Location loc,
mlir::Value mask, mlir::Value op0,
mlir::Value op1) {
auto constOp = mlir::dyn_cast_or_null<cir::ConstantOp>(mask.getDefiningOp());
// If the mask is all ones just return first argument.
if (constOp && constOp.isAllOnesValue())
return op0;

mask = getBoolMaskVecValue(builder, loc, mask,
cast<cir::VectorType>(op0.getType()).getSize());

return builder.createSelect(loc, mask, op0, op1);
}

static mlir::Value emitX86MaskAddLogic(CIRGenBuilderTy &builder,
mlir::Location loc,
const std::string &intrinsicName,
Expand Down Expand Up @@ -988,7 +1024,31 @@ mlir::Value CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID,
case X86::BI__builtin_ia32_extractf64x2_256_mask:
case X86::BI__builtin_ia32_extracti64x2_256_mask:
case X86::BI__builtin_ia32_extractf64x2_512_mask:
case X86::BI__builtin_ia32_extracti64x2_512_mask:
case X86::BI__builtin_ia32_extracti64x2_512_mask: {
mlir::Location loc = getLoc(expr->getExprLoc());
cir::VectorType dstTy = cast<cir::VectorType>(convertType(expr->getType()));
unsigned numElts = dstTy.getSize();
unsigned srcNumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
unsigned subVectors = srcNumElts / numElts;
assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 subvectors");
unsigned index =
ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();

index &= subVectors - 1; // Remove any extra bits.
index *= numElts;

int64_t indices[16];
std::iota(indices, indices + numElts, index);

mlir::Value poison =
builder.getConstant(loc, cir::PoisonAttr::get(ops[0].getType()));
mlir::Value res = builder.createVecShuffle(loc, ops[0], poison,
ArrayRef(indices, numElts));
if (ops.size() == 4)
res = emitX86Select(builder, loc, ops[3], res, ops[2]);

return res;
}
case X86::BI__builtin_ia32_vinsertf128_pd256:
case X86::BI__builtin_ia32_vinsertf128_ps256:
case X86::BI__builtin_ia32_vinsertf128_si256:
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2330,6 +2330,28 @@ OpFoldResult cir::SelectOp::fold(FoldAdaptor adaptor) {

return {};
}
LogicalResult cir::SelectOp::verify() {
Comment on lines 2332 to +2333
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
LogicalResult cir::SelectOp::verify() {
}
LogicalResult cir::SelectOp::verify() {

// INFO: No need to check if trueTy == falseTy here, it's verified by
// the AllTypesMatch trait already.
// We can go straight into getting the vector type.

auto condVecTy =
mlir::dyn_cast<cir::VectorType>(this->getCondition().getType());
auto trueVecTy =
mlir::dyn_cast<cir::VectorType>(this->getTrueValue().getType());
auto falseVecTy =
mlir::dyn_cast<cir::VectorType>(this->getFalseValue().getType());

if (condVecTy && (!trueVecTy || !falseVecTy)) {
// INFO: No need to check for size of vector here, it's verified by
// the AllTypesMatch trait already
return emitOpError()
<< "second and third operand must both be of the same "
"vector type when"
" the conditional operand is of vector boolean type";
}
return mlir::success();
}
Comment on lines 2332 to +2354
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
}
LogicalResult cir::SelectOp::verify() {
// INFO: No need to check if trueTy == falseTy here, it's verified by
// the AllTypesMatch trait already.
// We can go straight into getting the vector type.
auto condVecTy =
mlir::dyn_cast<cir::VectorType>(this->getCondition().getType());
auto trueVecTy =
mlir::dyn_cast<cir::VectorType>(this->getTrueValue().getType());
auto falseVecTy =
mlir::dyn_cast<cir::VectorType>(this->getFalseValue().getType());
if (condVecTy && (!trueVecTy || !falseVecTy)) {
// INFO: No need to check for size of vector here, it's verified by
// the AllTypesMatch trait already
return emitOpError()
<< "second and third operand must both be of the same "
"vector type when"
" the conditional operand is of vector boolean type";
}
return mlir::success();
}
}
LogicalResult cir::SelectOp::verify() {
// AllTypesMatch already guarantees trueVal and falseVal have matching types.
auto condTy = dyn_cast<cir::VectorType>(getCondition().getType());
// If condition is not a vector, no further checks are needed.
if (!condTy)
return success();
// When condition is a vector, both other operands must also be vectors.
if (!isa<cir::VectorType>(getTrueValue().getType()) ||
!isa<cir::VectorType>(getFalseValue().getType())) {
return emitOpError()
<< "expected both true and false operands to be vector types "
"when the condition is a vector boolean type";
}
return success();
}


//===----------------------------------------------------------------------===//
// ShiftOp
Expand Down
178 changes: 178 additions & 0 deletions clang/test/CIR/CodeGenBuiltins/X86/avx512f-builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,184 @@ void test_mm512_mask_i64scatter_epi32(void *__addr, __mmask8 __mask, __m512i __i
return _mm512_mask_i64scatter_epi32(__addr, __mask, __index, __v1, 2);
}

__m256d test_mm512_extractf64x4_pd(__m512d a)
{
// CIR-LABEL: test_mm512_extractf64x4_pd
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !cir.double>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !cir.double>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>

// LLVM-LABEL: test_mm512_extractf64x4_pd
// LLVM: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>

// OGCG-LABEL: test_mm512_extractf64x4_pd
// OGCG: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extractf64x4_pd(a, 1);
}

__m256d test_mm512_mask_extractf64x4_pd(__m256d __W,__mmask8 __U,__m512d __A){
// CIR-LABEL: test_mm512_mask_extractf64x4_pd
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !cir.double>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !cir.double>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
// CIR: cir.select if %{{.*}} then %{{.*}} else %{{.*}} : (!cir.vector<4 x !cir.bool>, !cir.vector<4 x !cir.double>, !cir.vector<4 x !cir.double>) -> !cir.vector<4 x !cir.double>

// LLVM-LABEL: test_mm512_mask_extractf64x4_pd
// LLVM: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}

// OGCG-LABEL: test_mm512_mask_extractf64x4_pd
// OGCG: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm512_mask_extractf64x4_pd( __W, __U, __A, 1);
}

__m256d test_mm512_maskz_extractf64x4_pd(__mmask8 __U,__m512d __A){
// CIR-LABEL: test_mm512_maskz_extractf64x4_pd
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !cir.double>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !cir.double>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.double>
// CIR: cir.select if %{{.*}} then %{{.*}} else %{{.*}} : (!cir.vector<4 x !cir.bool>, !cir.vector<4 x !cir.double>, !cir.vector<4 x !cir.double>) -> !cir.vector<4 x !cir.double>

// LLVM-LABEL: test_mm512_maskz_extractf64x4_pd
// LLVM: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}

// OGCG-LABEL: test_mm512_maskz_extractf64x4_pd
// OGCG: shufflevector <8 x double> %{{.*}}, <8 x double> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x double> %{{.*}}, <4 x double> %{{.*}}
return _mm512_maskz_extractf64x4_pd( __U, __A, 1);
}

__m128 test_mm512_extractf32x4_ps(__m512 a)
{
// CIR-LABEL: test_mm512_extractf32x4_ps
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !cir.float>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !cir.float>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.float>

// LLVM-LABEL: test_mm512_extractf32x4_ps
// LLVM: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>

// OGCG-LABEL: test_mm512_extractf32x4_ps
// OGCG: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extractf32x4_ps(a, 1);
}

__m128 test_mm512_mask_extractf32x4_ps(__m128 __W, __mmask8 __U,__m512 __A){
// CIR-LABEL: test_mm512_mask_extractf32x4_ps
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !cir.float>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !cir.float>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.float>

// LLVM-LABEL: test_mm512_mask_extractf32x4_ps
// LLVM: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}

// OGCG-LABEL: test_mm512_mask_extractf32x4_ps
// OGCG: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm512_mask_extractf32x4_ps( __W, __U, __A, 1);
}

__m128 test_mm512_maskz_extractf32x4_ps( __mmask8 __U,__m512 __A){
// CIR-LABEL: test_mm512_maskz_extractf32x4_ps
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !cir.float>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !cir.float>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !cir.float>

// LLVM-LABEL: test_mm512_maskz_extractf32x4_ps
// LLVM: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}

// OGCG-LABEL: test_mm512_maskz_extractf32x4_ps
// OGCG: shufflevector <16 x float> %{{.*}}, <16 x float> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x float> %{{.*}}, <4 x float> %{{.*}}
return _mm512_maskz_extractf32x4_ps(__U, __A, 1);
}

__m128i test_mm512_extracti32x4_epi32(__m512i __A) {
// CIR-LABEL: test_mm512_extracti32x4_epi32
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !s32i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !s32i>) [#cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<4 x !s32i>

// LLVM-LABEL: test_mm512_extracti32x4_epi32
// LLVM: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>

// OGCG-LABEL: test_mm512_extracti32x4_epi32
// OGCG: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
return _mm512_extracti32x4_epi32(__A, 3);
}

__m128i test_mm512_mask_extracti32x4_epi32(__m128i __W, __mmask8 __U, __m512i __A) {
// CIR-LABEL: test_mm512_mask_extracti32x4_epi32
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !s32i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !s32i>) [#cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<4 x !s32i>
// CIR: cir.select if %{{.*}} then %{{.*}} else %{{.*}} : (!cir.vector<4 x !cir.bool>, !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>

// LLVM-LABEL: test_mm512_mask_extracti32x4_epi32
// LLVM: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// LLVM: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}

// OGCG-LABEL: test_mm512_mask_extracti32x4_epi32
// OGCG: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// OGCG: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm512_mask_extracti32x4_epi32(__W, __U, __A, 3);
}

__m128i test_mm512_maskz_extracti32x4_epi32(__mmask8 __U, __m512i __A) {
// CIR-LABEL: test_mm512_maskz_extracti32x4_epi32
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<16 x !s32i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<16 x !s32i>) [#cir.int<12> : !s32i, #cir.int<13> : !s32i, #cir.int<14> : !s32i, #cir.int<15> : !s32i] : !cir.vector<4 x !s32i>
// CIR: cir.select if %{{.*}} then %{{.*}} else %{{.*}} : (!cir.vector<4 x !cir.bool>, !cir.vector<4 x !s32i>, !cir.vector<4 x !s32i>) -> !cir.vector<4 x !s32i>

// LLVM-LABEL: test_mm512_maskz_extracti32x4_epi32
// LLVM: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// LLVM: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}

// OGCG-LABEL: test_mm512_maskz_extracti32x4_epi32
// OGCG: shufflevector <16 x i32> %{{.*}}, <16 x i32> poison, <4 x i32> <i32 12, i32 13, i32 14, i32 15>
// OGCG: select <4 x i1> %{{.*}}, <4 x i32> %{{.*}}, <4 x i32> %{{.*}}
return _mm512_maskz_extracti32x4_epi32(__U, __A, 3);
}

__m256i test_mm512_extracti64x4_epi64(__m512i __A) {
// CIR-LABEL: test_mm512_extracti64x4_epi64
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !s64i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !s64i>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !s64i>

// LLVM-LABEL: test_mm512_extracti64x4_epi64
// LLVM: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>

// OGCG-LABEL: test_mm512_extracti64x4_epi64
// OGCG: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
return _mm512_extracti64x4_epi64(__A, 1);
}

__m256i test_mm512_mask_extracti64x4_epi64(__m256i __W, __mmask8 __U, __m512i __A) {
// CIR-LABEL: test_mm512_mask_extracti64x4_epi64
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !s64i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !s64i>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !s64i>

// LLVM-LABEL: test_mm512_mask_extracti64x4_epi64
// LLVM: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}

// OGCG-LABEL: test_mm512_mask_extracti64x4_epi64
// OGCG: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm512_mask_extracti64x4_epi64(__W, __U, __A, 1);
}

__m256i test_mm512_maskz_extracti64x4_epi64(__mmask8 __U, __m512i __A) {
// CIR-LABEL: test_mm512_maskz_extracti64x4_epi64
// CIR: [[POISON:%.*]] = cir.const #cir.poison : !cir.vector<8 x !s64i>
// CIR: cir.vec.shuffle(%{{.*}}, [[POISON]] : !cir.vector<8 x !s64i>) [#cir.int<4> : !s32i, #cir.int<5> : !s32i, #cir.int<6> : !s32i, #cir.int<7> : !s32i] : !cir.vector<4 x !s64i>

// LLVM-LABEL: test_mm512_maskz_extracti64x4_epi64
// LLVM: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// LLVM: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}

// OGCG-LABEL: test_mm512_maskz_extracti64x4_epi64
// OGCG: shufflevector <8 x i64> %{{.*}}, <8 x i64> poison, <4 x i32> <i32 4, i32 5, i32 6, i32 7>
// OGCG: select <4 x i1> %{{.*}}, <4 x i64> %{{.*}}, <4 x i64> %{{.*}}
return _mm512_maskz_extracti64x4_epi64(__U, __A, 1);
}

__m512i test_mm512_mul_epi32(__m512i __A, __m512i __B) {
// CIR-LABEL: _mm512_mul_epi32
// CIR: [[A64:%.*]] = cir.cast bitcast %{{.*}} : !cir.vector<16 x !s32i> -> !cir.vector<8 x !s64i>
Expand Down
Loading