Skip to content

Commit a8e0afe

Browse files
authored
[CIR] ArraySubscriptExpr on ExtVectorElementExpr (#169158)
Implement ArraySubscriptExpr support for ExtVectorElementExpr
1 parent dce95b2 commit a8e0afe

File tree

3 files changed

+69
-10
lines changed

3 files changed

+69
-10
lines changed

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,30 @@ RValue CIRGenFunction::emitLoadOfExtVectorElementLValue(LValue lv) {
683683
return RValue::get(resultVec);
684684
}
685685

686+
/// Generates lvalue for partial ext_vector access.
687+
Address CIRGenFunction::emitExtVectorElementLValue(LValue lv,
688+
mlir::Location loc) {
689+
Address vectorAddress = lv.getExtVectorAddress();
690+
QualType elementTy = lv.getType()->castAs<VectorType>()->getElementType();
691+
mlir::Type vectorElementTy = cgm.getTypes().convertType(elementTy);
692+
Address castToPointerElement =
693+
vectorAddress.withElementType(builder, vectorElementTy);
694+
695+
mlir::ArrayAttr extVecElts = lv.getExtVectorElts();
696+
unsigned idx = getAccessedFieldNo(0, extVecElts);
697+
mlir::Value idxValue =
698+
builder.getConstInt(loc, mlir::cast<cir::IntType>(ptrDiffTy), idx);
699+
700+
mlir::Value elementValue = builder.getArrayElement(
701+
loc, loc, castToPointerElement.getPointer(), vectorElementTy, idxValue,
702+
/*shouldDecay=*/false);
703+
704+
const CharUnits eltSize = getContext().getTypeSizeInChars(elementTy);
705+
const CharUnits alignment =
706+
castToPointerElement.getAlignment().alignmentAtOffset(idx * eltSize);
707+
return Address(elementValue, vectorElementTy, alignment);
708+
}
709+
686710
static cir::FuncOp emitFunctionDeclPointer(CIRGenModule &cgm, GlobalDecl gd) {
687711
assert(!cir::MissingFeatures::weakRefReference());
688712
return cgm.getAddrOfFunction(gd);
@@ -1081,12 +1105,6 @@ static Address emitArraySubscriptPtr(CIRGenFunction &cgf,
10811105

10821106
LValue
10831107
CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
1084-
if (isa<ExtVectorElementExpr>(e->getBase())) {
1085-
cgm.errorNYI(e->getSourceRange(),
1086-
"emitArraySubscriptExpr: ExtVectorElementExpr");
1087-
return LValue::makeAddr(Address::invalid(), e->getType(), LValueBaseInfo());
1088-
}
1089-
10901108
if (getContext().getAsVariableArrayType(e->getType())) {
10911109
cgm.errorNYI(e->getSourceRange(),
10921110
"emitArraySubscriptExpr: VariableArrayType");
@@ -1116,15 +1134,30 @@ CIRGenFunction::emitArraySubscriptExpr(const clang::ArraySubscriptExpr *e) {
11161134

11171135
// If the base is a vector type, then we are forming a vector element
11181136
// with this subscript.
1119-
if (e->getBase()->getType()->isVectorType() &&
1137+
if (e->getBase()->getType()->isSubscriptableVectorType() &&
11201138
!isa<ExtVectorElementExpr>(e->getBase())) {
11211139
const mlir::Value idx = emitIdxAfterBase(/*promote=*/false);
1122-
const LValue lhs = emitLValue(e->getBase());
1123-
return LValue::makeVectorElt(lhs.getAddress(), idx, e->getBase()->getType(),
1124-
lhs.getBaseInfo());
1140+
const LValue lv = emitLValue(e->getBase());
1141+
return LValue::makeVectorElt(lv.getAddress(), idx, e->getBase()->getType(),
1142+
lv.getBaseInfo());
11251143
}
11261144

11271145
const mlir::Value idx = emitIdxAfterBase(/*promote=*/true);
1146+
1147+
// Handle the extvector case we ignored above.
1148+
if (isa<ExtVectorElementExpr>(e->getBase())) {
1149+
const LValue lv = emitLValue(e->getBase());
1150+
Address addr = emitExtVectorElementLValue(lv, cgm.getLoc(e->getExprLoc()));
1151+
1152+
QualType elementType = lv.getType()->castAs<VectorType>()->getElementType();
1153+
addr = emitArraySubscriptPtr(*this, cgm.getLoc(e->getBeginLoc()),
1154+
cgm.getLoc(e->getEndLoc()), addr, e->getType(),
1155+
idx, cgm.getLoc(e->getExprLoc()),
1156+
/*shouldDecay=*/false);
1157+
1158+
return makeAddrLValue(addr, elementType, lv.getBaseInfo());
1159+
}
1160+
11281161
if (const Expr *array = getSimpleArrayDecayOperand(e->getBase())) {
11291162
LValue arrayLV;
11301163
if (const auto *ase = dyn_cast<ArraySubscriptExpr>(array))

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,8 @@ class CIRGenFunction : public CIRGenTypeCache {
531531
/// that we can just remove the code.
532532
bool containsLabel(const clang::Stmt *s, bool ignoreCaseStmts = false);
533533

534+
Address emitExtVectorElementLValue(LValue lv, mlir::Location loc);
535+
534536
class ConstantEmission {
535537
// Cannot use mlir::TypedAttr directly here because of bit availability.
536538
llvm::PointerIntPair<mlir::Attribute, 1, bool> valueAndIsReference;

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,3 +315,27 @@ void element_expr_from_rvalue_with_vec_result() {
315315
// OGCG: %[[TMP_2:.*]] = load <4 x i32>, ptr %[[TMP_2_ADDR]], align 16
316316
// OGCG: %[[D_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_2]], <4 x i32> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
317317
// OGCG: store <4 x i32> %[[D_VALUE]], ptr %[[D_ADDR]], align 16
318+
319+
void array_subscript_expr_with_element_expr_base() {
320+
vi4 a;
321+
a.xyz[1] = 2;
322+
}
323+
324+
// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
325+
// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
326+
// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i
327+
// CIR: %[[A_PTR:.*]] = cir.cast bitcast %0 : !cir.ptr<!cir.vector<4 x !s32i>> -> !cir.ptr<!s32i>
328+
// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i
329+
// CIR: %[[VEC_MEMBER_EXPR:.*]] = cir.ptr_stride %[[A_PTR]], %[[CONST_0]] : (!cir.ptr<!s32i>, !s64i) -> !cir.ptr<!s32i>
330+
// CIR: %[[VEC_ELEM_PTR:.*]] = cir.ptr_stride %[[VEC_MEMBER_EXPR]], %[[CONST_1]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
331+
// CIR: cir.store {{.*}} %[[CONST_2]], %[[VEC_ELEM_PTR]] : !s32i, !cir.ptr<!s32i>
332+
333+
// LLVM: %[[A_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16
334+
// LLVM: %[[VEC_MEMBER_EXPR:.*]] = getelementptr i32, ptr %[[A_ADDR]], i64 0
335+
// LLVM: %[[VEC_ELEM_PTR:.*]] = getelementptr i32, ptr %[[VEC_MEMBER_EXPR]], i64 1
336+
// LLVM: store i32 2, ptr %[[VEC_ELEM_PTR]], align 4
337+
338+
// OGCG: %[[A_ADDR:.*]] = alloca <4 x i32>, align 16
339+
// OGCG: %[[VEC_MEMBER_EXPR:.*]] = getelementptr inbounds i32, ptr %[[A_ADDR]], i64 0
340+
// OGCG: %[[VEC_ELEM_PTR:.*]] = getelementptr inbounds i32, ptr %[[VEC_MEMBER_EXPR]], i64 1
341+
// OGCG: store i32 2, ptr %[[VEC_ELEM_PTR]], align 4

0 commit comments

Comments
 (0)