diff --git a/include/polygeist/PolygeistOps.td b/include/polygeist/PolygeistOps.td index e70ee60b36cb..6f1cf0be8f29 100644 --- a/include/polygeist/PolygeistOps.td +++ b/include/polygeist/PolygeistOps.td @@ -96,4 +96,12 @@ def TypeSizeOp : Polygeist_Op<"typeSize", [NoSideEffect]> { let hasFolder = 1; let hasCanonicalizer = 1; } + +def TypeAlignOp : Polygeist_Op<"typeAlign", [NoSideEffect]> { + let summary = "Get alignment of type"; + let arguments = (ins TypeAttr : $source); + let results = (outs AnyType : $result); + let hasFolder = 1; + let hasCanonicalizer = 1; +} #endif // POLYGEIST_OPS diff --git a/lib/polygeist/Ops.cpp b/lib/polygeist/Ops.cpp index 9853cede9779..774b2d584ca9 100644 --- a/lib/polygeist/Ops.cpp +++ b/lib/polygeist/Ops.cpp @@ -1521,3 +1521,33 @@ void TypeSizeOp::getCanonicalizationPatterns(RewritePatternSet &results, MLIRContext *context) { results.insert(context); } + +OpFoldResult TypeAlignOp::fold(ArrayRef operands) { + Type T = sourceAttr().getValue(); + if (T.isa() || LLVM::isCompatibleType(T)) { + DataLayout DLI(((Operation *)*this)->getParentOfType()); + return IntegerAttr::get(getResult().getType(), + APInt(64, DLI.getTypeABIAlignment(T))); + } + return nullptr; +} +struct TypeAlignCanonicalize : public OpRewritePattern { + using OpRewritePattern::OpRewritePattern; + + LogicalResult matchAndRewrite(TypeAlignOp op, + PatternRewriter &rewriter) const override { + Type T = op.sourceAttr().getValue(); + if (T.isa() || LLVM::isCompatibleType(T)) { + DataLayout DLI(op->getParentOfType()); + rewriter.replaceOpWithNewOp( + op, DLI.getTypeABIAlignment(T)); + return success(); + } + return failure(); + } +}; + +void TypeAlignOp::getCanonicalizationPatterns(RewritePatternSet &results, + MLIRContext *context) { + results.insert(context); +} diff --git a/lib/polygeist/Passes/ConvertPolygeistToLLVM.cpp b/lib/polygeist/Passes/ConvertPolygeistToLLVM.cpp index 468824f9b231..ceef2c249efe 100644 --- a/lib/polygeist/Passes/ConvertPolygeistToLLVM.cpp +++ b/lib/polygeist/Passes/ConvertPolygeistToLLVM.cpp @@ -214,10 +214,41 @@ struct TypeSizeOpLowering : public ConvertOpToLLVMPattern { } }; +struct TypeAlignOpLowering : public ConvertOpToLLVMPattern { + using ConvertOpToLLVMPattern::ConvertOpToLLVMPattern; + + LogicalResult + matchAndRewrite(TypeAlignOp op, OpAdaptor transformed, + ConversionPatternRewriter &rewriter) const override { + + Type NT = op.sourceAttr().getValue(); + if (auto T = getTypeConverter()->convertType(NT)) { + NT = T; + } + assert(NT); + + auto type = getTypeConverter()->convertType(op.getType()); + + if (NT.isa() || LLVM::isCompatibleType(NT)) { + DataLayout DLI(op->getParentOfType()); + rewriter.replaceOpWithNewOp( + op, type, rewriter.getIntegerAttr(type, DLI.getTypeABIAlignment(NT))); + return success(); + } + + if (NT != op.sourceAttr().getValue() || type != op.getType()) { + rewriter.replaceOpWithNewOp(op, type, NT); + return success(); + } + return failure(); + } +}; + void populatePolygeistToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns) { // clang-format off patterns.add(converter); + patterns.add(converter); patterns.add(converter); patterns.add(converter); patterns.add(converter); diff --git a/tools/mlir-clang/Lib/clang-mlir.cc b/tools/mlir-clang/Lib/clang-mlir.cc index 84b3dd6637d8..916077f00dbb 100644 --- a/tools/mlir-clang/Lib/clang-mlir.cc +++ b/tools/mlir-clang/Lib/clang-mlir.cc @@ -2059,6 +2059,12 @@ MLIRScanner::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Uop) { return ValueCategory(builder.create(loc, retTy, value), /*isReference*/ false); } + case UETT_AlignOf: { + auto value = getTypeAlign(Uop->getTypeOfArgument()); + auto retTy = getMLIRType(Uop->getType()).cast(); + return ValueCategory(builder.create(loc, retTy, value), + /*isReference*/ false); + } default: Uop->dump(); assert(0 && "unhandled VisitUnaryExprOrTypeTraitExpr"); @@ -4868,6 +4874,17 @@ mlir::Value MLIRScanner::getTypeSize(clang::QualType t) { mlir::TypeAttr::get(innerTy)); // DLI.getTypeSize(innerTy); } +mlir::Value MLIRScanner::getTypeAlign(clang::QualType t) { + // llvm::Type *T = Glob.CGM.getTypes().ConvertType(t); + // return (Glob.llvmMod.getDataLayout().getTypeSizeInBits(T) + 7) / 8; + bool isArray = false; + auto innerTy = Glob.getMLIRType(t, &isArray); + assert(!isArray); + return builder.create( + loc, builder.getIndexType(), + mlir::TypeAttr::get(innerTy)); // DLI.getTypeSize(innerTy); +} + #include "clang/Frontend/TextDiagnosticBuffer.h" static DenseIntElementsAttr diff --git a/tools/mlir-clang/Lib/clang-mlir.h b/tools/mlir-clang/Lib/clang-mlir.h index 38826893c2b9..0178b92cf64c 100644 --- a/tools/mlir-clang/Lib/clang-mlir.h +++ b/tools/mlir-clang/Lib/clang-mlir.h @@ -171,6 +171,7 @@ class MLIRScanner : public StmtVisitor { mlir::Type getMLIRType(clang::QualType t); mlir::Value getTypeSize(clang::QualType t); + mlir::Value getTypeAlign(clang::QualType t); mlir::Value createAllocOp(mlir::Type t, VarDecl *name, uint64_t memspace, bool isArray, bool LLVMABI); diff --git a/tools/mlir-clang/Test/Verification/alignof.cpp b/tools/mlir-clang/Test/Verification/alignof.cpp new file mode 100644 index 000000000000..6c5cbdcfce92 --- /dev/null +++ b/tools/mlir-clang/Test/Verification/alignof.cpp @@ -0,0 +1,27 @@ +// RUN: mlir-clang -std=c++11 %s --function=* -S | FileCheck %s + +struct Meta { + float* f; + char x; +}; + +unsigned create() { + return alignof(struct Meta); +} + +unsigned create2() { + return alignof(char); +} + +// CHECK: func @_Z6createv() -> i32 attributes {llvm.linkage = #llvm.linkage} { +// CHECK-NEXT: %0 = "polygeist.typeAlign"() {source = !llvm.struct<(memref, i8)>} : () -> index +// CHECK-NEXT: %1 = arith.index_cast %0 : index to i64 +// CHECK-NEXT: %2 = arith.trunci %1 : i64 to i32 +// CHECK-NEXT: return %2 : i32 +// CHECK-NEXT: } + +// CHECK: func @_Z7create2v() -> i32 attributes {llvm.linkage = #llvm.linkage} { +// CHECK-NEXT: %c1_i32 = arith.constant 1 : i32 +// CHECK-NEXT: return %c1_i32 : i32 +// CHECK-NEXT: } +