-
Notifications
You must be signed in to change notification settings - Fork 15.2k
Fix side effects for LLVM integer operations (udiv, sdiv) incorrectly marked as Pure #166648
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
Conversation
|
@llvm/pr-subscribers-mlir Author: Jeremy Furtek (jfurtek) ChangesThis MR modifies side effect traits of some integer arithmetic operations in the LLVM dialect. Prior to this MR, the LLVM dialect This MR modifies the ed39825 Full diff: https://github.com/llvm/llvm-project/pull/166648.diff 4 Files Affected:
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index e425e16a4b1a6..971710fa3ee13 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -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);
@@ -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);
@@ -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
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 2731069d6ef54..da82809a9ddb0 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -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.
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Transforms/loop-invariant-code-motion.mlir b/mlir/test/Transforms/loop-invariant-code-motion.mlir
index c1604e226a334..31a4f64dd7de0 100644
--- a/mlir/test/Transforms/loop-invariant-code-motion.mlir
+++ b/mlir/test/Transforms/loop-invariant-code-motion.mlir
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
diff --git a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
index 7cc130d02ad74..568126fd342cc 100644
--- a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
@@ -4,4 +4,5 @@ add_mlir_unittest(MLIRLLVMIRTests
mlir_target_link_libraries(MLIRLLVMIRTests
PRIVATE
MLIRLLVMDialect
+ MLIRInferIntRangeInterface
)
|
|
@llvm/pr-subscribers-mlir-llvm Author: Jeremy Furtek (jfurtek) ChangesThis MR modifies side effect traits of some integer arithmetic operations in the LLVM dialect. Prior to this MR, the LLVM dialect This MR modifies the ed39825 Full diff: https://github.com/llvm/llvm-project/pull/166648.diff 4 Files Affected:
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index e425e16a4b1a6..971710fa3ee13 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -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);
@@ -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);
@@ -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
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 2731069d6ef54..da82809a9ddb0 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -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.
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Transforms/loop-invariant-code-motion.mlir b/mlir/test/Transforms/loop-invariant-code-motion.mlir
index c1604e226a334..31a4f64dd7de0 100644
--- a/mlir/test/Transforms/loop-invariant-code-motion.mlir
+++ b/mlir/test/Transforms/loop-invariant-code-motion.mlir
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
diff --git a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
index 7cc130d02ad74..568126fd342cc 100644
--- a/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/unittests/Dialect/LLVMIR/CMakeLists.txt
@@ -4,4 +4,5 @@ add_mlir_unittest(MLIRLLVMIRTests
mlir_target_link_libraries(MLIRLLVMIRTests
PRIVATE
MLIRLLVMDialect
+ MLIRInferIntRangeInterface
)
|
|
These seems legit build failures: https://lab.llvm.org/buildbot/#/builders/138/builds/21929 |
|
Looking into it now... |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/204/builds/28197 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/203/builds/29385 Here is the relevant piece of the build log for the reference |
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/205/builds/28176 Here is the relevant piece of the build log for the reference |
…face) (#168440) This MR fixes a recent build breakage by this MR: #166648 (Post-merge build error here: https://lab.llvm.org/buildbot/#/builders/138/builds/21929) The `MLIRInferIntRangeInterface` library is now a public dependency of `MLIRLLVMDialect`.
…tRangeInterface) (#168440) This MR fixes a recent build breakage by this MR: llvm/llvm-project#166648 (Post-merge build error here: https://lab.llvm.org/buildbot/#/builders/138/builds/21929) The `MLIRInferIntRangeInterface` library is now a public dependency of `MLIRLLVMDialect`.
This MR modifies side effect traits of some integer arithmetic operations in the LLVM dialect.
Prior to this MR, the LLVM dialect
sdivandudivoperations were marked asPurethroughtblgeninheritance of theLLVM_ArithmeticOpBaseclass. ThePuretrait allowed incorrect hoisting ofsdiv/udivoperations by theloop-independent-code-motionpass.This MR modifies the
sdivandudivLLVM operations to have traits and code motion behavior identical to their counterparts in thearithdialect, which were established by the commit/review below.ed39825
https://reviews.llvm.org/D137814