Skip to content

Commit 22f550b

Browse files
authored
[CIR] ExtVectorElementExpr with result Vector type (#167925)
Upstream ExtVectorElementExpr with result Vector type
1 parent 30c8465 commit 22f550b

File tree

3 files changed

+80
-3
lines changed

3 files changed

+80
-3
lines changed

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,35 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
574574
info.isSigned, isLvalueVolatile,
575575
addr.getAlignment().getAsAlign().value());
576576
}
577+
578+
cir::VecShuffleOp
579+
createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2,
580+
llvm::ArrayRef<mlir::Attribute> maskAttrs) {
581+
auto vecType = mlir::cast<cir::VectorType>(vec1.getType());
582+
auto resultTy = cir::VectorType::get(getContext(), vecType.getElementType(),
583+
maskAttrs.size());
584+
return cir::VecShuffleOp::create(*this, loc, resultTy, vec1, vec2,
585+
getArrayAttr(maskAttrs));
586+
}
587+
588+
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1,
589+
mlir::Value vec2,
590+
llvm::ArrayRef<int64_t> mask) {
591+
auto maskAttrs = llvm::to_vector_of<mlir::Attribute>(
592+
llvm::map_range(mask, [&](int32_t idx) {
593+
return cir::IntAttr::get(getSInt32Ty(), idx);
594+
}));
595+
return createVecShuffle(loc, vec1, vec2, maskAttrs);
596+
}
597+
598+
cir::VecShuffleOp createVecShuffle(mlir::Location loc, mlir::Value vec1,
599+
llvm::ArrayRef<int64_t> mask) {
600+
/// Create a unary shuffle. The second vector operand of the IR instruction
601+
/// is poison.
602+
cir::ConstantOp poison =
603+
getConstant(loc, cir::PoisonAttr::get(vec1.getType()));
604+
return createVecShuffle(loc, vec1, poison, mask);
605+
}
577606
};
578607

579608
} // namespace clang::CIRGen

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -669,9 +669,18 @@ RValue CIRGenFunction::emitLoadOfExtVectorElementLValue(LValue lv) {
669669
return RValue::get(cir::VecExtractOp::create(builder, loc, vec, index));
670670
}
671671

672-
cgm.errorNYI(
673-
loc, "emitLoadOfExtVectorElementLValue: Result of expr is vector type");
674-
return {};
672+
// Always use shuffle vector to try to retain the original program structure
673+
SmallVector<int64_t> mask;
674+
for (auto i : llvm::seq<unsigned>(0, exprVecTy->getNumElements()))
675+
mask.push_back(getAccessedFieldNo(i, elts));
676+
677+
cir::VecShuffleOp resultVec = builder.createVecShuffle(loc, vec, mask);
678+
if (lv.getType()->isExtVectorBoolType()) {
679+
cgm.errorNYI(loc, "emitLoadOfExtVectorElementLValue: ExtVectorBoolType");
680+
return {};
681+
}
682+
683+
return RValue::get(resultVec);
675684
}
676685

677686
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {

clang/test/CIR/CodeGen/vector-ext-element.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
66
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
77

8+
typedef int vi2 __attribute__((ext_vector_type(2)));
89
typedef int vi4 __attribute__((ext_vector_type(4)));
910

1011
void element_expr_from_gl() {
@@ -44,3 +45,41 @@ void element_expr_from_gl() {
4445
// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
4546
// OGCG: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1
4647
// OGCG: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4
48+
49+
void element_expr_from_gl_with_vec_result() {
50+
vi4 a;
51+
vi2 b = a.xy;
52+
vi4 c = a.wzyx;
53+
}
54+
55+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
56+
// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, ["b", init]
57+
// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["c", init]
58+
// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
59+
// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
60+
// CIR: %[[B_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<0> : !s32i, #cir.int<1> : !s32i] : !cir.vector<2 x !s32i>
61+
// CIR: cir.store {{.*}} %[[B_VALUE]], %[[B_ADDR]] : !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>
62+
// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !s32i>>, !cir.vector<4 x !s32i>
63+
// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i>
64+
// CIR: %[[C_VALUE:.*]] = cir.vec.shuffle(%[[TMP_A]], %[[POISON]] : !cir.vector<4 x !s32i>) [#cir.int<3> : !s32i, #cir.int<2> : !s32i, #cir.int<1> : !s32i, #cir.int<0> : !s32i] : !cir.vector<4 x !s32i>
65+
// CIR: cir.store {{.*}} %[[C_VALUE]], %[[C_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>
66+
67+
// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
68+
// LLVM: %[[B_ADDR:.*]] = alloca <2 x i32>, i64 1, align 8
69+
// LLVM: %[[C_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
70+
// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
71+
// LLVM: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
72+
// LLVM: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
73+
// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
74+
// LLVM: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
75+
// LLVM: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16
76+
77+
// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
78+
// OGCG: %[[B_ADDR:.*]] = alloca <2 x i32>, align 8
79+
// OGCG: %[[C_ADDR:.*]] = alloca <4 x i32>, align 16
80+
// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
81+
// OGCG: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> <i32 0, i32 1>
82+
// OGCG: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8
83+
// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16
84+
// OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
85+
// OGCG: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16

0 commit comments

Comments
 (0)