Skip to content
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

[LDE: Project] 'Codegen-only compilation pipeline for LA operations' #935

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
6 changes: 3 additions & 3 deletions containers/entrypoint-interactive.sh
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these changes.

Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

USER=ubuntu
/usr/sbin/sshd -f /etc/ssh/sshd_config
/usr/sbin/groupadd -g "$GID" dockerusers
/usr/sbin/useradd -c 'Docker Container User' -u $UID -g "$GID" -G sudo -m -s /bin/bash -d /home/"$USER" "$USER"
# /usr/sbin/groupadd -g "$GID" dockerusers
# /usr/sbin/useradd -c 'Docker Container User' -u $UID -g "$GID" -G sudo -m -s /bin/bash -d /home/"$USER" "$USER"
printf "${USER} ALL=(ALL:ALL) NOPASSWD:ALL" | sudo EDITOR="tee -a" visudo #>> /dev/null
mkdir -p /home/"$USER"/.ssh
chmod 700 /home/"$USER"/.ssh
Expand Down
1 change: 1 addition & 0 deletions containers/run-docker-example.sh
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these changes.

Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ fi
$USE_SUDO docker run $DEBUG_FLAGS $DEVICE_FLAGS -it --rm --hostname daphne-container -w $DAPHNE_ROOT_CONTAINER \
-v "$DAPHNE_ROOT:$DAPHNE_ROOT_CONTAINER" -e GID=$GID -e TERM=screen-256color -e PATH -e LD_LIBRARY_PATH \
-e USER=$USERNAME -e UID=$UID \
--entrypoint /daphne/containers/entrypoint-interactive.sh \
"$DOCKER_IMAGE:$DOCKER_TAG" $command

# move this up to above the DOCKER_IMAGE line to override the entrypoint:
Expand Down
17 changes: 17 additions & 0 deletions scripts/examples/slice.daph
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this file and add proper testcases. Look at the testcases in test/codegen/ and test/api/cli/codegen, there you will find different kind of tests for our codegen. FileCheck based tests that verify the IR after a certain pass(es), and end-to-end tests that execute daphne and verify the output. You should add a single file, e.g., test/codegen/sliceop.mlir for the IR tests and a single .cpp file for the end-to-end tests that compare the non codegen with the codegen'd execution of daphne.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
X = [1, 2, 3, 4, 5, 6, 7, 8, 9](3, 3);
//Y = transpose(X);
i=2;j=2;k=2;
n=1*3;

outSliceRow = X[:2, :];
print(outSliceRow);


//outExtractRow = X[ [0, 2], :];
//outSliceCol = X[:, :2];
//outExtractCol = X[:, [0, 2] ];

//print(Y);
//print(outExtractRow);
//print(outSliceCol);
//print(outExtractCol);
4 changes: 4 additions & 0 deletions src/compiler/execution/DaphneIrExecutor.cpp
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine these into a single pass which has two rewrite patterns.

Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ void DaphneIrExecutor::buildCodegenPipeline(mlir::PassManager &pm) {
pm.addPass(mlir::daphne::createAggDimOpLoweringPass());
pm.addPass(mlir::daphne::createMapOpLoweringPass());
pm.addPass(mlir::daphne::createTransposeOpLoweringPass());

pm.addPass(mlir::daphne::createSliceRowOpLoweringPass());
pm.addPass(mlir::daphne::createSliceColOpLoweringPass());

pm.addPass(mlir::createInlinerPass());

pm.addNestedPass<mlir::func::FuncOp>(mlir::createLoopFusionPass());
Expand Down
3 changes: 3 additions & 0 deletions src/compiler/lowering/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ add_mlir_dialect_library(MLIRDaphneTransforms
AggDimOpLowering.cpp
TransposeOpLowering.cpp

SliceRowOpLowering.cpp
SliceColOpLowering.cpp

DEPENDS
MLIRDaphneOpsIncGen
MLIRDaphneTransformsIncGen
Expand Down
178 changes: 178 additions & 0 deletions src/compiler/lowering/SliceColOpLowering.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright 2024 The DAPHNE Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "compiler/utils/LoweringUtils.h"
#include "ir/daphneir/Daphne.h"
#include "ir/daphneir/Passes.h"

#include "mlir/Conversion/AffineToStandard/AffineToStandard.h"
#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
#include "mlir/Conversion/LLVMCommon/LoweringOptions.h"
#include "mlir/Conversion/LLVMCommon/TypeConverter.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/Transforms/FuncConversions.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinDialect.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/UseDefLists.h"
#include "mlir/IR/Value.h"
#include "mlir/IR/ValueRange.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Transforms/DialectConversion.h"


using namespace mlir;
using namespace std;

//template<class SliceOp>
class SliceColOpLowering : public OpConversionPattern<daphne::SliceColOp> {
public:
using OpConversionPattern::OpConversionPattern;

explicit SliceColOpLowering(TypeConverter &typeConverter, MLIRContext *ctx)
: mlir::OpConversionPattern<daphne::SliceColOp>(typeConverter, ctx, PatternBenefit(1)) {
this->setDebugName("SliceColOpLowering");
}

/**
* @brief Replaces a Transpose operation with a Linalg TransposeOp if possible.
*
* @return mlir::success if Transpose has been replaced, else mlir::failure.
*/
LogicalResult matchAndRewrite(daphne::SliceColOp op, OpAdaptor adaptor,
ConversionPatternRewriter &rewriter) const override {

daphne::MatrixType matrixType = adaptor.getSource().getType().dyn_cast<daphne::MatrixType>();
if (!matrixType) {
return failure();
}

Location loc = op->getLoc();

Type matrixElementType = matrixType.getElementType();
ssize_t numRows = matrixType.getNumRows();
ssize_t numCols = matrixType.getNumCols();

if (numRows < 0 || numCols < 0) {
return rewriter.notifyMatchFailure(
op, "sliceColOp codegen currently only works with matrix dimensions that are known at compile time");
}

Value argMemref = rewriter.create<daphne::ConvertDenseMatrixToMemRef>(
loc, MemRefType::get({numRows, numCols}, matrixElementType), adaptor.getSource());

auto lowerIncl = adaptor.getLowerIncl().getDefiningOp<daphne::ConstantOp>().getValue().dyn_cast<mlir::IntegerAttr>().getSInt();
auto upperExcl = adaptor.getUpperExcl().getDefiningOp<daphne::ConstantOp>().getValue().dyn_cast<mlir::IntegerAttr>().getSInt();

Value resMemref = rewriter.create<memref::AllocOp>(loc, MemRefType::get({numRows, (upperExcl-lowerIncl)}, matrixElementType));

DenseI64ArrayAttr offset = rewriter.getDenseI64ArrayAttr({0, lowerIncl});
DenseI64ArrayAttr sizes = rewriter.getDenseI64ArrayAttr({numRows, (upperExcl-lowerIncl)});
DenseI64ArrayAttr strides = rewriter.getDenseI64ArrayAttr({1, 1});

Value selMemref = rewriter.create<memref::SubViewOp>(loc, argMemref, offset, sizes, strides);

SmallVector<AffineMap, 2> indexMaps{AffineMap::getMultiDimIdentityMap(2, rewriter.getContext()),
AffineMap::getMultiDimIdentityMap(2, rewriter.getContext())};

SmallVector<utils::IteratorType, 2> iterTypes{utils::IteratorType::parallel,
utils::IteratorType::parallel};

rewriter.create<linalg::GenericOp>(loc, TypeRange{}, ValueRange{selMemref}, ValueRange{resMemref},
indexMaps, iterTypes,
[&](OpBuilder &OpBuilderNested, Location locNested, ValueRange arg) {
OpBuilderNested.create<linalg::YieldOp>(locNested, arg[0]);
});
Comment on lines +105 to +115
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't be needed, as we want to create a view of a matrix we don't want to copy the data. The memref::SubViewOp should be enough. You'll need to properly lower it afterwards by adding the following passes to the pipeline:
mlir::memref::createExpandStridedMetadataPass; and mlir::createFinalizeMemRefToLLVMConversionPass.


Value resDenseMatrix = convertMemRefToDenseMatrix(loc, rewriter, resMemref, op.getType());

rewriter.replaceOp(op, resDenseMatrix);

return success();
}
};

namespace {
/**
* @brief Lowers the daphne::Transpose operator to a Linalg TransposeOp.
*
* This rewrite may enable loop fusion on the affine loops TransposeOp is
* lowered to by running the loop fusion pass.
*/
struct SliceColLoweringPass : public mlir::PassWrapper<SliceColLoweringPass, mlir::OperationPass<mlir::ModuleOp>> {
explicit SliceColLoweringPass() {}

StringRef getArgument() const final { return "lower-slice-col"; }
StringRef getDescription() const final { return "Lowers SliceCol operators to a Memref SubViewOp."; }

void getDependentDialects(mlir::DialectRegistry &registry) const override {
registry.insert<mlir::LLVM::LLVMDialect, mlir::linalg::LinalgDialect, mlir::memref::MemRefDialect>();
}
void runOnOperation() final;
};
} // end anonymous namespace

void SliceColLoweringPass::runOnOperation() {
mlir::ConversionTarget target(getContext());
mlir::RewritePatternSet patterns(&getContext());
LowerToLLVMOptions llvmOptions(&getContext());
LLVMTypeConverter typeConverter(&getContext(), llvmOptions);

typeConverter.addConversion(convertInteger);
typeConverter.addConversion(convertFloat);
typeConverter.addConversion([](Type type) { return type; });
typeConverter.addArgumentMaterialization(materializeCastFromIllegal);
typeConverter.addSourceMaterialization(materializeCastToIllegal);
typeConverter.addTargetMaterialization(materializeCastFromIllegal);

target.addLegalDialect<BuiltinDialect, daphne::DaphneDialect, linalg::LinalgDialect, memref::MemRefDialect>();

target.addDynamicallyLegalOp<daphne::SliceColOp>([](Operation *op) {
Type operand = op->getOperand(0).getType();
daphne::MatrixType matType = operand.dyn_cast<daphne::MatrixType>();
if (matType && matType.getRepresentation() == daphne::MatrixRepresentation::Dense) {
return false;
}
return true;
});

patterns.insert<SliceColOpLowering>(typeConverter, &getContext());
auto module = getOperation();
if (failed(applyPartialConversion(module, target, std::move(patterns)))) {
signalPassFailure();
}
}

std::unique_ptr<mlir::Pass> daphne::createSliceColOpLoweringPass() {
return std::make_unique<SliceColLoweringPass>();
}
Loading