Skip to content

[CIR] Upstream converting vector types #142012

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 30, 2025
Merged
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
15 changes: 14 additions & 1 deletion clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
@@ -185,6 +185,14 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
return {};
}

mlir::Value VisitConvertVectorExpr(ConvertVectorExpr *e) {
// __builtin_convertvector is an element-wise cast, and is implemented as a
// regular cast. The back end handles casts of vectors correctly.
return emitScalarConversion(Visit(e->getSrcExpr()),
e->getSrcExpr()->getType(), e->getType(),
e->getSourceRange().getBegin());
}

mlir::Value VisitMemberExpr(MemberExpr *e);

mlir::Value VisitInitListExpr(InitListExpr *e);
@@ -277,7 +285,12 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
"Obsolete code. Don't use mlir::IntegerType with CIR.");

mlir::Type fullDstTy = dstTy;
assert(!cir::MissingFeatures::vectorType());
if (mlir::isa<cir::VectorType>(srcTy) &&
mlir::isa<cir::VectorType>(dstTy)) {
// Use the element types of the vectors to figure out the CastKind.
srcTy = mlir::dyn_cast<cir::VectorType>(srcTy).getElementType();
dstTy = mlir::dyn_cast<cir::VectorType>(dstTy).getElementType();
}

std::optional<cir::CastKind> castKind;

12 changes: 10 additions & 2 deletions clang/lib/CIR/Dialect/IR/CIRDialect.cpp
Original file line number Diff line number Diff line change
@@ -286,8 +286,16 @@ LogicalResult cir::ContinueOp::verify() {
//===----------------------------------------------------------------------===//

LogicalResult cir::CastOp::verify() {
const mlir::Type resType = getResult().getType();
const mlir::Type srcType = getSrc().getType();
mlir::Type resType = getResult().getType();
mlir::Type srcType = getSrc().getType();

if (mlir::isa<cir::VectorType>(srcType) &&
mlir::isa<cir::VectorType>(resType)) {
// Use the element type of the vector to verify the cast kind. (Except for
// bitcast, see below.)
srcType = mlir::dyn_cast<cir::VectorType>(srcType).getElementType();
resType = mlir::dyn_cast<cir::VectorType>(resType).getElementType();
}

switch (getKind()) {
case cir::CastKind::int_to_bool: {
18 changes: 18 additions & 0 deletions clang/test/CIR/CodeGen/vector-ext.cpp
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG

typedef unsigned short vus2 __attribute__((ext_vector_type(2)));
typedef int vi4 __attribute__((ext_vector_type(4)));
typedef int vi6 __attribute__((ext_vector_type(6)));
typedef unsigned int uvi4 __attribute__((ext_vector_type(4)));
@@ -1073,3 +1074,20 @@ void foo16() {
// OGCG: %[[SHUF_IDX_3:.*]] = extractelement <6 x i32> %[[MASK]], i64 3
// OGCG: %[[SHUF_ELE_3:.*]] = extractelement <6 x i32> %[[TMP_A]], i32 %[[SHUF_IDX_3]]
// OGCG: %[[SHUF_INS_3:.*]] = insertelement <6 x i32> %[[SHUF_INS_2]], i32 %[[SHUF_ELE_3]], i64 3

void foo17() {
vd2 a;
vus2 W = __builtin_convertvector(a, vus2);
}

// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<2 x !cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>>, ["a"]
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double>
// CIR: %[[RES:.*]] = cir.cast(float_to_int, %[[TMP]] : !cir.vector<2 x !cir.double>), !cir.vector<2 x !u16i>

// LLVM: %[[VEC_A:.*]] = alloca <2 x double>, i64 1, align 16
// LLVM: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
// LLVM: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>

// OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16
// OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>
18 changes: 18 additions & 0 deletions clang/test/CIR/CodeGen/vector.cpp
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG

typedef unsigned short vus2 __attribute__((vector_size(4)));
typedef int vi4 __attribute__((vector_size(16)));
typedef int vi6 __attribute__((vector_size(24)));
typedef unsigned int uvi4 __attribute__((vector_size(16)));
@@ -1052,3 +1053,20 @@ void foo16() {
// OGCG: %[[SHUF_IDX_3:.*]] = extractelement <6 x i32> %[[MASK]], i64 3
// OGCG: %[[SHUF_ELE_3:.*]] = extractelement <6 x i32> %[[TMP_A]], i32 %[[SHUF_IDX_3]]
// OGCG: %[[SHUF_INS_3:.*]] = insertelement <6 x i32> %[[SHUF_INS_2]], i32 %[[SHUF_ELE_3]], i64 3

void foo17() {
vd2 a;
vus2 W = __builtin_convertvector(a, vus2);
}

// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<2 x !cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>>, ["a"]
// CIR: %[[TMP:.*]] = cir.load{{.*}} %[[VEC_A]] : !cir.ptr<!cir.vector<2 x !cir.double>>, !cir.vector<2 x !cir.double>
// CIR: %[[RES:.*]] = cir.cast(float_to_int, %[[TMP]] : !cir.vector<2 x !cir.double>), !cir.vector<2 x !u16i>

// LLVM: %[[VEC_A:.*]] = alloca <2 x double>, i64 1, align 16
// LLVM: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
// LLVM: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>

// OGCG: %[[VEC_A:.*]] = alloca <2 x double>, align 16
// OGCG: %[[TMP:.*]] = load <2 x double>, ptr %[[VEC_A]], align 16
// OGCG: %[[RES:.*]]= fptoui <2 x double> %[[TMP]] to <2 x i16>