diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index 91a59d60fcb3e..d35bb0af0de14 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1174,9 +1174,14 @@ LValue CIRGenFunction::emitExtVectorElementExpr(const ExtVectorElementExpr *e) { // ExtVectorElementExpr's base can either be a vector or pointer to vector. if (e->isArrow()) { - cgm.errorNYI(e->getSourceRange(), - "emitExtVectorElementExpr: pointer to vector"); - return {}; + // If it is a pointer to a vector, emit the address and form an lvalue with + // it. + LValueBaseInfo baseInfo; + Address ptr = emitPointerWithAlignment(e->getBase(), &baseInfo); + const auto *clangPtrTy = + e->getBase()->getType()->castAs(); + base = makeAddrLValue(ptr, clangPtrTy->getPointeeType(), baseInfo); + base.getQuals().removeObjCGCAttr(); } else if (e->getBase()->isGLValue()) { // Otherwise, if the base is an lvalue ( as in the case of foo.x.x), // emit the base as an lvalue. diff --git a/clang/test/CIR/CodeGen/vector-ext-element.cpp b/clang/test/CIR/CodeGen/vector-ext-element.cpp index e724eb58ff9aa..18542ee40b325 100644 --- a/clang/test/CIR/CodeGen/vector-ext-element.cpp +++ b/clang/test/CIR/CodeGen/vector-ext-element.cpp @@ -83,3 +83,91 @@ void element_expr_from_gl_with_vec_result() { // OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[A_ADDR]], align 16 // OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> // OGCG: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16 + +void element_expr_from_pointer() { + vi4 *a; + int X = a->x; + int Y = a->y; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["a"] +// CIR: %[[X_ADDR:.*]] = cir.alloca !s32i, !cir.ptr, ["X", init] +// CIR: %[[Y_ADDR:.*]] = cir.alloca !s32i, !cir.ptr, ["Y", init] +// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr>>, !cir.ptr> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr>, !cir.vector<4 x !s32i> +// CIR: %[[CONST_0:.*]] = cir.const #cir.int<0> : !s64i +// CIR: %[[ELEM_0:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_0]] : !s64i] : !cir.vector<4 x !s32i> +// CIR: cir.store {{.*}} %[[ELEM_0]], %[[X_ADDR]] : !s32i, !cir.ptr +// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr>>, !cir.ptr> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR:.*]] : !cir.ptr>, !cir.vector<4 x !s32i> +// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s64i +// CIR: %[[ELEM_1:.*]] = cir.vec.extract %[[TMP_A]][%[[CONST_1]] : !s64i] : !cir.vector<4 x !s32i> +// CIR: cir.store {{.*}} %[[ELEM_1]], %[[Y_ADDR]] : !s32i, !cir.ptr + +// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[X_ADDR:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[Y_ADDR:.*]] = alloca i32, i64 1, align 4 +// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// LLVM: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 0 +// LLVM: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4 +// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// LLVM: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1 +// LLVM: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4 + +// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[Y_ADDR:.*]] = alloca i32, align 4 +// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// OGCG: %[[ELEM_0:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 0 +// OGCG: store i32 %[[ELEM_0]], ptr %[[X_ADDR]], align 4 +// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// OGCG: %[[ELEM_1:.*]] = extractelement <4 x i32> %[[TMP_A]], i64 1 +// OGCG: store i32 %[[ELEM_1]], ptr %[[Y_ADDR]], align 4 + +void element_expr_from_pointer_with_vec_result() { + vi4 *a; + vi2 b = a->xy; + vi4 c = a->wzyx; +} + +// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.ptr>, !cir.ptr>>, ["a"] +// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr>, ["b", init] +// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr>, ["c", init] +// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr>>, !cir.ptr> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr>, !cir.vector<4 x !s32i> +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i> +// 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> +// CIR: cir.store {{.*}} %[[B_VALUE]], %[[B_ADDR]] : !cir.vector<2 x !s32i>, !cir.ptr> +// CIR: %[[TMP_A_PTR:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr>>, !cir.ptr> +// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[TMP_A_PTR]] : !cir.ptr>, !cir.vector<4 x !s32i> +// CIR: %[[POISON:.*]] = cir.const #cir.poison : !cir.vector<4 x !s32i> +// 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> +// CIR: cir.store {{.*}} %[[C_VALUE]], %[[C_ADDR]] : !cir.vector<4 x !s32i>, !cir.ptr> + +// LLVM: %[[A_ADDR:.*]] = alloca ptr, i64 1, align 8 +// LLVM: %[[B_ADDR:.*]] = alloca <2 x i32>, i64 1, align 8 +// LLVM: %[[C_ADDR:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// LLVM: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> +// LLVM: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8 +// LLVM: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// LLVM: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// LLVM: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> +// LLVM: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16 + +// OGCG: %[[A_ADDR:.*]] = alloca ptr, align 8 +// OGCG: %[[B_ADDR:.*]] = alloca <2 x i32>, align 8 +// OGCG: %[[C_ADDR:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// OGCG: %[[B_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <2 x i32> +// OGCG: store <2 x i32> %[[B_VALUE]], ptr %[[B_ADDR]], align 8 +// OGCG: %[[TMP_A_PTR:.*]] = load ptr, ptr %[[A_ADDR]], align 8 +// OGCG: %[[TMP_A:.*]] = load <4 x i32>, ptr %[[TMP_A_PTR]], align 16 +// OGCG: %[[C_VALUE:.*]] = shufflevector <4 x i32> %[[TMP_A]], <4 x i32> poison, <4 x i32> +// OGCG: store <4 x i32> %[[C_VALUE]], ptr %[[C_ADDR]], align 16