Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 18 additions & 15 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class LLVM_TerminatorOp<string mnemonic, list<Trait> traits = []> :
class LLVM_ArithmeticOpBase<Type type, string mnemonic,
string instName, list<Trait> traits = []> :
LLVM_Op<mnemonic,
!listconcat([Pure, SameOperandsAndResultType], traits)>,
!listconcat([SameOperandsAndResultType, NoMemoryEffect], traits)>,
LLVM_Builder<"$res = builder.Create" # instName # "($lhs, $rhs);"> {
dag commonArgs = (ins LLVM_ScalarOrVectorOf<type>:$lhs,
LLVM_ScalarOrVectorOf<type>:$rhs);
Expand Down Expand Up @@ -116,7 +116,8 @@ class LLVM_IntArithmeticOpWithDisjointFlag<string mnemonic, string instName,
class LLVM_FloatArithmeticOp<string mnemonic, string instName,
list<Trait> traits = []> :
LLVM_ArithmeticOpBase<LLVM_AnyFloat, mnemonic, instName,
!listconcat([DeclareOpInterfaceMethods<FastmathFlagsInterface>], traits)> {
!listconcat([DeclareOpInterfaceMethods<FastmathFlagsInterface>, Pure],
traits)> {
dag fmfArg = (
ins DefaultValuedAttr<LLVM_FastmathFlagsAttr, "{}">:$fastmathFlags);
let arguments = !con(commonArgs, fmfArg);
Expand Down Expand Up @@ -149,24 +150,26 @@ class LLVM_UnaryFloatArithmeticOp<Type type, string mnemonic,

// Integer binary operations.
def LLVM_AddOp : LLVM_IntArithmeticOpWithOverflowFlag<"add", "Add",
[Commutative]>;
def LLVM_SubOp : LLVM_IntArithmeticOpWithOverflowFlag<"sub", "Sub", []>;
[Commutative, Pure]>;
def LLVM_SubOp : LLVM_IntArithmeticOpWithOverflowFlag<"sub", "Sub", [Pure]>;
def LLVM_MulOp : LLVM_IntArithmeticOpWithOverflowFlag<"mul", "Mul",
[Commutative]>;
def LLVM_UDivOp : LLVM_IntArithmeticOpWithExactFlag<"udiv", "UDiv">;
def LLVM_SDivOp : LLVM_IntArithmeticOpWithExactFlag<"sdiv", "SDiv">;
def LLVM_URemOp : LLVM_IntArithmeticOp<"urem", "URem">;
def LLVM_SRemOp : LLVM_IntArithmeticOp<"srem", "SRem">;
def LLVM_AndOp : LLVM_IntArithmeticOp<"and", "And">;
def LLVM_OrOp : LLVM_IntArithmeticOpWithDisjointFlag<"or", "Or"> {
[Commutative, Pure]>;
def LLVM_UDivOp : LLVM_IntArithmeticOpWithExactFlag<"udiv", "UDiv",
[DeclareOpInterfaceMethods<ConditionallySpeculatable>]>;
def LLVM_SDivOp : LLVM_IntArithmeticOpWithExactFlag<"sdiv", "SDiv",
[DeclareOpInterfaceMethods<ConditionallySpeculatable>]>;
def LLVM_URemOp : LLVM_IntArithmeticOp<"urem", "URem", [Pure]>;
def LLVM_SRemOp : LLVM_IntArithmeticOp<"srem", "SRem", [Pure]>;
def LLVM_AndOp : LLVM_IntArithmeticOp<"and", "And", [Pure]>;
def LLVM_OrOp : LLVM_IntArithmeticOpWithDisjointFlag<"or", "Or", [Pure]> {
let hasFolder = 1;
}
def LLVM_XOrOp : LLVM_IntArithmeticOp<"xor", "Xor">;
def LLVM_ShlOp : LLVM_IntArithmeticOpWithOverflowFlag<"shl", "Shl", []> {
def LLVM_XOrOp : LLVM_IntArithmeticOp<"xor", "Xor", [Pure]>;
def LLVM_ShlOp : LLVM_IntArithmeticOpWithOverflowFlag<"shl", "Shl", [Pure]> {
let hasFolder = 1;
}
def LLVM_LShrOp : LLVM_IntArithmeticOpWithExactFlag<"lshr", "LShr">;
def LLVM_AShrOp : LLVM_IntArithmeticOpWithExactFlag<"ashr", "AShr">;
def LLVM_LShrOp : LLVM_IntArithmeticOpWithExactFlag<"lshr", "LShr", [Pure]>;
def LLVM_AShrOp : LLVM_IntArithmeticOpWithExactFlag<"ashr", "AShr", [Pure]>;

// Base class for compare operations. A compare operation takes two operands
// of the same type and returns a boolean result. If the operands are
Expand Down
28 changes: 28 additions & 0 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4225,6 +4225,34 @@ LogicalResult InlineAsmOp::verify() {
return success();
}

//===----------------------------------------------------------------------===//
// UDivOp
//===----------------------------------------------------------------------===//
Speculation::Speculatability UDivOp::getSpeculatability() {
// X / 0 => UB
Value divisor = getRhs();
if (matchPattern(divisor, m_IntRangeWithoutZeroU()))
return Speculation::Speculatable;

return Speculation::NotSpeculatable;
}

//===----------------------------------------------------------------------===//
// SDivOp
//===----------------------------------------------------------------------===//
Speculation::Speculatability SDivOp::getSpeculatability() {
// This function conservatively assumes that all signed division by -1 are
// not speculatable.
// X / 0 => UB
// INT_MIN / -1 => UB
Value divisor = getRhs();
if (matchPattern(divisor, m_IntRangeWithoutZeroS()) &&
matchPattern(divisor, m_IntRangeWithoutNegOneS()))
return Speculation::Speculatable;

return Speculation::NotSpeculatable;
}

//===----------------------------------------------------------------------===//
// LLVMDialect initialization, type parsing, and registration.
//===----------------------------------------------------------------------===//
Expand Down
145 changes: 145 additions & 0 deletions mlir/test/Transforms/loop-invariant-code-motion.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,18 @@ func.func @no_speculate_divui(
return
}

func.func @no_speculate_udiv(
// CHECK-LABEL: @no_speculate_udiv(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.udiv
%val = llvm.udiv %num, %denom : i32
}

return
}

func.func @no_speculate_divsi(
// CHECK-LABEL: @no_speculate_divsi(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
Expand All @@ -892,6 +904,18 @@ func.func @no_speculate_divsi(
return
}

func.func @no_speculate_sdiv(
// CHECK-LABEL: @no_speculate_sdiv(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.sdiv
%val = llvm.sdiv %num, %denom : i32
}

return
}

func.func @no_speculate_ceildivui(
// CHECK-LABEL: @no_speculate_ceildivui(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
Expand Down Expand Up @@ -928,6 +952,18 @@ func.func @no_speculate_divui_const(%num: i32, %lb: index, %ub: index, %step: in
return
}

func.func @no_speculate_udiv_const(%num: i32, %lb: index, %ub: index, %step: index) {
// CHECK-LABEL: @no_speculate_udiv_const(
%c0 = arith.constant 0 : i32
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.udiv
%val = llvm.udiv %num, %c0 : i32
}

return
}

func.func @speculate_divui_const(
// CHECK-LABEL: @speculate_divui_const(
%num: i32, %lb: index, %ub: index, %step: index) {
Expand All @@ -941,6 +977,19 @@ func.func @speculate_divui_const(
return
}

func.func @speculate_udiv_const(
// CHECK-LABEL: @speculate_udiv_const(
%num: i32, %lb: index, %ub: index, %step: index) {
%c5 = llvm.mlir.constant(5 : i32) : i32
// CHECK: llvm.udiv
// CHECK: scf.for
scf.for %i = %lb to %ub step %step {
%val = llvm.udiv %num, %c5 : i32
}

return
}

func.func @no_speculate_ceildivui_const(%num: i32, %lb: index, %ub: index, %step: index) {
// CHECK-LABEL: @no_speculate_ceildivui_const(
%c0 = arith.constant 0 : i32
Expand Down Expand Up @@ -979,6 +1028,19 @@ func.func @no_speculate_divsi_const0(
return
}

func.func @no_speculate_sdiv_const0(
// CHECK-LABEL: @no_speculate_sdiv_const0(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
%c0 = arith.constant 0 : i32
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.sdiv
%val = llvm.sdiv %num, %c0 : i32
}

return
}

func.func @no_speculate_divsi_const_minus1(
// CHECK-LABEL: @no_speculate_divsi_const_minus1(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
Expand All @@ -992,6 +1054,19 @@ func.func @no_speculate_divsi_const_minus1(
return
}

func.func @no_speculate_sdiv_const_minus1(
// CHECK-LABEL: @no_speculate_sdiv_const_minus1(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
%cm1 = arith.constant -1 : i32
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.sdiv
%val = llvm.sdiv %num, %cm1 : i32
}

return
}

func.func @speculate_divsi_const(
// CHECK-LABEL: @speculate_divsi_const(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
Expand All @@ -1005,6 +1080,19 @@ func.func @speculate_divsi_const(
return
}

func.func @speculate_sdiv_const(
// CHECK-LABEL: @speculate_sdiv_const(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
%c5 = arith.constant 5 : i32
scf.for %i = %lb to %ub step %step {
// CHECK: llvm.sdiv
// CHECK: scf.for
%val = llvm.sdiv %num, %c5 : i32
}

return
}

func.func @no_speculate_ceildivsi_const0(
// CHECK-LABEL: @no_speculate_ceildivsi_const0(
%num: i32, %denom: i32, %lb: index, %ub: index, %step: index) {
Expand Down Expand Up @@ -1057,6 +1145,19 @@ func.func @no_speculate_divui_range(
return
}

func.func @no_speculate_udiv_range(
// CHECK-LABEL: @no_speculate_udiv_range(
%num: i8, %lb: index, %ub: index, %step: index) {
%denom = test.with_bounds {smax = 127 : i8, smin = -128 : i8, umax = 255 : i8, umin = 0 : i8} : i8
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK: llvm.udiv
%val = llvm.udiv %num, %denom : i8
}

return
}

func.func @no_speculate_divsi_range(
// CHECK-LABEL: @no_speculate_divsi_range(
%num: i8, %lb: index, %ub: index, %step: index) {
Expand All @@ -1072,6 +1173,21 @@ func.func @no_speculate_divsi_range(
return
}

func.func @no_speculate_sdiv_range(
// CHECK-LABEL: @no_speculate_sdiv_range(
%num: i8, %lb: index, %ub: index, %step: index) {
%denom0 = test.with_bounds {smax = -1: i8, smin = -128 : i8, umax = 255 : i8, umin = 0 : i8} : i8
%denom1 = test.with_bounds {smax = 127 : i8, smin = 0 : i8, umax = 255 : i8, umin = 0 : i8} : i8
scf.for %i = %lb to %ub step %step {
// CHECK: scf.for
// CHECK-COUNT-2: llvm.sdiv
%val0 = llvm.sdiv %num, %denom0 : i8
%val1 = llvm.sdiv %num, %denom1 : i8
}

return
}

func.func @no_speculate_ceildivui_range(
// CHECK-LABEL: @no_speculate_ceildivui_range(
%num: i8, %lb: index, %ub: index, %step: index) {
Expand Down Expand Up @@ -1113,6 +1229,19 @@ func.func @speculate_divui_range(
return
}

func.func @speculate_udiv_range(
// CHECK-LABEL: @speculate_udiv_range(
%num: i8, %lb: index, %ub: index, %step: index) {
%denom = test.with_bounds {smax = 127 : i8, smin = -128 : i8, umax = 255 : i8, umin = 1 : i8} : i8
scf.for %i = %lb to %ub step %step {
// CHECK: llvm.udiv
// CHECK: scf.for
%val = llvm.udiv %num, %denom : i8
}

return
}

func.func @speculate_divsi_range(
// CHECK-LABEL: @speculate_divsi_range(
%num: i8, %lb: index, %ub: index, %step: index) {
Expand All @@ -1129,6 +1258,22 @@ func.func @speculate_divsi_range(
return
}

func.func @speculate_sdiv_range(
// CHECK-LABEL: @speculate_sdiv_range(
%num: i8, %lb: index, %ub: index, %step: index) {
%denom0 = test.with_bounds {smax = 127 : i8, smin = 1 : i8, umax = 255 : i8, umin = 0 : i8} : i8
%denom1 = test.with_bounds {smax = -2 : i8, smin = -128 : i8, umax = 255 : i8, umin = 0 : i8} : i8
scf.for %i = %lb to %ub step %step {
// CHECK-COUNT-2: llvm.sdiv
// CHECK: scf.for
%val0 = llvm.sdiv %num, %denom0 : i8
%val1 = llvm.sdiv %num, %denom1 : i8

}

return
}

func.func @speculate_ceildivui_range(
// CHECK-LABEL: @speculate_ceildivui_range(
%num: i8, %lb: index, %ub: index, %step: index) {
Expand Down
1 change: 1 addition & 0 deletions mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ add_mlir_unittest(MLIRLLVMIRTests
mlir_target_link_libraries(MLIRLLVMIRTests
PRIVATE
MLIRLLVMDialect
MLIRInferIntRangeInterface
)