llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Amr Hesham (AmrDeveloper) <details> <summary>Changes</summary> This change adds local initialization for VectorType Issue https://github.com/llvm/llvm-project/issues/136487 --- Full diff: https://github.com/llvm/llvm-project/pull/138107.diff 11 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+24) - (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+14-3) - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+43) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+27) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp (+25-1) - (modified) clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h (+10) - (modified) clang/test/CIR/CodeGen/vector-ext.cpp (+20) - (modified) clang/test/CIR/CodeGen/vector.cpp (+21-1) - (added) clang/test/CIR/IR/invalid-vector-create-wrong-size.cir (+16) - (added) clang/test/CIR/IR/invalid-vector-create-wrong-type.cir (+17) - (modified) clang/test/CIR/IR/vector.cir (+22) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 8319364b9e5e3..39417b340b29d 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1903,4 +1903,28 @@ def TrapOp : CIR_Op<"trap", [Terminator]> { let assemblyFormat = "attr-dict"; } +//===----------------------------------------------------------------------===// +// VecCreate +//===----------------------------------------------------------------------===// + +def VecCreateOp : CIR_Op<"vec.create", [Pure]> { + + let summary = "Create a vector value"; + let description = [{ + The `cir.vec.create` operation creates a vector value with the given element + values. The number of element arguments must match the number of elements + in the vector type. + }]; + + let arguments = (ins Variadic<CIR_AnyType>:$elements); + let results = (outs CIR_VectorType:$result); + + let assemblyFormat = [{ + `(` ($elements^ `:` type($elements))? `)` `:` qualified(type($result)) + attr-dict + }]; + + let hasVerifier = 1; +} + #endif // CLANG_CIR_DIALECT_IR_CIROPS_TD diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index da5a0b97a395e..a134b066b0ab0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -258,9 +258,20 @@ void CIRGenFunction::emitStoreOfScalar(mlir::Value value, Address addr, bool isInit, bool isNontemporal) { assert(!cir::MissingFeatures::opLoadStoreThreadLocal()); - if (ty->getAs<clang::VectorType>()) { - cgm.errorNYI(addr.getPointer().getLoc(), "emitStoreOfScalar vector type"); - return; + if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) { + // Boolean vectors use `iN` as storage type. + if (clangVecTy->isExtVectorBoolType()) + cgm.errorNYI(addr.getPointer().getLoc(), + "emitStoreOfScalar ExtVectorBoolType"); + + // Handle vectors of size 3 like size 4 for better performance. + const mlir::Type elementType = addr.getElementType(); + const auto vecTy = cast<cir::VectorType>(elementType); + + // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it upstreamed + if (vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type) + cgm.errorNYI(addr.getPointer().getLoc(), + "emitStoreOfScalar Vec3 & PreserveVec3Type disabled"); } value = emitToMemory(value, ty); diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index aef5b125a2877..53fa81e73d496 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -170,6 +170,8 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { mlir::Value VisitMemberExpr(MemberExpr *e); + mlir::Value VisitInitListExpr(InitListExpr *e); + mlir::Value VisitExplicitCastExpr(ExplicitCastExpr *e) { return VisitCastExpr(e); } @@ -1584,6 +1586,47 @@ mlir::Value ScalarExprEmitter::VisitMemberExpr(MemberExpr *e) { return emitLoadOfLValue(e); } +mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) { + const unsigned numInitElements = e->getNumInits(); + + if (e->hadArrayRangeDesignator()) { + cgf.cgm.errorNYI(e->getSourceRange(), "ArrayRangeDesignator"); + return {}; + } + + if (numInitElements == 0) { + cgf.cgm.errorNYI(e->getSourceRange(), "InitListExpr with 0 init elements"); + return {}; + } + + if (e->getType()->isVectorType()) { + const auto vectorType = + mlir::cast<cir::VectorType>(cgf.convertType(e->getType())); + + SmallVector<mlir::Value, 16> elements; + for (Expr *init : e->inits()) { + elements.push_back(Visit(init)); + } + + // Zero-initialize any remaining values. + if (numInitElements < vectorType.getSize()) { + mlir::TypedAttr zeroInitAttr = + cgf.getBuilder().getZeroInitAttr(vectorType.getElementType()); + cir::ConstantOp zeroValue = + cgf.getBuilder().getConstant(cgf.getLoc(e->getSourceRange()), zeroInitAttr); + + for (uint64_t i = numInitElements; i < vectorType.getSize(); ++i) { + elements.push_back(zeroValue); + } + } + + return cgf.getBuilder().create<cir::VecCreateOp>( + cgf.getLoc(e->getSourceRange()), vectorType, elements); + } + + return Visit(e->getInit(0)); +} + mlir::Value CIRGenFunction::emitScalarConversion(mlir::Value src, QualType srcTy, QualType dstTy, SourceLocation loc) { diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 7ca012fbd73c6..58c79edc76a96 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1307,6 +1307,33 @@ LogicalResult cir::GetMemberOp::verify() { return mlir::success(); } +//===----------------------------------------------------------------------===// +// VecCreateOp +//===----------------------------------------------------------------------===// + +LogicalResult cir::VecCreateOp::verify() { + // Verify that the number of arguments matches the number of elements in the + // vector, and that the type of all the arguments matches the type of the + // elements in the vector. + const VectorType vecTy = getResult().getType(); + if (getElements().size() != vecTy.getSize()) { + return emitOpError() << "operand count of " << getElements().size() + << " doesn't match vector type " << vecTy + << " element count of " << vecTy.getSize(); + } + + const mlir::Type elementType = vecTy.getElementType(); + for (const mlir::Value element : getElements()) { + if (element.getType() != elementType) { + return emitOpError() << "operand type " << element.getType() + << " doesn't match vector element type " + << elementType; + } + } + + return success(); +} + //===----------------------------------------------------------------------===// // TableGen'd op method definitions //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index ea8125026a8c6..6137adb1e9936 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1599,7 +1599,8 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMStackSaveOpLowering, CIRToLLVMStackRestoreOpLowering, CIRToLLVMTrapOpLowering, - CIRToLLVMUnaryOpLowering + CIRToLLVMUnaryOpLowering, + CIRToLLVMVecCreateOpLowering // clang-format on >(converter, patterns.getContext()); @@ -1685,6 +1686,29 @@ mlir::LogicalResult CIRToLLVMStackRestoreOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMVecCreateOpLowering::matchAndRewrite( + cir::VecCreateOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + // Start with an 'undef' value for the vector. Then 'insertelement' for + // each of the vector elements. + const auto vecTy = mlir::cast<cir::VectorType>(op.getType()); + const mlir::Type llvmTy = typeConverter->convertType(vecTy); + const mlir::Location loc = op.getLoc(); + mlir::Value result = rewriter.create<mlir::LLVM::PoisonOp>(loc, llvmTy); + assert(vecTy.getSize() == op.getElements().size() && + "cir.vec.create op count doesn't match vector type elements count"); + + for (uint64_t i = 0; i < vecTy.getSize(); ++i) { + const mlir::Value indexValue = + rewriter.create<mlir::LLVM::ConstantOp>(loc, rewriter.getI64Type(), i); + result = rewriter.create<mlir::LLVM::InsertElementOp>( + loc, result, adaptor.getElements()[i], indexValue); + } + + rewriter.replaceOp(op, result); + return mlir::success(); +} + std::unique_ptr<mlir::Pass> createConvertCIRToLLVMPass() { return std::make_unique<ConvertCIRToLLVMPass>(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index f32e3a381c6f0..f248ea31e7844 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -293,6 +293,16 @@ class CIRToLLVMStackRestoreOpLowering mlir::ConversionPatternRewriter &rewriter) const override; }; +class CIRToLLVMVecCreateOpLowering + : public mlir::OpConversionPattern<cir::VecCreateOp> { +public: + using mlir::OpConversionPattern<cir::VecCreateOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::VecCreateOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + } // namespace direct } // namespace cir diff --git a/clang/test/CIR/CodeGen/vector-ext.cpp b/clang/test/CIR/CodeGen/vector-ext.cpp index 7759a32fc1378..ff21881452c9f 100644 --- a/clang/test/CIR/CodeGen/vector-ext.cpp +++ b/clang/test/CIR/CodeGen/vector-ext.cpp @@ -48,27 +48,47 @@ vi4 vec_e = { 1, 2, 3, 4 }; // OGCG: @[[VEC_E:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4> +int x = 5; + void foo() { vi4 a; vi3 b; vi2 c; vd2 d; + + vi4 e = { 1, 2, 3, 4 }; + + vi4 f = { x, 5, 6, x + 1 }; } // CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"] // CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<3 x !s32i>, !cir.ptr<!cir.vector<3 x !s32i>>, ["b"] // CIR: %[[VEC_C:.*]] = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, ["c"] // CIR: %[[VEC_D:.*]] = cir.alloca !cir.vector<2 x !cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>>, ["d"] +// CIR: %[[VEC_E:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["e", init] +// CIR: %[[VEC_F:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["f", init] +// CIR: %[[VEC_E_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_E_VAL]], %[[VEC_E]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[VEC_F_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_F_VAL]], %[[VEC_F]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> // LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16 // LLVM: %[[VEC_B:.*]] = alloca <3 x i32>, i64 1, align 16 // LLVM: %[[VEC_C:.*]] = alloca <2 x i32>, i64 1, align 8 // LLVM: %[[VEC_D:.*]] = alloca <2 x double>, i64 1, align 16 +// LLVM: %[[VEC_E:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[VEC_F:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_E]], align 16 +// LLVM: store <4 x i32> {{.*}}, ptr %[[VEC_F:.*]], align 16 // OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16 // OGCG: %[[VEC_B:.*]] = alloca <3 x i32>, align 16 // OGCG: %[[VEC_C:.*]] = alloca <2 x i32>, align 8 // OGCG: %[[VEC_D:.*]] = alloca <2 x double>, align 16 +// OGCG: %[[VEC_E:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[VEC_F:.*]] = alloca <4 x i32>, align 16 +// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_E]], align 16 +// OGCG: store <4 x i32> {{.*}}, ptr %[[VEC_F:.*]], align 16 void foo2(vi4 p) {} diff --git a/clang/test/CIR/CodeGen/vector.cpp b/clang/test/CIR/CodeGen/vector.cpp index 4c1850141a21c..840c30095ab83 100644 --- a/clang/test/CIR/CodeGen/vector.cpp +++ b/clang/test/CIR/CodeGen/vector.cpp @@ -39,23 +39,43 @@ vi4 d = { 1, 2, 3, 4 }; // OGCG: @[[VEC_D:.*]] = global <4 x i32> <i32 1, i32 2, i32 3, i32 4> -void vec_int_test() { +int x = 5; + +void foo() { vi4 a; vd2 b; vll2 c; + + vi4 d = { 1, 2, 3, 4 }; + + vi4 e = { x, 5, 6, x + 1 }; } // CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a"] // CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<2 x !cir.double>, !cir.ptr<!cir.vector<2 x !cir.double>>, ["b"] // CIR: %[[VEC_C:.*]] = cir.alloca !cir.vector<2 x !s64i>, !cir.ptr<!cir.vector<2 x !s64i>>, ["c"] +// CIR: %[[VEC_D:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["d", init] +// CIR: %[[VEC_E:.*]] = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["e", init] +// CIR: %[[VEC_D_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_D_VAL]], %[[VEC_D]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CIR: %[[VEC_E_VAL:.*]] = cir.vec.create({{.*}}, {{.*}}, {{.*}}, {{.*}} : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CIR: cir.store %[[VEC_E_VAL]], %[[VEC_E]] : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> // LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16 // LLVM: %[[VEC_B:.*]] = alloca <2 x double>, i64 1, align 16 // LLVM: %[[VEC_C:.*]] = alloca <2 x i64>, i64 1, align 16 +// LLVM: %[[VEC_D:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: %[[VEC_E:.*]] = alloca <4 x i32>, i64 1, align 16 +// LLVM: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_D]], align 16 +// LLVM: store <4 x i32> {{.*}}, ptr %[[VEC_E:.*]], align 16 // OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16 // OGCG: %[[VEC_B:.*]] = alloca <2 x double>, align 16 // OGCG: %[[VEC_C:.*]] = alloca <2 x i64>, align 16 +// OGCG: %[[VEC_D:.*]] = alloca <4 x i32>, align 16 +// OGCG: %[[VEC_E:.*]] = alloca <4 x i32>, align 16 +// OGCG: store <4 x i32> <i32 1, i32 2, i32 3, i32 4>, ptr %[[VEC_D]], align 16 +// OGCG: store <4 x i32> {{.*}}, ptr %[[VEC_E:.*]], align 16 void foo2(vi4 p) {} diff --git a/clang/test/CIR/IR/invalid-vector-create-wrong-size.cir b/clang/test/CIR/IR/invalid-vector-create-wrong-size.cir new file mode 100644 index 0000000000000..38ae74e83fb9e --- /dev/null +++ b/clang/test/CIR/IR/invalid-vector-create-wrong-size.cir @@ -0,0 +1,16 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s32i = !cir.int<s, 32> + +module { + cir.func @foo() { + %1 = cir.const #cir.int<1> : !s32i + %2 = cir.const #cir.int<2> : !s32i + %3 = cir.const #cir.int<3> : !s32i + %4 = cir.const #cir.int<4> : !s32i + + // expected-error @below {{operand count of 4 doesn't match vector type '!cir.vector<8 x !cir.int<s, 32>>' element count of 8}} + %5 = cir.vec.create(%1, %2, %3, %4 : !s32i, !s32i, !s32i, !s32i) : !cir.vector<8 x !s32i> + cir.return + } +} diff --git a/clang/test/CIR/IR/invalid-vector-create-wrong-type.cir b/clang/test/CIR/IR/invalid-vector-create-wrong-type.cir new file mode 100644 index 0000000000000..ded0e6072b536 --- /dev/null +++ b/clang/test/CIR/IR/invalid-vector-create-wrong-type.cir @@ -0,0 +1,17 @@ +// RUN: cir-opt %s -verify-diagnostics -split-input-file + +!s32i = !cir.int<s, 32> +!s64i = !cir.int<s, 64> + +module { + cir.func @foo() { + %1 = cir.const #cir.int<1> : !s32i + %2 = cir.const #cir.int<2> : !s32i + %3 = cir.const #cir.int<3> : !s32i + %4 = cir.const #cir.int<4> : !s64i + + // expected-error @below {{operand type '!cir.int<s, 64>' doesn't match vector element type '!cir.int<s, 32>'}} + %5 = cir.vec.create(%1, %2, %3, %4 : !s32i, !s32i, !s32i, !s64i) : !cir.vector<4 x !s32i> + cir.return + } +} diff --git a/clang/test/CIR/IR/vector.cir b/clang/test/CIR/IR/vector.cir index bc70a8b55fa5c..d2612a7310ad0 100644 --- a/clang/test/CIR/IR/vector.cir +++ b/clang/test/CIR/IR/vector.cir @@ -43,4 +43,26 @@ cir.func @vec_double_test() { // CHECK: cir.return // CHECK: } +cir.func @local_vector_create_test() { + %0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init] + %1 = cir.const #cir.int<1> : !s32i + %2 = cir.const #cir.int<2> : !s32i + %3 = cir.const #cir.int<3> : !s32i + %4 = cir.const #cir.int<4> : !s32i + %5 = cir.vec.create(%1, %2, %3, %4 : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> + cir.store %5, %0 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> + cir.return +} + +// CHECK: cir.func @local_vector_create_test() { +// CHECK: %0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, ["a", init] +// CHECK: %1 = cir.const #cir.int<1> : !s32i +// CHECK: %2 = cir.const #cir.int<2> : !s32i +// CHECK: %3 = cir.const #cir.int<3> : !s32i +// CHECK: %4 = cir.const #cir.int<4> : !s32i +// CHECK: %5 = cir.vec.create(%1, %2, %3, %4 : !s32i, !s32i, !s32i, !s32i) : !cir.vector<4 x !s32i> +// CHECK: cir.store %5, %0 : !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>> +// CHECK: cir.return +// CHECK: } + } `````````` </details> https://github.com/llvm/llvm-project/pull/138107 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits