Skip to content

Commit 401dfc2

Browse files
authored
fix: break circular dependency to enable 'BUILD_SHARED_LIBS' (#4620)
This PR tries to close #3961. `Torch-MLIR` fails to build when using `-DBUILD_SHARED_LIBS=ON`. The root cause is a circular dependency between `TorchMLIRTorchUtils` and `TorchMLIRTorchDialect`, between `TorchMLIRConversionPasses` and `TorchMLIRTorchConversionPasses`, combined with many missing explicit link dependencies across conversion libraries. This commit does the following works: - Inline small utility functions used by `TorchMLIRTorchDialect` and move `squeezeTensor/unsqueezeTensor/sparsity` functions to `TorchOps.cpp` to make `TorchMLIRTorchDialect` not depend on `TorchMLIRTorchUtils`. - Relocate backend pipeline registration to conversion lib to break the circular dependency between `TorchMLIRConversionPasses` and `TorchMLIRTorchConversionPasses`. - Add many missing CMake `LINK_LIBS`. It's my first time to contribute to LLVM community and this project, any feedback is appreciated!
1 parent 874f3a4 commit 401dfc2

27 files changed

Lines changed: 558 additions & 554 deletions

File tree

include/torch-mlir/Dialect/Torch/IR/TorchOps.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,31 @@ inline int64_t getIntAttrAsSigned(IntegerAttr intAttr) {
370370
return intAttr.getValue().getSExtValue();
371371
}
372372

373+
/// Create a new SparseTensorEncodingAttr based on the provided `attr`, but with
374+
/// a new dense level inserted at `dim`.
375+
FailureOr<Attribute> getSparsityWithDenseLTAtDim(Attribute attr, Value dim);
376+
377+
/// Helper function to squeeze the input tensor at given dim.
378+
/// Return the squeezed tensor or failure.
379+
FailureOr<Value> squeezeTensor(PatternRewriter &rewriter, Operation *op,
380+
Location loc, int64_t dim, Value input);
381+
382+
/// Helper function to unsqueeze the input tensor at given dim.
383+
/// Return the unsqueezed tensor or failure.
384+
FailureOr<Value> unsqueezeTensor(PatternRewriter &rewriter, Operation *op,
385+
Value input, Value dim);
386+
387+
/// Helper function to get the list construct elements.
388+
/// The `elems` array is expected to be empty.
389+
/// Return true if the value `v` is defined by ListConstruct.
390+
bool getListConstructElements(Value v, SmallVectorImpl<Value> &elems);
391+
392+
/// Returns the index indicated by `v` for a list of given `length`.
393+
/// If the index is negative, it is adjusted to `length` + `v`.
394+
/// `None` is returned the index is not an integer in the range [0,`length).
395+
std::optional<int64_t> matchLegalConstantIndexIntoListOfSize(Value v,
396+
int64_t length);
397+
373398
} // namespace Torch
374399
} // namespace torch
375400
} // namespace mlir

include/torch-mlir/Dialect/Torch/Utils/SparsityUtils.h

Lines changed: 0 additions & 28 deletions
This file was deleted.

include/torch-mlir/Dialect/Torch/Utils/Utils.h

Lines changed: 156 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,147 @@ namespace mlir {
1818
namespace torch {
1919
namespace Torch {
2020

21-
int64_t toPositiveDim(int64_t dim, int64_t inputRank);
22-
bool isValidDim(int64_t dim, int64_t inputRank);
21+
inline int64_t toPositiveDim(int64_t dim, int64_t inputRank) {
22+
return dim >= 0 ? dim : dim + inputRank;
23+
}
24+
25+
inline bool isValidDim(int64_t dim, int64_t inputRank) {
26+
return dim >= 0 && dim < inputRank;
27+
}
28+
2329
Value toIntListConstruct(PatternRewriter &rewriter, Location loc,
2430
ArrayRef<int64_t> cstInput);
25-
bool getListConstructElements(Value v, SmallVectorImpl<Value> &elems);
26-
/// Returns the index indicated by `v` for a list of given `length`.
27-
/// If the index is negative, it is adjusted to `length` + `v`.
28-
/// `None` is returned the index is not an integer in the range [0,`length).
29-
std::optional<int64_t> matchLegalConstantIndexIntoListOfSize(Value v,
30-
int64_t length);
31-
torch_upstream::ScalarType getScalarTypeForType(Type type);
32-
FailureOr<Type> getTypeForScalarType(MLIRContext *context,
33-
torch_upstream::ScalarType dtypeInt);
31+
32+
inline torch_upstream::ScalarType getScalarTypeForType(Type type) {
33+
if (isa<Float32Type>(type))
34+
return torch_upstream::ScalarType::Float;
35+
if (isa<Float64Type>(type))
36+
return torch_upstream::ScalarType::Double;
37+
if (type.isSignedInteger(64))
38+
return torch_upstream::ScalarType::Long;
39+
if (type.isSignedInteger(32))
40+
return torch_upstream::ScalarType::Int;
41+
if (type.isSignedInteger(16))
42+
return torch_upstream::ScalarType::Short;
43+
if (type.isSignlessInteger(1))
44+
return torch_upstream::ScalarType::Bool;
45+
if (type.isBF16())
46+
return torch_upstream::ScalarType::BFloat16;
47+
if (type.isF16())
48+
return torch_upstream::ScalarType::Half;
49+
if (type.isUnsignedInteger(8))
50+
return torch_upstream::ScalarType::Byte;
51+
if (type.isSignedInteger(8))
52+
return torch_upstream::ScalarType::Char;
53+
if (isa<QUInt8Type>(type))
54+
return torch_upstream::ScalarType::QUInt8;
55+
if (isa<QInt8Type>(type))
56+
return torch_upstream::ScalarType::QInt8;
57+
if (isa<QInt16Type>(type))
58+
return torch_upstream::ScalarType::QInt16;
59+
if (isa<QInt32Type>(type))
60+
return torch_upstream::ScalarType::QInt32;
61+
if (isa<ComplexType>(type)) {
62+
mlir::Type complexElemType = cast<ComplexType>(type).getElementType();
63+
if (complexElemType.isF16())
64+
return torch_upstream::ScalarType::ComplexHalf;
65+
if (complexElemType.isF32())
66+
return torch_upstream::ScalarType::ComplexFloat;
67+
if (complexElemType.isF64())
68+
return torch_upstream::ScalarType::ComplexDouble;
69+
}
70+
if (isa<Float8E5M2Type>(type))
71+
return torch_upstream::ScalarType::Float8_e5m2;
72+
if (isa<Float8E4M3FNType>(type))
73+
return torch_upstream::ScalarType::Float8_e4m3fn;
74+
if (isa<Float8E5M2FNUZType>(type))
75+
return torch_upstream::ScalarType::Float8_e5m2fnuz;
76+
if (isa<Float8E4M3FNUZType>(type))
77+
return torch_upstream::ScalarType::Float8_e4m3fnuz;
78+
if (isa<Float8E8M0FNUType>(type))
79+
return torch_upstream::ScalarType::Float8_e8m0fnu;
80+
if (isa<Float4E2M1FNType>(type))
81+
return torch_upstream::ScalarType::Float4_e2m1fn_x2;
82+
std::string errorMsg = "Unhandled type in getScalarTypeForType: ";
83+
llvm::raw_string_ostream os(errorMsg);
84+
type.print(os);
85+
// os << "\nType ID: " << type.getTypeID();
86+
os << "\nType properties:";
87+
os << "\n Is integer: " << (type.isInteger() ? "yes" : "no");
88+
os << "\n Is float: "
89+
<< (type.isIntOrFloat() && !type.isInteger() ? "yes" : "no");
90+
os << "\n Is index: " << (type.isIndex() ? "yes" : "no");
91+
os << "\n Bit width: "
92+
<< (type.isIntOrFloat() ? std::to_string(type.getIntOrFloatBitWidth())
93+
: "N/A");
94+
os << "\n Is signless: " << (type.isSignlessInteger() ? "yes" : "no");
95+
os << "\n Is signed: " << (type.isSignedInteger() ? "yes" : "no");
96+
// special error message for unsigned integer
97+
if (type.isUnsignedInteger()) {
98+
os << "\n Is unsigned: yes";
99+
os << "\nUnsigned integer support is currently spotty. Please seeheck "
100+
"https://github.com/llvm/torch-mlir/issues/3720 "
101+
"for more details.";
102+
}
103+
llvm::report_fatal_error(llvm::StringRef(errorMsg));
104+
}
105+
106+
inline FailureOr<Type>
107+
getTypeForScalarType(MLIRContext *context,
108+
torch_upstream::ScalarType dtypeInt) {
109+
switch (dtypeInt) {
110+
case torch_upstream::ScalarType::Float:
111+
return Float32Type::get(context);
112+
case torch_upstream::ScalarType::Double:
113+
return Float64Type::get(context);
114+
case torch_upstream::ScalarType::Long:
115+
return IntegerType::get(context, 64, mlir::IntegerType::Signed);
116+
case torch_upstream::ScalarType::Int:
117+
return IntegerType::get(context, 32, mlir::IntegerType::Signed);
118+
case torch_upstream::ScalarType::Short:
119+
return IntegerType::get(context, 16, mlir::IntegerType::Signed);
120+
case torch_upstream::ScalarType::Bool:
121+
return IntegerType::get(context, 1);
122+
case torch_upstream::ScalarType::BFloat16:
123+
return mlir::BFloat16Type::get(context);
124+
case torch_upstream::ScalarType::Half:
125+
return mlir::Float16Type::get(context);
126+
case torch_upstream::ScalarType::Byte:
127+
return mlir::IntegerType::get(context, 8, mlir::IntegerType::Unsigned);
128+
case torch_upstream::ScalarType::Char:
129+
return mlir::IntegerType::get(context, 8, mlir::IntegerType::Signed);
130+
case torch_upstream::ScalarType::QUInt8:
131+
return QUInt8Type::get(context);
132+
case torch_upstream::ScalarType::QInt8:
133+
return QInt8Type::get(context);
134+
case torch_upstream::ScalarType::QInt16:
135+
return QInt16Type::get(context);
136+
case torch_upstream::ScalarType::QInt32:
137+
return QInt32Type::get(context);
138+
case torch_upstream::ScalarType::ComplexHalf:
139+
return mlir::ComplexType::get(Float16Type::get(context));
140+
case torch_upstream::ScalarType::ComplexFloat:
141+
return mlir::ComplexType::get(Float32Type::get(context));
142+
case torch_upstream::ScalarType::ComplexDouble:
143+
return mlir::ComplexType::get(Float64Type::get(context));
144+
case torch_upstream::ScalarType::Float8_e5m2:
145+
return Float8E5M2Type::get(context);
146+
case torch_upstream::ScalarType::Float8_e4m3fn:
147+
return Float8E4M3FNType::get(context);
148+
case torch_upstream::ScalarType::Float8_e5m2fnuz:
149+
return Float8E5M2FNUZType::get(context);
150+
case torch_upstream::ScalarType::Float8_e4m3fnuz:
151+
return Float8E4M3FNUZType::get(context);
152+
case torch_upstream::ScalarType::Float8_e8m0fnu:
153+
return Float8E8M0FNUType::get(context);
154+
case torch_upstream::ScalarType::Float4_e2m1fn_x2:
155+
return Float4E2M1FNType::get(context);
156+
case torch_upstream::ScalarType::Undefined:
157+
return failure();
158+
default:
159+
llvm::report_fatal_error("unhandled type for getTypeForScalarType");
160+
}
161+
}
34162

35163
Type getTypeForTorchType(
36164
MLIRContext *context, Type type,
@@ -75,7 +203,12 @@ bool isBuiltInType(Type type);
75203

76204
// Helper function to get rank of `Base tensor type`.
77205
// std::nullopt is returned if the tensorRank can't be determined.
78-
std::optional<unsigned> getTensorRank(Value tensor);
206+
inline std::optional<unsigned> getTensorRank(Value tensor) {
207+
BaseTensorType tensorType = cast<BaseTensorType>(tensor.getType());
208+
if (!tensorType.hasSizes())
209+
return std::nullopt;
210+
return tensorType.getSizes().size();
211+
}
79212

80213
// Helper function to get the number of elements in a tensor.
81214
std::optional<int64_t> getTensorNumel(Value tensor);
@@ -89,23 +222,23 @@ Value getConstantWithGivenDtypeAndValue(PatternRewriter &rewriter, Location loc,
89222
// return -1.
90223
int64_t getNumberOfElements(RankedTensorType inputType);
91224

92-
SmallVector<int64_t> makeShapeLLVMCompatible(ArrayRef<int64_t> shape);
225+
inline SmallVector<int64_t> makeShapeLLVMCompatible(ArrayRef<int64_t> shape) {
226+
SmallVector<int64_t> updatedShape(shape);
227+
int64_t kDynamic = ShapedType::kDynamic;
228+
for (unsigned i = 0; i < shape.size(); i++) {
229+
assert(shape[i] >= 0 || shape[i] == kUnknownSize);
230+
if (shape[i] == kUnknownSize)
231+
updatedShape[i] = kDynamic;
232+
}
233+
return updatedShape;
234+
}
235+
93236
SmallVector<int64_t> makeShapeTorchCompatible(ArrayRef<int64_t> shape);
94237

95238
ValueTensorType getTensorTypeFromShapeValues(ArrayRef<Value> shapes,
96239
Type dtype);
97240
Value getTensorDimSize(PatternRewriter &rewriter, Value tensor, int64_t dim);
98241

99-
// Helper function to squeeze the input tensor at given dim.
100-
// Return the squeezed tensor or failure.
101-
FailureOr<Value> squeezeTensor(PatternRewriter &rewriter, Operation *op,
102-
Location loc, int64_t dim, Value input);
103-
104-
// Helper function to unsqueeze the input tensor at given dim.
105-
// Return the unsqueezed tensor or failure.
106-
FailureOr<Value> unsqueezeTensor(PatternRewriter &rewriter, Operation *op,
107-
Value input, Value dim);
108-
109242
// In Dynamo import paths, we can assume that dynamic dimensions are strictly
110243
// quantities and are not ambiguous with '1' symbols that can be interpreted
111244
// to signal an expansion in various broadcasting scenarios. In the

lib/CAPI/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ add_mlir_public_c_api_library(TorchMLIRCAPI
1111
ENABLE_AGGREGATION
1212

1313
LINK_LIBS PUBLIC
14+
MLIRCAPIIR
1415
MLIRIR
1516
MLIRSupport
1617
TorchMLIRTorchDialect

lib/Conversion/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ set(linked_libs TorchMLIRTorchToArith
2020
TorchMLIRTorchToTensor
2121
TorchMLIRTorchToTMTensor
2222
TorchMLIRTorchConversionToMLProgram
23-
TorchMLIRConversionUtils)
23+
TorchMLIRConversionUtils
24+
TorchMLIRTorchConversionDialect)
2425
if(TORCH_MLIR_ENABLE_STABLEHLO)
2526
list(APPEND linked_libs TorchMLIRTorchToStablehlo)
2627
endif()

0 commit comments

Comments
 (0)