-
Notifications
You must be signed in to change notification settings - Fork 15.6k
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`.
…face) (#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`. Signed-off-by: Hafidz Muzakky <[email protected]>
… marked as Pure (llvm#166648) This MR modifies side effect traits of some integer arithmetic operations in the LLVM dialect. Prior to this MR, the LLVM dialect `sdiv` and `udiv` operations were marked as `Pure` through `tblgen` inheritance of the `LLVM_ArithmeticOpBase` class. The `Pure` trait allowed incorrect hoisting of `sdiv`/`udiv` operations by the `loop-independent-code-motion` pass. This MR modifies the `sdiv` and `udiv` LLVM operations to have traits and code motion behavior identical to their counterparts in the `arith` dialect, which were established by the commit/review below. llvm@ed39825 https://reviews.llvm.org/D137814
…face) (llvm#168440) This MR fixes a recent build breakage by this MR: llvm#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 bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. We also updated the scalarized_packed_fops to look specifically for v_pk(add|mul|sub) because with updated llvm we can now vectorize mov into v_pk_mov, which is unrelated to the scalarize pass. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. We also updated the scalarized_packed_fops to look specifically for v_pk(add|mul|sub) because with updated llvm we can now vectorize mov into v_pk_mov, which is unrelated to the scalarize pass. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in triton-lang@8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. We also updated the scalarized_packed_fops to look specifically for v_pk(add|mul|sub) because with updated llvm we can now vectorize mov into v_pk_mov, which is unrelated to the scalarize pass. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in 8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. This PR Replaced it with urem which is similar class of op who still has Pure trait. We also updated the scalarized_packed_fops to look specifically for v_pk(add|mul|sub) because with updated llvm we can now vectorize mov into v_pk_mov, which is unrelated to the scalarize pass. Signed-off-by: Stanley Winata <[email protected]>
This bump picks up llvm/llvm-project#169546 which resolves some register spilling in downstream use cases. Additionally, we also pick up llvm/llvm-project#166648 which converted udiv and sdiv to non Pure attributes. This require changes on warp_specialize_to_llvm.mlir `remat_subgraph` since the original test found in 8601b39 was meant to test rematerializing some "pure ops" into partition region, which the tested udiv is no longer. Replaced it with urem which is similar class of op who still has Pure trait. With latest change in LLVM, we are also vectorizing/packing `movs`. This requires a test update, since the original test checks for any `v_pk` while it is only scalarizing `v_pk_(add|mul|sub)` as seen on https://github.com/triton-lang/triton/blob/91822318570f76e8952b9a49934df97e8871492e/third_party/amd/lib/TritonAMDGPUToLLVM/ScalarizePackedFOps.cpp#L46-L52 Signed-off-by: Stanley Winata <[email protected]>
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