-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[CIR] Upstream local initialization for VectorType #138107
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -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); | ||||||||||||||
|
||||||||||||||
| mlir::TypedAttr zeroInitAttr = | |
| cgf.getBuilder().getZeroInitAttr(vectorType.getElementType()); | |
| cir::ConstantOp zeroValue = cgf.getBuilder().getConstant( | |
| cgf.getLoc(e->getSourceRange()), zeroInitAttr); | |
| cir::ConstantOp zeroValue = cgf.getBuilder().getNullValue( | |
| vectorType.getElementType(), cgf.getLoc(e->getSourceRange())); |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| for (uint64_t i = numInitElements; i < vectorType.getSize(); ++i) { | |
| elements.assign(vectorType.getSize(), zeroValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As far as I understood, elements.assign will assign zeroValue to all elements, not just the remaining uninit ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. I had forgotten this vector already had entries from above. What about this?
std::fill_n(std::back_inserter(elements), vectorType.getSize(), zeroValue);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be like this
std::fill_n(std::back_inserter(elements), vectorType.getSize() - numInitElements, zeroValue);
To fill in the remaining size not init + full size
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that looks right.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we not do this with an
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will try to see if i can pass the values to StoreOp and use it
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I addressed all comments except this one :D, To use
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK. We can possibly revisit this later. For constant values, it looks like it ends up as a single store in LLVM IR anyway. |
||
| 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>(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 }; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a test case where the initializer list doesn't fill the entire vector? |
||
| } | ||
|
|
||
| // 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) {} | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.