|
19 | 19 | #include "mlir/Dialect/DLTI/DLTI.h"
|
20 | 20 | #include "mlir/Dialect/Func/IR/FuncOps.h"
|
21 | 21 | #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
|
| 22 | +#include "mlir/IR/BuiltinAttributes.h" |
22 | 23 | #include "mlir/IR/BuiltinDialect.h"
|
23 | 24 | #include "mlir/IR/BuiltinOps.h"
|
24 | 25 | #include "mlir/IR/Types.h"
|
|
28 | 29 | #include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
|
29 | 30 | #include "mlir/Target/LLVMIR/Export.h"
|
30 | 31 | #include "mlir/Transforms/DialectConversion.h"
|
| 32 | +#include "clang/CIR/Dialect/IR/CIRAttrs.h" |
31 | 33 | #include "clang/CIR/Dialect/IR/CIRDialect.h"
|
32 | 34 | #include "clang/CIR/Dialect/Passes.h"
|
33 | 35 | #include "clang/CIR/LoweringHelpers.h"
|
@@ -1292,6 +1294,90 @@ mlir::LogicalResult CIRToLLVMCmpOpLowering::matchAndRewrite(
|
1292 | 1294 | return mlir::success();
|
1293 | 1295 | }
|
1294 | 1296 |
|
| 1297 | +mlir::LogicalResult CIRToLLVMShiftOpLowering::matchAndRewrite( |
| 1298 | + cir::ShiftOp op, OpAdaptor adaptor, |
| 1299 | + mlir::ConversionPatternRewriter &rewriter) const { |
| 1300 | + auto cirAmtTy = mlir::dyn_cast<cir::IntType>(op.getAmount().getType()); |
| 1301 | + auto cirValTy = mlir::dyn_cast<cir::IntType>(op.getValue().getType()); |
| 1302 | + |
| 1303 | + // Operands could also be vector type |
| 1304 | + assert(!cir::MissingFeatures::vectorType()); |
| 1305 | + mlir::Type llvmTy = getTypeConverter()->convertType(op.getType()); |
| 1306 | + mlir::Value amt = adaptor.getAmount(); |
| 1307 | + mlir::Value val = adaptor.getValue(); |
| 1308 | + |
| 1309 | + // TODO(cir): Assert for vector types |
| 1310 | + assert((cirValTy && cirAmtTy) && |
| 1311 | + "shift input type must be integer or vector type, otherwise NYI"); |
| 1312 | + |
| 1313 | + assert((cirValTy == op.getType()) && "inconsistent operands' types NYI"); |
| 1314 | + |
| 1315 | + // Ensure shift amount is the same type as the value. Some undefined |
| 1316 | + // behavior might occur in the casts below as per [C99 6.5.7.3]. |
| 1317 | + // Vector type shift amount needs no cast as type consistency is expected to |
| 1318 | + // be already be enforced at CIRGen. |
| 1319 | + if (cirAmtTy) |
| 1320 | + amt = getLLVMIntCast(rewriter, amt, mlir::cast<mlir::IntegerType>(llvmTy), |
| 1321 | + true, cirAmtTy.getWidth(), cirValTy.getWidth()); |
| 1322 | + |
| 1323 | + // Lower to the proper LLVM shift operation. |
| 1324 | + if (op.getIsShiftleft()) { |
| 1325 | + rewriter.replaceOpWithNewOp<mlir::LLVM::ShlOp>(op, llvmTy, val, amt); |
| 1326 | + } else { |
| 1327 | + assert(!cir::MissingFeatures::vectorType()); |
| 1328 | + bool isUnsigned = !cirValTy.isSigned(); |
| 1329 | + if (isUnsigned) |
| 1330 | + rewriter.replaceOpWithNewOp<mlir::LLVM::LShrOp>(op, llvmTy, val, amt); |
| 1331 | + else |
| 1332 | + rewriter.replaceOpWithNewOp<mlir::LLVM::AShrOp>(op, llvmTy, val, amt); |
| 1333 | + } |
| 1334 | + |
| 1335 | + return mlir::success(); |
| 1336 | +} |
| 1337 | + |
| 1338 | +mlir::LogicalResult CIRToLLVMSelectOpLowering::matchAndRewrite( |
| 1339 | + cir::SelectOp op, OpAdaptor adaptor, |
| 1340 | + mlir::ConversionPatternRewriter &rewriter) const { |
| 1341 | + auto getConstantBool = [](mlir::Value value) -> cir::BoolAttr { |
| 1342 | + auto definingOp = |
| 1343 | + mlir::dyn_cast_if_present<cir::ConstantOp>(value.getDefiningOp()); |
| 1344 | + if (!definingOp) |
| 1345 | + return {}; |
| 1346 | + |
| 1347 | + auto constValue = mlir::dyn_cast<cir::BoolAttr>(definingOp.getValue()); |
| 1348 | + if (!constValue) |
| 1349 | + return {}; |
| 1350 | + |
| 1351 | + return constValue; |
| 1352 | + }; |
| 1353 | + |
| 1354 | + // Two special cases in the LLVMIR codegen of select op: |
| 1355 | + // - select %0, %1, false => and %0, %1 |
| 1356 | + // - select %0, true, %1 => or %0, %1 |
| 1357 | + if (mlir::isa<cir::BoolType>(op.getTrueValue().getType())) { |
| 1358 | + cir::BoolAttr trueValue = getConstantBool(op.getTrueValue()); |
| 1359 | + cir::BoolAttr falseValue = getConstantBool(op.getFalseValue()); |
| 1360 | + if (falseValue && !falseValue.getValue()) { |
| 1361 | + // select %0, %1, false => and %0, %1 |
| 1362 | + rewriter.replaceOpWithNewOp<mlir::LLVM::AndOp>(op, adaptor.getCondition(), |
| 1363 | + adaptor.getTrueValue()); |
| 1364 | + return mlir::success(); |
| 1365 | + } |
| 1366 | + if (trueValue && trueValue.getValue()) { |
| 1367 | + // select %0, true, %1 => or %0, %1 |
| 1368 | + rewriter.replaceOpWithNewOp<mlir::LLVM::OrOp>(op, adaptor.getCondition(), |
| 1369 | + adaptor.getFalseValue()); |
| 1370 | + return mlir::success(); |
| 1371 | + } |
| 1372 | + } |
| 1373 | + |
| 1374 | + mlir::Value llvmCondition = adaptor.getCondition(); |
| 1375 | + rewriter.replaceOpWithNewOp<mlir::LLVM::SelectOp>( |
| 1376 | + op, llvmCondition, adaptor.getTrueValue(), adaptor.getFalseValue()); |
| 1377 | + |
| 1378 | + return mlir::success(); |
| 1379 | +} |
| 1380 | + |
1295 | 1381 | static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
|
1296 | 1382 | mlir::DataLayout &dataLayout) {
|
1297 | 1383 | converter.addConversion([&](cir::PointerType type) -> mlir::Type {
|
@@ -1465,6 +1551,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
|
1465 | 1551 | CIRToLLVMConstantOpLowering,
|
1466 | 1552 | CIRToLLVMFuncOpLowering,
|
1467 | 1553 | CIRToLLVMGetGlobalOpLowering,
|
| 1554 | + CIRToLLVMSelectOpLowering, |
| 1555 | + CIRToLLVMShiftOpLowering, |
1468 | 1556 | CIRToLLVMTrapOpLowering,
|
1469 | 1557 | CIRToLLVMUnaryOpLowering
|
1470 | 1558 | // clang-format on
|
|
0 commit comments