Skip to content

Commit 3cbc73f

Browse files
authored
[MLIR][Arith] Add CeilFloorDivExpandOpsPatterns to conversion to LLVM (Reland) (#118839)
When running `convert-to-llvm`, `ceildiv` and `floordiv` ops, which do not have direct llvm conversion pattern, would not get lowered to llvm dialect. This patch adds CeilFloorDivExpandOpsPatterns to both `convert-to-llvm` and `arith-to-llvm` (deprecated) lowering those ops to lower level arith ops which can be lowered to llvm using LLVM conversion. Reland of #117305 after buildbot failures. See: https://lab.llvm.org/buildbot/#/builders/80/builds/7168 https://lab.llvm.org/buildbot/#/builders/130/builds/7036 https://lab.llvm.org/buildbot/#/builders/138/builds/7290 Added dependence to ArithTransforms in ArithToLLVM. In previous discussion, it has been suggested to move the CeilFloorDivExpandOpsPatterns to ArithUtils but I think linking ArithTransforms makes more sense as otherwise : * ArithToLLVM needs a new dependency to ArithUtils * ArithUtils needs new dependency to ArithTransforms or move the patterns as well which will create more dependencies * It creates lots of code motion which makes it hard to review.
1 parent d1a7225 commit 3cbc73f

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

mlir/lib/Conversion/ArithToLLVM/ArithToLLVM.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
1414
#include "mlir/Conversion/LLVMCommon/VectorPattern.h"
1515
#include "mlir/Dialect/Arith/IR/Arith.h"
16+
#include "mlir/Dialect/Arith/Transforms/Passes.h"
1617
#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
1718
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1819
#include "mlir/IR/TypeUtilities.h"
@@ -477,7 +478,8 @@ struct ArithToLLVMConversionPass
477478
options.overrideIndexBitwidth(indexBitwidth);
478479

479480
LLVMTypeConverter converter(&getContext(), options);
480-
mlir::arith::populateArithToLLVMConversionPatterns(converter, patterns);
481+
arith::populateCeilFloorDivExpandOpsPatterns(patterns);
482+
arith::populateArithToLLVMConversionPatterns(converter, patterns);
481483

482484
if (failed(applyPartialConversion(getOperation(), target,
483485
std::move(patterns))))
@@ -503,6 +505,7 @@ struct ArithToLLVMDialectInterface : public ConvertToLLVMPatternInterface {
503505
void populateConvertToLLVMConversionPatterns(
504506
ConversionTarget &target, LLVMTypeConverter &typeConverter,
505507
RewritePatternSet &patterns) const final {
508+
arith::populateCeilFloorDivExpandOpsPatterns(patterns);
506509
arith::populateArithToLLVMConversionPatterns(typeConverter, patterns);
507510
}
508511
};

mlir/lib/Conversion/ArithToLLVM/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ add_mlir_conversion_library(MLIRArithToLLVM
1313
LINK_LIBS PUBLIC
1414
MLIRArithAttrToLLVMConversion
1515
MLIRArithDialect
16+
MLIRArithTransforms
1617
MLIRLLVMCommonConversion
1718
MLIRLLVMDialect
1819
)

mlir/test/Conversion/ArithToLLVM/arith-to-llvm.mlir

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,68 @@ func.func @select(%arg0 : i1, %arg1 : i32, %arg2 : i32) -> i32 {
540540

541541
// -----
542542

543+
// CHECK-LABEL: @ceildivsi
544+
// CHECK-SAME: %[[ARG0:.*]]: i64) -> i64
545+
func.func @ceildivsi(%arg0 : i64) -> i64 {
546+
// CHECK: %[[CST0:.*]] = llvm.mlir.constant(1 : i64) : i64
547+
// CHECK: %[[CST1:.*]] = llvm.mlir.constant(0 : i64) : i64
548+
// CHECK: %[[CST2:.*]] = llvm.mlir.constant(-1 : i64) : i64
549+
// CHECK: %[[CMP0:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
550+
// CHECK: %[[SEL0:.*]] = llvm.select %[[CMP0]], %[[CST2]], %[[CST0]] : i1, i64
551+
// CHECK: %[[ADD0:.*]] = llvm.add %[[SEL0]], %[[ARG0]] : i64
552+
// CHECK: %[[DIV0:.*]] = llvm.sdiv %[[ADD0]], %[[ARG0]] : i64
553+
// CHECK: %[[ADD1:.*]] = llvm.add %[[DIV0]], %[[CST0]] : i64
554+
// CHECK: %[[SUB0:.*]] = llvm.sub %[[CST1]], %[[ARG0]] : i64
555+
// CHECK: %[[DIV1:.*]] = llvm.sdiv %[[SUB0]], %[[ARG0]] : i64
556+
// CHECK: %[[SUB1:.*]] = llvm.sub %[[CST1]], %[[DIV1]] : i64
557+
// CHECK: %[[CMP1:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST1]] : i64
558+
// CHECK: %[[CMP2:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
559+
// CHECK: %[[CMP3:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST1]] : i64
560+
// CHECK: %[[CMP4:.*]] = llvm.icmp "sgt" %[[ARG0]], %[[CST1]] : i64
561+
// CHECK: %[[AND0:.*]] = llvm.and %[[CMP1]], %[[CMP3]] : i1
562+
// CHECK: %[[AND1:.*]] = llvm.and %[[CMP2]], %[[CMP4]] : i1
563+
// CHECK: %[[OR:.*]] = llvm.or %[[AND0]], %[[AND1]] : i1
564+
// CHECK: %[[SEL1:.*]] = llvm.select %[[OR]], %[[ADD1]], %[[SUB1]] : i1, i64
565+
%0 = arith.ceildivsi %arg0, %arg0 : i64
566+
return %0: i64
567+
}
568+
569+
// CHECK-LABEL: @ceildivui
570+
// CHECK-SAME: %[[ARG0:.*]]: i32) -> i32
571+
func.func @ceildivui(%arg0 : i32) -> i32 {
572+
// CHECK: %[[CST0:.*]] = llvm.mlir.constant(0 : i32) : i32
573+
// CHECK: %[[CMP0:.*]] = llvm.icmp "eq" %[[ARG0]], %[[CST0]] : i32
574+
// CHECK: %[[CST1:.*]] = llvm.mlir.constant(1 : i32) : i32
575+
// CHECK: %[[SUB0:.*]] = llvm.sub %[[ARG0]], %[[CST1]] : i32
576+
// CHECK: %[[DIV0:.*]] = llvm.udiv %[[SUB0]], %[[ARG0]] : i32
577+
// CHECK: %[[ADD0:.*]] = llvm.add %[[DIV0]], %[[CST1]] : i32
578+
// CHECK: %[[SEL0:.*]] = llvm.select %[[CMP0]], %[[CST0]], %[[ADD0]] : i1, i32
579+
%0 = arith.ceildivui %arg0, %arg0 : i32
580+
return %0: i32
581+
}
582+
583+
// -----
584+
585+
// CHECK-LABEL: @floordivsi
586+
// CHECK-SAME: %[[ARG0:.*]]: i32, %[[ARG1:.*]]: i32) -> i32
587+
func.func @floordivsi(%arg0 : i32, %arg1 : i32) -> i32 {
588+
// CHECK: %[[SDIV:.*]] = llvm.sdiv %[[ARG0]], %[[ARG1]] : i32
589+
// CHECK: %[[MUL0:.*]] = llvm.mul %[[SDIV]], %[[ARG1]] : i32
590+
// CHECK: %[[CMP0:.*]] = llvm.icmp "ne" %[[ARG0]], %[[MUL0]] : i32
591+
// CHECK: %[[CST0:.*]] = llvm.mlir.constant(0 : i32) : i32
592+
// CHECK: %[[CMP1:.*]] = llvm.icmp "slt" %[[ARG0]], %[[CST0]] : i32
593+
// CHECK: %[[CMP2:.*]] = llvm.icmp "slt" %[[ARG1]], %[[CST0]] : i32
594+
// CHECK: %[[CMP3:.*]] = llvm.icmp "ne" %[[CMP1]], %[[CMP2]] : i1
595+
// CHECK: %[[AND:.*]] = llvm.and %[[CMP0]], %[[CMP3]] : i1
596+
// CHECK: %[[CST1:.*]] = llvm.mlir.constant(-1 : i32) : i32
597+
// CHECK: %[[ADD:.*]] = llvm.add %[[SDIV]], %[[CST1]] : i32
598+
// CHECK: %[[SEL:.*]] = llvm.select %[[AND]], %[[ADD]], %[[SDIV]] : i1, i32
599+
%0 = arith.floordivsi %arg0, %arg1 : i32
600+
return %0 : i32
601+
}
602+
603+
// -----
604+
543605
// CHECK-LABEL: @minmaxi
544606
func.func @minmaxi(%arg0 : i32, %arg1 : i32) -> i32 {
545607
// CHECK: = llvm.intr.smin(%arg0, %arg1) : (i32, i32) -> i32

0 commit comments

Comments
 (0)