@@ -18,19 +18,147 @@ namespace mlir {
1818namespace torch {
1919namespace 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+
2329Value 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 << " \n Type 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 << " \n Unsigned 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
35163Type 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.
81214std::optional<int64_t > getTensorNumel (Value tensor);
@@ -89,23 +222,23 @@ Value getConstantWithGivenDtypeAndValue(PatternRewriter &rewriter, Location loc,
89222// return -1.
90223int64_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+
93236SmallVector<int64_t > makeShapeTorchCompatible (ArrayRef<int64_t > shape);
94237
95238ValueTensorType getTensorTypeFromShapeValues (ArrayRef<Value> shapes,
96239 Type dtype);
97240Value 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
0 commit comments