[Mlir-commits] [mlir] Revert "[MLIR] Add `IntegerDivisibilityAnalysis` and `InferIntDivisibilityOpInterface`" (PR #198048)
Kewen Meng
llvmlistbot at llvm.org
Fri May 15 17:23:40 PDT 2026
https://github.com/Kewen12 created https://github.com/llvm/llvm-project/pull/198048
Reverts llvm/llvm-project#197728
unblock bots:
https://lab.llvm.org/buildbot/#/builders/226
https://lab.llvm.org/buildbot/#/builders/203
>From 81c0a254380ada9aadc404318b5b8cafb810534b Mon Sep 17 00:00:00 2001
From: Kewen Meng <Kewen.Meng at amd.com>
Date: Fri, 15 May 2026 17:22:21 -0700
Subject: [PATCH] =?UTF-8?q?Revert=20"[MLIR]=20Add=20`IntegerDivisibilityAn?=
=?UTF-8?q?alysis`=20and=20`InferIntDivisibilityOpI=E2=80=A6"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit ba0fef9f9ecc5c0622e294b0bc7c27d574941cb5.
---
.../DataFlow/IntegerDivisibilityAnalysis.h | 64 ----
.../mlir/Dialect/Affine/IR/AffineOps.td | 12 +-
mlir/include/mlir/Dialect/Arith/IR/Arith.h | 1 -
.../include/mlir/Dialect/Arith/IR/ArithOps.td | 28 +-
mlir/include/mlir/Interfaces/CMakeLists.txt | 1 -
.../InferIntDivisibilityOpInterface.h | 120 -------
.../InferIntDivisibilityOpInterface.td | 41 ---
mlir/lib/Analysis/CMakeLists.txt | 3 -
.../DataFlow/IntegerDivisibilityAnalysis.cpp | 135 --------
mlir/lib/Dialect/Affine/IR/CMakeLists.txt | 2 -
.../InferIntDivisibilityOpInterfaceImpl.cpp | 312 ------------------
mlir/lib/Dialect/Arith/IR/CMakeLists.txt | 3 -
.../InferIntDivisibilityOpInterfaceImpl.cpp | 122 -------
mlir/lib/Interfaces/CMakeLists.txt | 2 -
.../InferIntDivisibilityOpInterface.cpp | 11 -
.../DataFlow/integer-divisibility.mlir | 152 ---------
mlir/test/lib/Analysis/CMakeLists.txt | 2 -
.../TestIntegerDivisibilityAnalysis.cpp | 93 ------
mlir/tools/mlir-opt/mlir-opt.cpp | 2 -
19 files changed, 11 insertions(+), 1095 deletions(-)
delete mode 100644 mlir/include/mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h
delete mode 100644 mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.h
delete mode 100644 mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.td
delete mode 100644 mlir/lib/Analysis/DataFlow/IntegerDivisibilityAnalysis.cpp
delete mode 100644 mlir/lib/Dialect/Affine/IR/InferIntDivisibilityOpInterfaceImpl.cpp
delete mode 100644 mlir/lib/Dialect/Arith/IR/InferIntDivisibilityOpInterfaceImpl.cpp
delete mode 100644 mlir/lib/Interfaces/InferIntDivisibilityOpInterface.cpp
delete mode 100644 mlir/test/Analysis/DataFlow/integer-divisibility.mlir
delete mode 100644 mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
diff --git a/mlir/include/mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h b/mlir/include/mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h
deleted file mode 100644
index 3a877647490a3..0000000000000
--- a/mlir/include/mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//===- IntegerDivisibilityAnalysis.h - Integer divisibility -----*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the dataflow analysis class for integer divisibility
-// inference. Operations participate in the analysis by implementing
-// `InferIntDivisibilityOpInterface`.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_ANALYSIS_DATAFLOW_INTEGERDIVISIBILITYANALYSIS_H
-#define MLIR_ANALYSIS_DATAFLOW_INTEGERDIVISIBILITYANALYSIS_H
-
-#include "mlir/Analysis/DataFlow/SparseAnalysis.h"
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h"
-
-namespace mlir::dataflow {
-
-/// This lattice element represents the integer divisibility of an SSA value.
-class IntegerDivisibilityLattice : public Lattice<IntegerDivisibility> {
-public:
- using Lattice::Lattice;
-};
-
-/// Integer divisibility analysis determines, for each integer-typed SSA
-/// value, a divisor that the value is guaranteed to be a multiple of. It
-/// uses operations that implement `InferIntDivisibilityOpInterface` and
-/// also sets the divisibility of induction variables of loops with known
-/// lower bounds and steps.
-///
-/// This analysis depends on DeadCodeAnalysis, and will be a silent no-op
-/// if DeadCodeAnalysis is not loaded in the same solver context.
-class IntegerDivisibilityAnalysis
- : public SparseForwardDataFlowAnalysis<IntegerDivisibilityLattice> {
-public:
- using SparseForwardDataFlowAnalysis::SparseForwardDataFlowAnalysis;
-
- /// At an entry point, set the lattice to the most pessimistic state,
- /// indicating that no further reasoning can be done.
- void setToEntryState(IntegerDivisibilityLattice *lattice) override;
-
- /// Visit an operation, invoking the transfer function.
- LogicalResult
- visitOperation(Operation *op,
- ArrayRef<const IntegerDivisibilityLattice *> operands,
- ArrayRef<IntegerDivisibilityLattice *> results) override;
-
- /// Visit block arguments or operation results of an operation with region
- /// control-flow for which values are not defined by region control-flow. This
- /// function tries to infer the divisibility of loop induction variables based
- /// on known loop bounds and steps.
- void visitNonControlFlowArguments(
- Operation *op, const RegionSuccessor &successor,
- ValueRange successorInputs,
- ArrayRef<IntegerDivisibilityLattice *> argLattices) override;
-};
-
-} // namespace mlir::dataflow
-
-#endif // MLIR_ANALYSIS_DATAFLOW_INTEGERDIVISIBILITYANALYSIS_H
diff --git a/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td b/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
index 3d7cbcc375d2a..b2a4cf7f488bd 100644
--- a/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
+++ b/mlir/include/mlir/Dialect/Affine/IR/AffineOps.td
@@ -16,7 +16,6 @@
include "mlir/Dialect/Arith/IR/ArithBase.td"
include "mlir/Dialect/Affine/IR/AffineMemoryOpInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
-include "mlir/Interfaces/InferIntDivisibilityOpInterface.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/LoopLikeInterface.td"
@@ -44,9 +43,7 @@ def ImplicitAffineTerminator
: SingleBlockImplicitTerminator<"AffineYieldOp">;
def AffineApplyOp : Affine_Op<"apply",
- [Pure,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>,
- DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
+ [Pure, DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "affine apply operation";
let description = [{
The `affine.apply` operation applies an [affine mapping](#affine-maps)
@@ -573,8 +570,7 @@ class AffineMinMaxOpBase<string mnemonic, list<Trait> traits = []> :
let hasVerifier = 1;
}
-def AffineMinOp : AffineMinMaxOpBase<"min",
- [Pure, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def AffineMinOp : AffineMinMaxOpBase<"min", [Pure]> {
let summary = "min operation";
let description = [{
Syntax:
@@ -598,8 +594,7 @@ def AffineMinOp : AffineMinMaxOpBase<"min",
}];
}
-def AffineMaxOp : AffineMinMaxOpBase<"max",
- [Pure, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def AffineMaxOp : AffineMinMaxOpBase<"max", [Pure]> {
let summary = "max operation";
let description = [{
The `affine.max` operation computes the maximum value result from a multi-result
@@ -1076,7 +1071,6 @@ def AffineVectorStoreOp : AffineStoreOpBase<"vector_store"> {
def AffineDelinearizeIndexOp : Affine_Op<"delinearize_index",
[Pure, Elementwise,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>,
// Infer linear_index type from the first result type during parsing.
TypesMatchWith<"linear_index type must match result types",
"multi_index", "linear_index", "$_self[0]">
diff --git a/mlir/include/mlir/Dialect/Arith/IR/Arith.h b/mlir/include/mlir/Dialect/Arith/IR/Arith.h
index bf6eb18df2e8a..0fc3db8e993d8 100644
--- a/mlir/include/mlir/Dialect/Arith/IR/Arith.h
+++ b/mlir/include/mlir/Dialect/Arith/IR/Arith.h
@@ -15,7 +15,6 @@
#include "mlir/IR/OpImplementation.h"
#include "mlir/Interfaces/CastInterfaces.h"
#include "mlir/Interfaces/ControlFlowInterfaces.h"
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h"
#include "mlir/Interfaces/InferIntRangeInterface.h"
#include "mlir/Interfaces/InferTypeOpInterface.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
diff --git a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
index 1f8b07aed3f0d..fa85b840e2707 100644
--- a/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
+++ b/mlir/include/mlir/Dialect/Arith/IR/ArithOps.td
@@ -13,7 +13,6 @@ include "mlir/Dialect/Arith/IR/ArithBase.td"
include "mlir/Dialect/Arith/IR/ArithOpsInterfaces.td"
include "mlir/Interfaces/CastInterfaces.td"
include "mlir/Interfaces/ControlFlowInterfaces.td"
-include "mlir/Interfaces/InferIntDivisibilityOpInterface.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
include "mlir/Interfaces/InferTypeOpInterface.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
@@ -224,7 +223,6 @@ def Arith_ConstantOp : Op<Arith_Dialect, "constant",
[ConstantLike, Pure,
DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>,
AllTypesMatch<["value", "result"]>,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRanges"]>]> {
let summary = "integer or floating point constant";
let description = [{
@@ -272,8 +270,7 @@ def Arith_ConstantOp : Op<Arith_Dialect, "constant",
// AddIOp
//===----------------------------------------------------------------------===//
-def Arith_AddIOp : Arith_IntBinaryOpWithOverflowFlags<"addi",
- [Commutative, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_AddIOp : Arith_IntBinaryOpWithOverflowFlags<"addi", [Commutative]> {
let summary = "integer addition operation";
let description = [{
Performs N-bit addition on the operands. The operands are interpreted as
@@ -419,8 +416,7 @@ def Arith_SubUIExtendedOp : Arith_Op<"subui_extended", [Pure,
// SubIOp
//===----------------------------------------------------------------------===//
-def Arith_SubIOp : Arith_IntBinaryOpWithOverflowFlags<"subi",
- [DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_SubIOp : Arith_IntBinaryOpWithOverflowFlags<"subi"> {
let summary = [{
Integer subtraction operation.
}];
@@ -465,9 +461,7 @@ def Arith_SubIOp : Arith_IntBinaryOpWithOverflowFlags<"subi",
//===----------------------------------------------------------------------===//
def Arith_MulIOp : Arith_IntBinaryOpWithOverflowFlags<"muli",
- [Commutative,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>,
- DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]
+ [Commutative, DeclareOpInterfaceMethods<OpAsmOpInterface, ["getAsmResultNames"]>]
> {
let summary = [{
Integer multiplication operation.
@@ -599,8 +593,7 @@ def Arith_MulUIExtendedOp : Arith_Op<"mului_extended", [Pure, Commutative,
//===----------------------------------------------------------------------===//
def Arith_DivUIOp : Arith_IntBinaryOpWithExactFlag<"divui",
- [ConditionallySpeculatable,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+ [ConditionallySpeculatable]> {
let summary = "unsigned integer division operation";
let description = [{
Unsigned integer division. Rounds towards zero. Treats the leading bit as
@@ -1198,8 +1191,7 @@ def Arith_MaxNumFOp : Arith_FloatBinaryOp<"maxnumf", [Commutative]> {
// MaxSIOp
//===----------------------------------------------------------------------===//
-def Arith_MaxSIOp : Arith_TotalIntBinaryOp<"maxsi",
- [Commutative, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_MaxSIOp : Arith_TotalIntBinaryOp<"maxsi", [Commutative]> {
let summary = "signed integer maximum operation";
let hasFolder = 1;
}
@@ -1208,8 +1200,7 @@ def Arith_MaxSIOp : Arith_TotalIntBinaryOp<"maxsi",
// MaxUIOp
//===----------------------------------------------------------------------===//
-def Arith_MaxUIOp : Arith_TotalIntBinaryOp<"maxui",
- [Commutative, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_MaxUIOp : Arith_TotalIntBinaryOp<"maxui", [Commutative]> {
let summary = "unsigned integer maximum operation";
let hasFolder = 1;
}
@@ -1259,8 +1250,7 @@ def Arith_MinNumFOp : Arith_FloatBinaryOp<"minnumf", [Commutative]> {
// MinSIOp
//===----------------------------------------------------------------------===//
-def Arith_MinSIOp : Arith_TotalIntBinaryOp<"minsi",
- [Commutative, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_MinSIOp : Arith_TotalIntBinaryOp<"minsi", [Commutative]> {
let summary = "signed integer minimum operation";
let hasFolder = 1;
}
@@ -1269,8 +1259,7 @@ def Arith_MinSIOp : Arith_TotalIntBinaryOp<"minsi",
// MinUIOp
//===----------------------------------------------------------------------===//
-def Arith_MinUIOp : Arith_TotalIntBinaryOp<"minui",
- [Commutative, DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>]> {
+def Arith_MinUIOp : Arith_TotalIntBinaryOp<"minui", [Commutative]> {
let summary = "unsigned integer minimum operation";
let hasFolder = 1;
}
@@ -2015,7 +2004,6 @@ class BooleanConditionOrMatchingShape<string condition, string result> :
def SelectOp : Arith_Op<"select", [Pure,
AllTypesMatch<["true_value", "false_value", "result"]>,
BooleanConditionOrMatchingShape<"condition", "result">,
- DeclareOpInterfaceMethods<InferIntDivisibilityOpInterface>,
DeclareOpInterfaceMethods<InferIntRangeInterface, ["inferResultRangesFromOptional"]>,
DeclareOpInterfaceMethods<SelectLikeOpInterface>]> {
let summary = "select operation";
diff --git a/mlir/include/mlir/Interfaces/CMakeLists.txt b/mlir/include/mlir/Interfaces/CMakeLists.txt
index 6461c68423c73..3cbc9df05f3d7 100644
--- a/mlir/include/mlir/Interfaces/CMakeLists.txt
+++ b/mlir/include/mlir/Interfaces/CMakeLists.txt
@@ -6,7 +6,6 @@ add_mlir_interface(DerivedAttributeOpInterface)
add_mlir_interface(DestinationStyleOpInterface)
add_mlir_interface(FunctionInterfaces)
add_mlir_interface(IndexingMapOpInterface)
-add_mlir_interface(InferIntDivisibilityOpInterface)
add_mlir_interface(InferIntRangeInterface)
add_mlir_interface(InferStridedMetadataInterface)
add_mlir_interface(InferTypeOpInterface)
diff --git a/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.h b/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.h
deleted file mode 100644
index 374acee05cb10..0000000000000
--- a/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//===- InferIntDivisibilityOpInterface.h - Integer Divisibility -*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains definitions of the integer divisibility inference
-// interface defined in `InferIntDivisibilityOpInterface.td`.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE_H
-#define MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE_H
-
-#include "mlir/IR/OpDefinition.h"
-#include <numeric>
-#include <optional>
-
-namespace mlir {
-
-/// Statically known divisibility information for an integer SSA value.
-/// Tracks separate divisors for the unsigned and signed interpretations of
-/// the value so that subsequent analyses can use whichever is more precise.
-class ConstantIntDivisibility {
-public:
- ConstantIntDivisibility() = default;
- ConstantIntDivisibility(uint64_t udiv, uint64_t sdiv)
- : udivVal(udiv), sdivVal(sdiv) {}
-
- bool operator==(const ConstantIntDivisibility &other) const {
- return udivVal == other.udivVal && sdivVal == other.sdivVal;
- }
-
- uint64_t udiv() const { return this->udivVal; }
- uint64_t sdiv() const { return this->sdivVal; }
-
- // Returns the union (computed separately for signed and unsigned bounds)
- // for this divisibility and `other`.
- ConstantIntDivisibility getUnion(const ConstantIntDivisibility &other) const {
- return ConstantIntDivisibility(
- /*udiv=*/std::gcd(udiv(), other.udiv()),
- /*sdiv=*/std::gcd(sdiv(), other.sdiv()));
- }
-
-private:
- uint64_t udivVal;
- uint64_t sdivVal;
-
- friend raw_ostream &operator<<(raw_ostream &os,
- const ConstantIntDivisibility &div);
-};
-
-inline raw_ostream &operator<<(raw_ostream &os,
- const ConstantIntDivisibility &div) {
- os << "ConstantIntDivisibility(udiv = " << div.udivVal
- << ", sdiv = " << div.sdivVal << ")";
- return os;
-}
-
-/// This lattice value represents the integer divisibility of an SSA value.
-class IntegerDivisibility {
-public:
- IntegerDivisibility(ConstantIntDivisibility value)
- : value(std::move(value)) {}
- explicit IntegerDivisibility(
- std::optional<ConstantIntDivisibility> value = std::nullopt)
- : value(std::move(value)) {}
- // Gets the minimum divisibility of 1 that is used to indicate that the value
- // cannot be analyzed further.
- static IntegerDivisibility getMinDivisibility() {
- return IntegerDivisibility(ConstantIntDivisibility(1, 1));
- }
-
- bool isUninitialized() const { return !value.has_value(); }
- const ConstantIntDivisibility &getValue() const {
- assert(!isUninitialized());
- return *value;
- }
-
- bool operator==(const IntegerDivisibility &rhs) const {
- return value == rhs.value;
- }
-
- static IntegerDivisibility join(const IntegerDivisibility &lhs,
- const IntegerDivisibility &rhs) {
- if (lhs.isUninitialized()) {
- return rhs;
- }
- if (rhs.isUninitialized()) {
- return lhs;
- }
- return IntegerDivisibility(lhs.getValue().getUnion(rhs.getValue()));
- }
-
- void print(raw_ostream &os) const { os << value; }
-
-private:
- std::optional<ConstantIntDivisibility> value;
-};
-
-inline raw_ostream &operator<<(raw_ostream &os,
- const IntegerDivisibility &div) {
- div.print(os);
- return os;
-}
-
-/// The type of the `setResultDivs` callback provided to ops implementing
-/// InferIntDivisibilityOpInterface. It should be called once for each integer
-/// result value and be passed the ConstantIntDivisibility corresponding to
-/// that value.
-using SetIntDivisibilityFn =
- llvm::function_ref<void(Value, const ConstantIntDivisibility &)>;
-
-} // end namespace mlir
-
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h.inc"
-
-#endif // MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE_H
diff --git a/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.td b/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.td
deleted file mode 100644
index c665475e0fd7f..0000000000000
--- a/mlir/include/mlir/Interfaces/InferIntDivisibilityOpInterface.td
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- InferIntDivisibilityOpInterface.td - Integer Divisibility -*- tablegen -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines the interface for divisibility analysis on scalar integers.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE
-#define MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE
-
-include "mlir/IR/OpBase.td"
-
-def InferIntDivisibilityOpInterface :
- OpInterface<"InferIntDivisibilityOpInterface"> {
- let description = [{
- Allows operations to participate in integer divisibility analysis.
- }];
- let cppNamespace = "::mlir";
-
- let methods = [
- InterfaceMethod<
- /*desc=*/[{
- Infer the divisibility of the results of this op given the
- divisibility of its arguments. For each result value, the method
- should call `setResultDivs` with that `Value` as an argument.
- }],
- /*retTy=*/"void",
- /*methodName=*/"inferResultDivisibility",
- /*args=*/(ins
- "::llvm::ArrayRef<::mlir::IntegerDivisibility>":$argDivs,
- "::mlir::SetIntDivisibilityFn":$setResultDivs)
- >
- ];
-}
-
-#endif // MLIR_INTERFACES_INFERINTDIVISIBILITYOPINTERFACE
diff --git a/mlir/lib/Analysis/CMakeLists.txt b/mlir/lib/Analysis/CMakeLists.txt
index 596ffaff428b5..db10ebcf2c311 100644
--- a/mlir/lib/Analysis/CMakeLists.txt
+++ b/mlir/lib/Analysis/CMakeLists.txt
@@ -13,7 +13,6 @@ set(LLVM_OPTIONAL_SOURCES
DataFlow/ConstantPropagationAnalysis.cpp
DataFlow/DeadCodeAnalysis.cpp
DataFlow/DenseAnalysis.cpp
- DataFlow/IntegerDivisibilityAnalysis.cpp
DataFlow/IntegerRangeAnalysis.cpp
DataFlow/LivenessAnalysis.cpp
DataFlow/SparseAnalysis.cpp
@@ -38,7 +37,6 @@ add_mlir_library(MLIRAnalysis
DataFlow/ConstantPropagationAnalysis.cpp
DataFlow/DeadCodeAnalysis.cpp
DataFlow/DenseAnalysis.cpp
- DataFlow/IntegerDivisibilityAnalysis.cpp
DataFlow/IntegerRangeAnalysis.cpp
DataFlow/LivenessAnalysis.cpp
DataFlow/SparseAnalysis.cpp
@@ -55,7 +53,6 @@ add_mlir_library(MLIRAnalysis
MLIRControlFlowInterfaces
MLIRDataLayoutInterfaces
MLIRFunctionInterfaces
- MLIRInferIntDivisibilityOpInterface
MLIRInferIntRangeInterface
MLIRInferStridedMetadataInterface
MLIRInferTypeOpInterface
diff --git a/mlir/lib/Analysis/DataFlow/IntegerDivisibilityAnalysis.cpp b/mlir/lib/Analysis/DataFlow/IntegerDivisibilityAnalysis.cpp
deleted file mode 100644
index ba10a8b5a0060..0000000000000
--- a/mlir/lib/Analysis/DataFlow/IntegerDivisibilityAnalysis.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-//===- IntegerDivisibilityAnalysis.cpp - Integer divisibility ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the dataflow analysis class for integer divisibility
-// inference. Operations participate in the analysis by implementing
-// `InferIntDivisibilityOpInterface`.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h"
-
-#include "mlir/Dialect/Utils/StaticValueUtils.h"
-#include "mlir/Interfaces/LoopLikeInterface.h"
-#include "llvm/Support/Debug.h"
-
-#define DEBUG_TYPE "int-divisibility-analysis"
-
-using llvm::dbgs;
-
-namespace mlir::dataflow {
-
-void IntegerDivisibilityAnalysis::setToEntryState(
- IntegerDivisibilityLattice *lattice) {
- propagateIfChanged(lattice,
- lattice->join(IntegerDivisibility::getMinDivisibility()));
-}
-
-LogicalResult IntegerDivisibilityAnalysis::visitOperation(
- Operation *op, ArrayRef<const IntegerDivisibilityLattice *> operands,
- ArrayRef<IntegerDivisibilityLattice *> results) {
- auto inferrable = dyn_cast<InferIntDivisibilityOpInterface>(op);
- if (!inferrable) {
- setAllToEntryStates(results);
- return success();
- }
-
- LLVM_DEBUG(dbgs() << "Inferring divisibility for " << *op << "\n");
- auto argDivs = llvm::map_to_vector(
- operands, [](const IntegerDivisibilityLattice *lattice) {
- return lattice->getValue();
- });
- auto joinCallback = [&](Value v, const IntegerDivisibility &newDiv) {
- auto result = dyn_cast<OpResult>(v);
- if (!result) {
- return;
- }
- assert(llvm::is_contained(op->getResults(), result));
-
- LLVM_DEBUG(dbgs() << "Inferred divisibility " << newDiv << "\n");
- IntegerDivisibilityLattice *lattice = results[result.getResultNumber()];
- IntegerDivisibility oldDiv = lattice->getValue();
-
- ChangeResult changed = lattice->join(newDiv);
-
- // Catch loop results with loop-variant divisibility and conservatively
- // set them to divisibility 1 (no information) so we don't ratchet
- // indefinitely (the dataflow analysis in MLIR doesn't attempt to work
- // out trip counts and often can't).
- bool isYieldedResult = llvm::any_of(v.getUsers(), [](Operation *op) {
- return op->hasTrait<OpTrait::IsTerminator>();
- });
- if (isYieldedResult && !oldDiv.isUninitialized() &&
- !(lattice->getValue() == oldDiv)) {
- LLVM_DEBUG(llvm::dbgs() << "Loop variant loop result detected\n");
- changed |= lattice->join(IntegerDivisibility::getMinDivisibility());
- }
- propagateIfChanged(lattice, changed);
- };
-
- inferrable.inferResultDivisibility(argDivs, joinCallback);
- return success();
-}
-
-void IntegerDivisibilityAnalysis::visitNonControlFlowArguments(
- Operation *op, const RegionSuccessor &successor, ValueRange successorInputs,
- ArrayRef<IntegerDivisibilityLattice *> argLattices) {
- // Get the constant divisibility, or query the lattice for Values.
- auto getDivFromOfr = [&](std::optional<OpFoldResult> ofr, Block *block,
- bool isUnsigned) -> uint64_t {
- if (ofr.has_value()) {
- if (auto constBound = getConstantIntValue(*ofr)) {
- return constBound.value();
- }
- auto value = cast<Value>(ofr.value());
- const IntegerDivisibilityLattice *lattice =
- getLatticeElementFor(getProgramPointBefore(block), value);
- if (lattice != nullptr && !lattice->getValue().isUninitialized()) {
- return isUnsigned ? lattice->getValue().getValue().udiv()
- : lattice->getValue().getValue().sdiv();
- }
- }
- return isUnsigned
- ? IntegerDivisibility::getMinDivisibility().getValue().udiv()
- : IntegerDivisibility::getMinDivisibility().getValue().sdiv();
- };
-
- // Infer bounds for loop arguments that have static bounds
- if (auto loop = dyn_cast<LoopLikeOpInterface>(op)) {
- std::optional<SmallVector<Value>> ivs = loop.getLoopInductionVars();
- std::optional<SmallVector<OpFoldResult>> lbs = loop.getLoopLowerBounds();
- std::optional<SmallVector<OpFoldResult>> steps = loop.getLoopSteps();
- if (!ivs || !lbs || !steps) {
- return SparseForwardDataFlowAnalysis::visitNonControlFlowArguments(
- op, successor, successorInputs, argLattices);
- }
- for (auto [iv, lb, step] : llvm::zip_equal(*ivs, *lbs, *steps)) {
- IntegerDivisibilityLattice *ivEntry = getLatticeElement(iv);
- Block *block = iv.getParentBlock();
- uint64_t stepUDiv = getDivFromOfr(step, block, /*unsigned=*/true);
- uint64_t stepSDiv = getDivFromOfr(step, block, /*unsigned=*/false);
- uint64_t lbUDiv = getDivFromOfr(lb, block, /*unsigned=*/true);
- uint64_t lbSDiv = getDivFromOfr(lb, block, /*unsigned=*/false);
- ConstantIntDivisibility lbDiv(lbUDiv, lbSDiv);
- ConstantIntDivisibility stepDiv(stepUDiv, stepSDiv);
-
- // Loop induction variables are computed as `lb + i * step`. The
- // divisibility for `i * step` is just the divisibility of `step`, so
- // the total divisibility is obtained by unioning the step divisibility
- // with the lower bound divisibility, which takes the GCD of the two.
- ConstantIntDivisibility ivDiv = stepDiv.getUnion(lbDiv);
- propagateIfChanged(ivEntry, ivEntry->join(ivDiv));
- }
- return;
- }
-
- return SparseForwardDataFlowAnalysis::visitNonControlFlowArguments(
- op, successor, successorInputs, argLattices);
-}
-
-} // namespace mlir::dataflow
diff --git a/mlir/lib/Dialect/Affine/IR/CMakeLists.txt b/mlir/lib/Dialect/Affine/IR/CMakeLists.txt
index 1caf2fa396797..566bc060e5d38 100644
--- a/mlir/lib/Dialect/Affine/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/Affine/IR/CMakeLists.txt
@@ -2,7 +2,6 @@ add_mlir_dialect_library(MLIRAffineDialect
AffineMemoryOpInterfaces.cpp
AffineOps.cpp
AffineValueMap.cpp
- InferIntDivisibilityOpInterfaceImpl.cpp
InferIntRangeInterfaceImpls.cpp
ValueBoundsOpInterfaceImpl.cpp
@@ -17,7 +16,6 @@ add_mlir_dialect_library(MLIRAffineDialect
MLIRArithDialect
MLIRDialectUtils
MLIRIR
- MLIRInferIntDivisibilityOpInterface
MLIRInferIntRangeInterface
MLIRInferTypeOpInterface
MLIRLoopLikeInterface
diff --git a/mlir/lib/Dialect/Affine/IR/InferIntDivisibilityOpInterfaceImpl.cpp b/mlir/lib/Dialect/Affine/IR/InferIntDivisibilityOpInterfaceImpl.cpp
deleted file mode 100644
index 451ec98ef3737..0000000000000
--- a/mlir/lib/Dialect/Affine/IR/InferIntDivisibilityOpInterfaceImpl.cpp
+++ /dev/null
@@ -1,312 +0,0 @@
-//===- InferIntDivisibilityOpInterfaceImpl.cpp ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Direct implementations of `InferIntDivisibilityOpInterface` for affine ops.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Dialect/Affine/IR/AffineOps.h"
-#include "mlir/IR/AffineExprVisitor.h"
-#include "mlir/IR/Matchers.h"
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h"
-
-#include <cstdlib>
-#include <numeric>
-
-using namespace mlir;
-using namespace mlir::affine;
-
-namespace {
-
-static ConstantIntDivisibility
-getDivisibilityOfOperand(Value v, IntegerDivisibility divisibility) {
- if (!divisibility.isUninitialized())
- return divisibility.getValue();
- APInt intVal;
- if (matchPattern(v, m_ConstantInt(&intVal))) {
- uint64_t udiv = intVal.getZExtValue();
- uint64_t sdiv = std::abs(intVal.getSExtValue());
- return ConstantIntDivisibility(udiv, sdiv);
- }
- return ConstantIntDivisibility(1, 1);
-}
-
-/// Visits affine expressions and recursively calculates the divisibilities of
-/// each subexpression. The final divisibilities of the expression and its
-/// subexpressions will be stored in the map for which a reference is provided
-/// to the AffineExprDivisibilityFinder (i.e., `divisibilityMap`).
-class AffineExprDivisibilityFinder
- : public AffineExprVisitor<AffineExprDivisibilityFinder,
- ConstantIntDivisibility> {
-public:
- using ExprDivisibilityMap =
- llvm::DenseMap<AffineExpr, ConstantIntDivisibility>;
- AffineExprDivisibilityFinder(ExprDivisibilityMap &divisibilityMap)
- : divisibilityMap(divisibilityMap) {}
-
- ConstantIntDivisibility visitConstantExpr(AffineConstantExpr expr) {
- // Constant expressions are trivial, since they are always static.
- uint64_t constValue = std::abs(expr.getValue());
- return ConstantIntDivisibility(constValue, constValue);
- }
-
- ConstantIntDivisibility visitDimExpr(AffineDimExpr expr) {
- // Dim expressions cannot be analyzed further, so return the divisibility
- // in `divisibilityMap` if it has been populated by the caller, or fallback
- // to the minimum divisibility.
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- return IntegerDivisibility::getMinDivisibility().getValue();
- }
-
- ConstantIntDivisibility visitSymbolExpr(AffineSymbolExpr expr) {
- // Symbol expressions cannot be analyzed further, so return the divisibility
- // in `divisibilityMap` if it has been populated by the caller, or fallback
- // to the minimum divisibility.
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- return IntegerDivisibility::getMinDivisibility().getValue();
- }
-
- /// Infer the divisibility of an addition or subtraction expression by
- /// recursively visiting the LHS and RHS, and then unioning the results.
- ConstantIntDivisibility visitAddExpr(AffineBinaryOpExpr expr) {
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- // The divisibility of an addition is the GCD of its constituents'
- // divisibilities.
- ConstantIntDivisibility lhsDiv = visit(expr.getLHS());
- ConstantIntDivisibility rhsDiv = visit(expr.getRHS());
- return lhsDiv.getUnion(rhsDiv);
- }
-
- /// Infer the divisibility of a multiplication expression by recursively
- /// visiting the LHS and RHS, and then multiplying the results.
- ConstantIntDivisibility visitMulExpr(AffineBinaryOpExpr expr) {
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- // The divisibility of a multiplication is the product of its constituents'
- // divisibilities.
- ConstantIntDivisibility lhsDiv = visit(expr.getLHS());
- ConstantIntDivisibility rhsDiv = visit(expr.getRHS());
- return ConstantIntDivisibility(lhsDiv.udiv() * rhsDiv.udiv(),
- lhsDiv.sdiv() * rhsDiv.sdiv());
- }
-
- ConstantIntDivisibility visitFloorDivExpr(AffineBinaryOpExpr expr) {
- return visitDivExpr(expr);
- }
-
- ConstantIntDivisibility visitCeilDivExpr(AffineBinaryOpExpr expr) {
- return visitDivExpr(expr);
- }
-
- /// Infer the divisibility of a mod expression. If the RHS is a constant,
- /// the result divisibility is gcd(lhs_divisibility, rhs_constant), since
- /// (d * k) mod c is always divisible by gcd(d, c). Furthermore, if the
- /// LHS divisibility is itself divisible by the constant (i.e., d % c == 0),
- /// then (d * k) mod c is always zero, represented as divisibility 0.
- ConstantIntDivisibility visitModExpr(AffineBinaryOpExpr expr) {
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- auto constRhs = dyn_cast<AffineConstantExpr>(expr.getRHS());
- if (!constRhs || constRhs.getValue() == 0)
- return ConstantIntDivisibility(1, 1);
- auto constValue = static_cast<uint64_t>(std::abs(constRhs.getValue()));
- ConstantIntDivisibility lhsDiv = visit(expr.getLHS());
- // If the LHS is always a multiple of constValue, x mod constValue is
- // always zero. Divisibility 0 is the lattice top ("divides everything").
- uint64_t modUDiv = (lhsDiv.udiv() % constValue == 0)
- ? 0
- : std::gcd(lhsDiv.udiv(), constValue);
- uint64_t modSDiv = (lhsDiv.sdiv() % constValue == 0)
- ? 0
- : std::gcd(lhsDiv.sdiv(), constValue);
- return ConstantIntDivisibility(modUDiv, modSDiv);
- }
-
-private:
- ConstantIntDivisibility visitInvalidExpr(AffineBinaryOpExpr expr) {
- return IntegerDivisibility::getMinDivisibility().getValue();
- }
-
- /// Helper shared by ceildiv and floordiv implementations. Returns the minimum
- /// divisibility as a fallback if the divisor is not a constant, because the
- /// divisibility cannot be inferred in this case. If the divisor is a
- /// constant, then this function recursively visits the dividend, and returns
- /// the quotient of the dividend's divisibility with the divisor.
- ConstantIntDivisibility visitDivExpr(AffineBinaryOpExpr expr) {
- if (divisibilityMap.contains(expr))
- return divisibilityMap[expr];
- auto constRhs = dyn_cast<AffineConstantExpr>(expr.getRHS());
- // Division by zero is undefined, so return the minimum divisibility.
- if (!constRhs || constRhs.getValue() == 0)
- return ConstantIntDivisibility(1, 1);
- auto constValue = static_cast<uint64_t>(std::abs(constRhs.getValue()));
- ConstantIntDivisibility lhsDiv = visit(expr.getLHS());
- uint64_t divUDiv =
- lhsDiv.udiv() % constValue == 0 ? lhsDiv.udiv() / constValue : 1;
- uint64_t divSDiv =
- lhsDiv.sdiv() % constValue == 0 ? lhsDiv.sdiv() / constValue : 1;
- return ConstantIntDivisibility(divUDiv, divSDiv);
- }
-
- ExprDivisibilityMap &divisibilityMap;
-};
-
-/// Returns the divisibilities of each AffineMap result based on the
-/// divisibilities of its dims and symbols. The `dimAndSymbolDivisibilities`
-/// should contain the divisibilities of the dims, followed by the
-/// divisibilities of the symbols in ascending order by their positions.
-SmallVector<ConstantIntDivisibility> getResultDivisibilities(
- AffineMap map,
- ArrayRef<ConstantIntDivisibility> dimAndSymbolDivisibilities) {
- // Seed the AffineExprDivisibilityFinder with the dimAndSymbolDivisibilities.
- llvm::DenseMap<AffineExpr, ConstantIntDivisibility> exprDivisibilityMap;
- SmallVector<AffineExpr> inputExprs;
- inputExprs.append(llvm::map_to_vector(
- llvm::seq<int64_t>(map.getNumDims()),
- [&](int64_t dim) { return getAffineDimExpr(dim, map.getContext()); }));
- inputExprs.append(llvm::map_to_vector(
- llvm::seq<int64_t>(map.getNumSymbols()),
- [&](int64_t sym) { return getAffineSymbolExpr(sym, map.getContext()); }));
- for (auto [expr, divisibility] :
- llvm::zip_equal(inputExprs, dimAndSymbolDivisibilities)) {
- exprDivisibilityMap[expr] = divisibility;
- }
- AffineExprDivisibilityFinder divisibilityFinder(exprDivisibilityMap);
-
- // Walk each result expression and compute their divisibilities.
- SmallVector<ConstantIntDivisibility> resultDivisibilities;
- for (AffineExpr resultExpr : map.getResults())
- resultDivisibilities.push_back(divisibilityFinder.visit(resultExpr));
- return resultDivisibilities;
-}
-
-/// Infer the result divisibility of an affine.min or affine.max operation
-/// based on its operand divisibilities. The result divisibility is the GCD
-/// of the divisibilities of each of the affine map results, because the result
-/// of the affine.min/max op could be any of these results.
-template <typename MinOrMaxTy>
-void inferAffineMinOrMaxResultDivisibility(
- MinOrMaxTy minOrMaxOp, ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- static_assert(llvm::is_one_of<MinOrMaxTy, AffineMinOp, AffineMaxOp>::value,
- "MinOrMaxTy must be AffineMinOp or AffineMaxOp");
- SmallVector<ConstantIntDivisibility> operandDivisibilities;
- for (auto [operand, divisibility] :
- llvm::zip(minOrMaxOp.getOperands(), argDivs)) {
- operandDivisibilities.push_back(
- getDivisibilityOfOperand(operand, divisibility));
- }
-
- SmallVector<ConstantIntDivisibility> resultDivisibilities =
- getResultDivisibilities(minOrMaxOp.getMap(), operandDivisibilities);
-
- ConstantIntDivisibility resultDivisibility =
- resultDivisibilities.pop_back_val();
- for (auto divisibility : resultDivisibilities)
- resultDivisibility = resultDivisibility.getUnion(divisibility);
- setResultDivs(minOrMaxOp.getResult(), resultDivisibility);
-}
-
-} // namespace
-
-void AffineApplyOp::inferResultDivisibility(
- ArrayRef<IntegerDivisibility> argDivs, SetIntDivisibilityFn setResultDivs) {
- SmallVector<ConstantIntDivisibility> operandDivisibilities;
- for (auto [operand, divisibility] : llvm::zip(getOperands(), argDivs)) {
- operandDivisibilities.push_back(
- getDivisibilityOfOperand(operand, divisibility));
- }
-
- SmallVector<ConstantIntDivisibility> resultDivisibilities =
- getResultDivisibilities(getMap(), operandDivisibilities);
- for (auto [result, divisibility] :
- llvm::zip_equal(getOperation()->getResults(), resultDivisibilities)) {
- setResultDivs(result, divisibility);
- }
-}
-
-void AffineMinOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferAffineMinOrMaxResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void AffineMaxOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferAffineMinOrMaxResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void AffineDelinearizeIndexOp::inferResultDivisibility(
- ArrayRef<IntegerDivisibility> argDivs, SetIntDivisibilityFn setResultDivs) {
- MLIRContext *ctx = getContext();
-
- // Operands are: [linear_index, dynamic_basis_values...]
- ConstantIntDivisibility linearDiv =
- getDivisibilityOfOperand(getLinearIndex(), argDivs[0]);
-
- ArrayRef<int64_t> staticBasis = getStaticBasis();
- int64_t numResults = getNumResults();
-
- // Build affine expressions for each result.
- // Dim 0 = linear index, symbols = dynamic basis values.
- AffineExpr linearExpr = getAffineDimExpr(0, ctx);
-
- // Collect operand divisibilities: [linear_index_div, dynamic_basis_divs...]
- SmallVector<ConstantIntDivisibility> operandDivs;
- operandDivs.push_back(linearDiv);
-
- // Map static/dynamic basis values to affine expressions.
- int64_t dynIdx = 0;
- SmallVector<AffineExpr> basisExprs;
- for (int64_t i = 0, e = static_cast<int64_t>(staticBasis.size()); i < e;
- ++i) {
- if (ShapedType::isDynamic(staticBasis[i])) {
- basisExprs.push_back(getAffineSymbolExpr(dynIdx, ctx));
- operandDivs.push_back(getDivisibilityOfOperand(getDynamicBasis()[dynIdx],
- argDivs[1 + dynIdx]));
- dynIdx++;
- } else {
- basisExprs.push_back(getAffineConstantExpr(staticBasis[i], ctx));
- }
- }
-
- // The computation basis skips the outer bound if present.
- bool hasOuter = hasOuterBound();
- int64_t basisStart = hasOuter ? 1 : 0;
-
- // Each result[i] can be expressed as an affine expression of the linear
- // index using the effective basis (after dropping outer bound if present).
- // Effective basis B[k] = basisExprs[basisStart + k], for k = 0..N-2.
- // Stride s[i] = product of B[i..N-2] = product of
- // basisExprs[basisStart+i .. end].
- //
- // result[0] = x floordiv s[0]
- // result[i>0] = (x floordiv s[i]) mod B[i-1]
- // For i=N-1, s[N-1]=1, so result[N-1] = x mod B[N-2].
-
- AffineExpr stride = getAffineConstantExpr(1, ctx);
- for (int64_t i = numResults - 1; i >= 0; --i) {
- AffineExpr resultExpr;
- if (i == 0) {
- resultExpr = linearExpr.floorDiv(stride);
- } else {
- resultExpr =
- (linearExpr.floorDiv(stride)) % basisExprs[basisStart + i - 1];
- }
-
- AffineMap resultMap = AffineMap::get(1, dynIdx, resultExpr, ctx);
- SmallVector<ConstantIntDivisibility> divs =
- getResultDivisibilities(resultMap, operandDivs);
- setResultDivs(getResult(i), divs[0]);
-
- if (i > 0)
- stride = basisExprs[basisStart + i - 1] * stride;
- }
-}
diff --git a/mlir/lib/Dialect/Arith/IR/CMakeLists.txt b/mlir/lib/Dialect/Arith/IR/CMakeLists.txt
index 3423e11a7d0f0..4beb99ccfdfba 100644
--- a/mlir/lib/Dialect/Arith/IR/CMakeLists.txt
+++ b/mlir/lib/Dialect/Arith/IR/CMakeLists.txt
@@ -1,7 +1,6 @@
set(LLVM_OPTIONAL_SOURCES
ArithOps.cpp
ArithDialect.cpp
- InferIntDivisibilityOpInterfaceImpl.cpp
InferIntRangeInterfaceImpls.cpp
ValueBoundsOpInterfaceImpl.cpp
)
@@ -13,7 +12,6 @@ add_public_tablegen_target(MLIRArithCanonicalizationIncGen)
add_mlir_dialect_library(MLIRArithDialect
ArithOps.cpp
ArithDialect.cpp
- InferIntDivisibilityOpInterfaceImpl.cpp
InferIntRangeInterfaceImpls.cpp
ADDITIONAL_HEADER_DIRS
@@ -26,7 +24,6 @@ add_mlir_dialect_library(MLIRArithDialect
LINK_LIBS PUBLIC
MLIRCastInterfaces
MLIRDialect
- MLIRInferIntDivisibilityOpInterface
MLIRInferIntRangeCommon
MLIRInferIntRangeInterface
MLIRInferTypeOpInterface
diff --git a/mlir/lib/Dialect/Arith/IR/InferIntDivisibilityOpInterfaceImpl.cpp b/mlir/lib/Dialect/Arith/IR/InferIntDivisibilityOpInterfaceImpl.cpp
deleted file mode 100644
index b23ee108ca4a3..0000000000000
--- a/mlir/lib/Dialect/Arith/IR/InferIntDivisibilityOpInterfaceImpl.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-//===- InferIntDivisibilityOpInterfaceImpl.cpp ----------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Direct implementations of `InferIntDivisibilityOpInterface` for arith ops.
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/IR/Matchers.h"
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h"
-
-#include <cstdlib>
-
-using namespace mlir;
-using namespace mlir::arith;
-
-static ConstantIntDivisibility
-getDivisibilityOfOperand(Value v, IntegerDivisibility divisibility) {
- if (!divisibility.isUninitialized())
- return divisibility.getValue();
- APInt intVal;
- if (matchPattern(v, m_ConstantInt(&intVal))) {
- uint64_t udiv = intVal.getZExtValue();
- uint64_t sdiv = std::abs(intVal.getSExtValue());
- return ConstantIntDivisibility(udiv, sdiv);
- }
- return ConstantIntDivisibility(1, 1);
-}
-
-// Result divisibility is the GCD (union) of the operand divisibilities.
-template <typename OpTy>
-static void
-inferBinaryGCDResultDivisibility(OpTy op, ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- auto lhsDiv = getDivisibilityOfOperand(op.getLhs(), argDivs[0]);
- auto rhsDiv = getDivisibilityOfOperand(op.getRhs(), argDivs[1]);
- setResultDivs(op.getResult(), lhsDiv.getUnion(rhsDiv));
-}
-
-void ConstantOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- auto constAttr = dyn_cast_if_present<IntegerAttr>(getValue());
- if (!constAttr)
- return;
- const APInt &value = constAttr.getValue();
- uint64_t udiv = value.getZExtValue();
- uint64_t sdiv = std::abs(value.getSExtValue());
- setResultDivs(getResult(), ConstantIntDivisibility(udiv, sdiv));
-}
-
-void AddIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void SubIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void MinUIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void MaxUIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void MinSIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void MaxSIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- inferBinaryGCDResultDivisibility(*this, argDivs, setResultDivs);
-}
-
-void MulIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- auto lhsDivisibility = getDivisibilityOfOperand(getLhs(), argDivs[0]);
- auto rhsDivisibility = getDivisibilityOfOperand(getRhs(), argDivs[1]);
-
- uint64_t mulUDiv = lhsDivisibility.udiv() * rhsDivisibility.udiv();
- uint64_t mulSDiv = lhsDivisibility.sdiv() * rhsDivisibility.sdiv();
-
- setResultDivs(getResult(), ConstantIntDivisibility(mulUDiv, mulSDiv));
-}
-
-void DivUIOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- APInt intVal;
- if (!matchPattern(getRhs(), m_ConstantInt(&intVal)))
- return;
-
- auto lhsDivisibility = getDivisibilityOfOperand(getLhs(), argDivs[0]);
-
- uint64_t divUDiv = lhsDivisibility.udiv() % intVal.getZExtValue() == 0
- ? lhsDivisibility.udiv() / intVal.getZExtValue()
- : 1;
- uint64_t divSDiv =
- lhsDivisibility.sdiv() % std::abs(intVal.getSExtValue()) == 0
- ? lhsDivisibility.sdiv() / std::abs(intVal.getSExtValue())
- : 1;
-
- setResultDivs(getResult(), ConstantIntDivisibility(divUDiv, divSDiv));
-}
-
-void SelectOp::inferResultDivisibility(ArrayRef<IntegerDivisibility> argDivs,
- SetIntDivisibilityFn setResultDivs) {
- // argDivs[0] is the condition (i1), argDivs[1] is true, argDivs[2] is false.
- auto trueDiv = getDivisibilityOfOperand(getTrueValue(), argDivs[1]);
- auto falseDiv = getDivisibilityOfOperand(getFalseValue(), argDivs[2]);
- setResultDivs(getResult(), trueDiv.getUnion(falseDiv));
-}
diff --git a/mlir/lib/Interfaces/CMakeLists.txt b/mlir/lib/Interfaces/CMakeLists.txt
index d20d290c45c01..41e890cb408ba 100644
--- a/mlir/lib/Interfaces/CMakeLists.txt
+++ b/mlir/lib/Interfaces/CMakeLists.txt
@@ -9,7 +9,6 @@ set(LLVM_OPTIONAL_SOURCES
FunctionImplementation.cpp
FunctionInterfaces.cpp
IndexingMapOpInterface.cpp
- InferIntDivisibilityOpInterface.cpp
InferIntRangeInterface.cpp
InferStridedMetadataInterface.cpp
InferTypeOpInterface.cpp
@@ -67,7 +66,6 @@ add_mlir_library(MLIRFunctionInterfaces
)
add_mlir_interface_library(IndexingMapOpInterface)
-add_mlir_interface_library(InferIntDivisibilityOpInterface)
add_mlir_interface_library(InferIntRangeInterface)
add_mlir_library(MLIRInferStridedMetadataInterface
diff --git a/mlir/lib/Interfaces/InferIntDivisibilityOpInterface.cpp b/mlir/lib/Interfaces/InferIntDivisibilityOpInterface.cpp
deleted file mode 100644
index acd7cd9530b5c..0000000000000
--- a/mlir/lib/Interfaces/InferIntDivisibilityOpInterface.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-//===- InferIntDivisibilityOpInterface.cpp - Integer divisibility inference ==//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.h"
-
-#include "mlir/Interfaces/InferIntDivisibilityOpInterface.cpp.inc"
diff --git a/mlir/test/Analysis/DataFlow/integer-divisibility.mlir b/mlir/test/Analysis/DataFlow/integer-divisibility.mlir
deleted file mode 100644
index 7f9466e949d4c..0000000000000
--- a/mlir/test/Analysis/DataFlow/integer-divisibility.mlir
+++ /dev/null
@@ -1,152 +0,0 @@
-// RUN: mlir-opt --split-input-file --test-int-divisibility-analysis --allow-unregistered-dialect %s | FileCheck %s
-
-// CHECK-LABEL: @constant
-func.func @constant() -> index {
- %0 = arith.constant 8 : index
- // CHECK: divisibility = "udiv = 8, sdiv = 8"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @muli_constant
-func.func @muli_constant(%arg0 : index) -> index {
- %c4 = arith.constant 4 : index
- %0 = arith.muli %arg0, %c4 : index
- // CHECK: divisibility = "udiv = 4, sdiv = 4"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @addi_gcd_of_muli_operands
-func.func @addi_gcd_of_muli_operands(%arg0 : index, %arg1 : index) -> index {
- %c8 = arith.constant 8 : index
- %c12 = arith.constant 12 : index
- %a = arith.muli %arg0, %c8 : index
- %b = arith.muli %arg1, %c12 : index
- %0 = arith.addi %a, %b : index
- // gcd(8, 12) = 4.
- // CHECK: divisibility = "udiv = 4, sdiv = 4"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @addi_same_divisibility
-func.func @addi_same_divisibility(%arg0 : index, %arg1 : index) -> index {
- %c16 = arith.constant 16 : index
- %a = arith.muli %arg0, %c16 : index
- %b = arith.muli %arg1, %c16 : index
- %0 = arith.addi %a, %b : index
- // CHECK: divisibility = "udiv = 16, sdiv = 16"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @affine_apply_mul
-func.func @affine_apply_mul(%arg0 : index) -> index {
- %c2 = arith.constant 2 : index
- %seed = arith.muli %arg0, %c2 : index
- %0 = affine.apply affine_map<(d0) -> (d0 * 16)>(%seed)
- // 2 * 16 = 32.
- // CHECK: divisibility = "udiv = 32, sdiv = 32"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @affine_apply_mul_then_floordiv
-func.func @affine_apply_mul_then_floordiv(%arg0 : index) -> index {
- %0 = affine.apply affine_map<(d0) -> (d0 * 16)>(%arg0)
- %1 = affine.apply affine_map<(d0) -> (d0 floordiv 4)>(%0)
- // 16 floordiv 4 = 4.
- // CHECK: divisibility = "udiv = 4, sdiv = 4"
- %2 = "test.int_divisibility"(%1) : (index) -> index
- return %2 : index
-}
-
-// -----
-
-// CHECK-LABEL: @affine_apply_mod_zero
-func.func @affine_apply_mod_zero(%arg0 : index) -> index {
- %0 = affine.apply affine_map<(d0) -> (d0 * 16)>(%arg0)
- %1 = affine.apply affine_map<(d0) -> (d0 mod 16)>(%0)
- // 16 % 16 == 0, so x mod 16 is always 0 -> divisibility 0 (lattice top).
- // CHECK: divisibility = "udiv = 0, sdiv = 0"
- %2 = "test.int_divisibility"(%1) : (index) -> index
- return %2 : index
-}
-
-// -----
-
-// CHECK-LABEL: @affine_apply_constant
-func.func @affine_apply_constant() -> index {
- %0 = affine.apply affine_map<() -> (64)>()
- // CHECK: divisibility = "udiv = 64, sdiv = 64"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
-
-// -----
-
-// CHECK-LABEL: @scf_for_constant_step
-func.func @scf_for_constant_step() {
- %c0 = arith.constant 0 : index
- %c64 = arith.constant 64 : index
- %c8 = arith.constant 8 : index
- scf.for %iv = %c0 to %c64 step %c8 {
- // CHECK: divisibility = "udiv = 8, sdiv = 8"
- %0 = "test.int_divisibility"(%iv) : (index) -> index
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: @scf_for_nontrivial_gcd
-func.func @scf_for_nontrivial_gcd() {
- %c12 = arith.constant 12 : index
- %c100 = arith.constant 100 : index
- %c18 = arith.constant 18 : index
- scf.for %iv = %c12 to %c100 step %c18 {
- // gcd(12, 18) = 6.
- // CHECK: divisibility = "udiv = 6, sdiv = 6"
- %0 = "test.int_divisibility"(%iv) : (index) -> index
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: @scf_for_coprime
-func.func @scf_for_coprime() {
- %c15 = arith.constant 15 : index
- %c100 = arith.constant 100 : index
- %c8 = arith.constant 8 : index
- scf.for %iv = %c15 to %c100 step %c8 {
- // gcd(15, 8) = 1.
- // CHECK: divisibility = "udiv = 1, sdiv = 1"
- %0 = "test.int_divisibility"(%iv) : (index) -> index
- }
- return
-}
-
-// -----
-
-// CHECK-LABEL: @affine_apply_mul_plus_const
-func.func @affine_apply_mul_plus_const(%arg0 : index) -> index {
- %c4 = arith.constant 4 : index
- %seed = arith.muli %arg0, %c4 : index
- %0 = affine.apply affine_map<(d0) -> (d0 * 8 + 16)>(%seed)
- // seed has udiv = 4, multiplied by 8 -> 32, then +16. gcd(32,16) = 16.
- // CHECK: divisibility = "udiv = 16, sdiv = 16"
- %1 = "test.int_divisibility"(%0) : (index) -> index
- return %1 : index
-}
diff --git a/mlir/test/lib/Analysis/CMakeLists.txt b/mlir/test/lib/Analysis/CMakeLists.txt
index d86af5017f24b..c37671ade37b3 100644
--- a/mlir/test/lib/Analysis/CMakeLists.txt
+++ b/mlir/test/lib/Analysis/CMakeLists.txt
@@ -15,7 +15,6 @@ add_mlir_library(MLIRTestAnalysis
DataFlow/TestDeadCodeAnalysis.cpp
DataFlow/TestDenseBackwardDataFlowAnalysis.cpp
DataFlow/TestDenseForwardDataFlowAnalysis.cpp
- DataFlow/TestIntegerDivisibilityAnalysis.cpp
DataFlow/TestLivenessAnalysis.cpp
DataFlow/TestSparseBackwardDataFlowAnalysis.cpp
DataFlow/TestStridedMetadataRangeAnalysis.cpp
@@ -28,7 +27,6 @@ add_mlir_library(MLIRTestAnalysis
mlir_target_link_libraries(MLIRTestAnalysis PUBLIC
MLIRAffineDialect
MLIRAnalysis
- MLIRArithDialect
MLIRFunctionInterfaces
MLIRMemRefDialect
MLIRPass
diff --git a/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp b/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
deleted file mode 100644
index 626cbc0fac7aa..0000000000000
--- a/mlir/test/lib/Analysis/DataFlow/TestIntegerDivisibilityAnalysis.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- TestIntegerDivisibilityAnalysis.cpp - Test int divisibility --------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Analysis/DataFlow/ConstantPropagationAnalysis.h"
-#include "mlir/Analysis/DataFlow/DeadCodeAnalysis.h"
-#include "mlir/Analysis/DataFlow/IntegerDivisibilityAnalysis.h"
-#include "mlir/Analysis/DataFlowFramework.h"
-#include "mlir/Dialect/Affine/IR/AffineOps.h"
-#include "mlir/Dialect/Arith/IR/Arith.h"
-#include "mlir/IR/BuiltinAttributes.h"
-#include "mlir/IR/DialectRegistry.h"
-#include "mlir/IR/Operation.h"
-#include "mlir/Pass/Pass.h"
-#include "mlir/Pass/PassRegistry.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace mlir;
-using namespace mlir::dataflow;
-
-namespace {
-struct TestIntegerDivisibilityAnalysisPass
- : public PassWrapper<TestIntegerDivisibilityAnalysisPass, OperationPass<>> {
- MLIR_DEFINE_EXPLICIT_INTERNAL_INLINE_TYPE_ID(
- TestIntegerDivisibilityAnalysisPass)
-
- StringRef getArgument() const override {
- return "test-int-divisibility-analysis";
- }
- StringRef getDescription() const override {
- return "Test integer divisibility analysis by annotating "
- "'test.int_divisibility' ops with the divisibility of their "
- "operand.";
- }
-
- void getDependentDialects(DialectRegistry ®istry) const override {
- registry.insert<arith::ArithDialect, affine::AffineDialect>();
- }
-
- void runOnOperation() override {
- Operation *rootOp = getOperation();
- MLIRContext *context = &getContext();
-
- // The pass is rooted on `test.int_divisibility` ops, which are expected
- // to have a single operand for which to annotate divisibility information.
- SmallVector<std::pair<Operation *, Value>> queryOps;
- rootOp->walk([&](Operation *op) {
- if (op->getName().getStringRef() == "test.int_divisibility" &&
- op->getNumOperands() == 1)
- queryOps.emplace_back(op, op->getOperand(0));
- });
-
- DataFlowSolver solver;
- // DeadCodeAnalysis is the base analysis that allows the solver to traverse
- // control flow. It is required by IntegerDivisibilityAnalysis.
- solver.load<DeadCodeAnalysis>();
- // SparseConstantPropagation allows the solver to call
- // visitNonControlFlowArguments and analyze arguments like loop induction
- // variables.
- solver.load<SparseConstantPropagation>();
- solver.load<IntegerDivisibilityAnalysis>();
- if (failed(solver.initializeAndRun(rootOp)))
- return signalPassFailure();
-
- for (auto &[op, value] : queryOps) {
- const auto *lattice =
- solver.lookupState<IntegerDivisibilityLattice>(value);
- if (!lattice || lattice->getValue().isUninitialized()) {
- op->setAttr("divisibility", StringAttr::get(context, "uninitialized"));
- continue;
- }
-
- // Format for the divisibility information is "udiv = X, sdiv = Y".
- const auto &div = lattice->getValue().getValue();
- std::string result;
- llvm::raw_string_ostream os(result);
- os << "udiv = " << div.udiv() << ", sdiv = " << div.sdiv();
- op->setAttr("divisibility", StringAttr::get(context, result));
- }
- }
-};
-} // end anonymous namespace
-
-namespace mlir::test {
-void registerTestIntegerDivisibilityAnalysisPass() {
- PassRegistration<TestIntegerDivisibilityAnalysisPass>();
-}
-} // end namespace mlir::test
diff --git a/mlir/tools/mlir-opt/mlir-opt.cpp b/mlir/tools/mlir-opt/mlir-opt.cpp
index 13c0934f34656..c4754b3a08551 100644
--- a/mlir/tools/mlir-opt/mlir-opt.cpp
+++ b/mlir/tools/mlir-opt/mlir-opt.cpp
@@ -104,7 +104,6 @@ void registerTestComposeSubView();
void registerTestMultiBuffering();
void registerTestIRVisitorsPass();
void registerTestGenericIRVisitorsPass();
-void registerTestIntegerDivisibilityAnalysisPass();
void registerTestInterfaces();
void registerTestIRVisitorsPass();
void registerTestLastModifiedPass();
@@ -254,7 +253,6 @@ static void registerTestPasses() {
mlir::test::registerTestMultiBuffering();
mlir::test::registerTestIRVisitorsPass();
mlir::test::registerTestGenericIRVisitorsPass();
- mlir::test::registerTestIntegerDivisibilityAnalysisPass();
mlir::test::registerTestInterfaces();
mlir::test::registerTestIrdlTestDialectConversionPass();
mlir::test::registerTestIRVisitorsPass();
More information about the Mlir-commits
mailing list