xref: /llvm-project/mlir/lib/Dialect/Utils/StaticValueUtils.cpp (revision 092372da15e5165be14cdbb7cac3cf4976fd82d0)
10813700dSMatthias Springer //===- StaticValueUtils.cpp - Utilities for dealing with static values ----===//
20813700dSMatthias Springer //
30813700dSMatthias Springer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40813700dSMatthias Springer // See https://llvm.org/LICENSE.txt for license information.
50813700dSMatthias Springer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60813700dSMatthias Springer //
70813700dSMatthias Springer //===----------------------------------------------------------------------===//
80813700dSMatthias Springer 
90813700dSMatthias Springer #include "mlir/Dialect/Utils/StaticValueUtils.h"
100813700dSMatthias Springer #include "mlir/IR/Matchers.h"
110813700dSMatthias Springer #include "mlir/Support/LLVM.h"
120813700dSMatthias Springer #include "llvm/ADT/APSInt.h"
1398e838a8SMax191 #include "llvm/ADT/STLExtras.h"
140fb216fbSRamkumar Ramachandra #include "llvm/Support/MathExtras.h"
150813700dSMatthias Springer 
160813700dSMatthias Springer namespace mlir {
170813700dSMatthias Springer 
1896179dffSNicolas Vasilache bool isZeroIndex(OpFoldResult v) {
1996179dffSNicolas Vasilache   if (!v)
2096179dffSNicolas Vasilache     return false;
21da2c98b5SThomas Preud'homme   std::optional<int64_t> constint = getConstantIntValue(v);
22da2c98b5SThomas Preud'homme   if (!constint)
2396179dffSNicolas Vasilache     return false;
24da2c98b5SThomas Preud'homme   return *constint == 0;
2596179dffSNicolas Vasilache }
2696179dffSNicolas Vasilache 
27f4a478cdSChristopher Bate std::tuple<SmallVector<OpFoldResult>, SmallVector<OpFoldResult>,
28f4a478cdSChristopher Bate            SmallVector<OpFoldResult>>
29f4a478cdSChristopher Bate getOffsetsSizesAndStrides(ArrayRef<Range> ranges) {
30f4a478cdSChristopher Bate   SmallVector<OpFoldResult> offsets, sizes, strides;
31f4a478cdSChristopher Bate   offsets.reserve(ranges.size());
32f4a478cdSChristopher Bate   sizes.reserve(ranges.size());
33f4a478cdSChristopher Bate   strides.reserve(ranges.size());
34f4a478cdSChristopher Bate   for (const auto &[offset, size, stride] : ranges) {
35f4a478cdSChristopher Bate     offsets.push_back(offset);
36f4a478cdSChristopher Bate     sizes.push_back(size);
37f4a478cdSChristopher Bate     strides.push_back(stride);
38f4a478cdSChristopher Bate   }
39f4a478cdSChristopher Bate   return std::make_tuple(offsets, sizes, strides);
40f4a478cdSChristopher Bate }
41f4a478cdSChristopher Bate 
42a08b750cSNicolas Vasilache /// Helper function to dispatch an OpFoldResult into `staticVec` if:
43a08b750cSNicolas Vasilache ///   a) it is an IntegerAttr
44a08b750cSNicolas Vasilache /// In other cases, the OpFoldResult is dispached to the `dynamicVec`.
45a08b750cSNicolas Vasilache /// In such dynamic cases, a copy of the `sentinel` value is also pushed to
460813700dSMatthias Springer /// `staticVec`. This is useful to extract mixed static and dynamic entries that
470813700dSMatthias Springer /// come from an AttrSizedOperandSegments trait.
480813700dSMatthias Springer void dispatchIndexOpFoldResult(OpFoldResult ofr,
490813700dSMatthias Springer                                SmallVectorImpl<Value> &dynamicVec,
50ded75a28SAliia Khasanova                                SmallVectorImpl<int64_t> &staticVec) {
5168f58812STres Popp   auto v = llvm::dyn_cast_if_present<Value>(ofr);
52a08b750cSNicolas Vasilache   if (!v) {
53129f1001SKazu Hirata     APInt apInt = cast<IntegerAttr>(cast<Attribute>(ofr)).getValue();
54a08b750cSNicolas Vasilache     staticVec.push_back(apInt.getSExtValue());
550813700dSMatthias Springer     return;
560813700dSMatthias Springer   }
57a08b750cSNicolas Vasilache   dynamicVec.push_back(v);
58ded75a28SAliia Khasanova   staticVec.push_back(ShapedType::kDynamic);
590813700dSMatthias Springer }
600813700dSMatthias Springer 
61e9bafa35SAndrzej Warzyński std::pair<int64_t, OpFoldResult>
62e9bafa35SAndrzej Warzyński getSimplifiedOfrAndStaticSizePair(OpFoldResult tileSizeOfr, Builder &b) {
63e9bafa35SAndrzej Warzyński   int64_t tileSizeForShape =
64e9bafa35SAndrzej Warzyński       getConstantIntValue(tileSizeOfr).value_or(ShapedType::kDynamic);
65e9bafa35SAndrzej Warzyński 
66e9bafa35SAndrzej Warzyński   OpFoldResult tileSizeOfrSimplified =
67e9bafa35SAndrzej Warzyński       (tileSizeForShape != ShapedType::kDynamic)
68e9bafa35SAndrzej Warzyński           ? b.getIndexAttr(tileSizeForShape)
69e9bafa35SAndrzej Warzyński           : tileSizeOfr;
70e9bafa35SAndrzej Warzyński 
71e9bafa35SAndrzej Warzyński   return std::pair<int64_t, OpFoldResult>(tileSizeForShape,
72e9bafa35SAndrzej Warzyński                                           tileSizeOfrSimplified);
73e9bafa35SAndrzej Warzyński }
74e9bafa35SAndrzej Warzyński 
750813700dSMatthias Springer void dispatchIndexOpFoldResults(ArrayRef<OpFoldResult> ofrs,
760813700dSMatthias Springer                                 SmallVectorImpl<Value> &dynamicVec,
77ded75a28SAliia Khasanova                                 SmallVectorImpl<int64_t> &staticVec) {
780813700dSMatthias Springer   for (OpFoldResult ofr : ofrs)
79ded75a28SAliia Khasanova     dispatchIndexOpFoldResult(ofr, dynamicVec, staticVec);
800813700dSMatthias Springer }
810813700dSMatthias Springer 
82d624c1b5SMatthias Springer /// Given a value, try to extract a constant Attribute. If this fails, return
83d624c1b5SMatthias Springer /// the original value.
84d624c1b5SMatthias Springer OpFoldResult getAsOpFoldResult(Value val) {
85e99fae89SAlex Zinenko   if (!val)
86e99fae89SAlex Zinenko     return OpFoldResult();
87d624c1b5SMatthias Springer   Attribute attr;
88d624c1b5SMatthias Springer   if (matchPattern(val, m_Constant(&attr)))
89d624c1b5SMatthias Springer     return attr;
90d624c1b5SMatthias Springer   return val;
91d624c1b5SMatthias Springer }
92d624c1b5SMatthias Springer 
93d624c1b5SMatthias Springer /// Given an array of values, try to extract a constant Attribute from each
94d624c1b5SMatthias Springer /// value. If this fails, return the original value.
956f03a10eSMahesh Ravishankar SmallVector<OpFoldResult> getAsOpFoldResult(ValueRange values) {
96aafb52d7SNicolas Vasilache   return llvm::to_vector(
97d624c1b5SMatthias Springer       llvm::map_range(values, [](Value v) { return getAsOpFoldResult(v); }));
98d624c1b5SMatthias Springer }
99d624c1b5SMatthias Springer 
10018b92c66SNicolas Vasilache /// Convert `arrayAttr` to a vector of OpFoldResult.
10118b92c66SNicolas Vasilache SmallVector<OpFoldResult> getAsOpFoldResult(ArrayAttr arrayAttr) {
10218b92c66SNicolas Vasilache   SmallVector<OpFoldResult> res;
10318b92c66SNicolas Vasilache   res.reserve(arrayAttr.size());
10418b92c66SNicolas Vasilache   for (Attribute a : arrayAttr)
10518b92c66SNicolas Vasilache     res.push_back(a);
10618b92c66SNicolas Vasilache   return res;
10718b92c66SNicolas Vasilache }
10818b92c66SNicolas Vasilache 
1098afe6f7bSNicolas Vasilache OpFoldResult getAsIndexOpFoldResult(MLIRContext *ctx, int64_t val) {
1108afe6f7bSNicolas Vasilache   return IntegerAttr::get(IndexType::get(ctx), val);
1118afe6f7bSNicolas Vasilache }
1128afe6f7bSNicolas Vasilache 
1138afe6f7bSNicolas Vasilache SmallVector<OpFoldResult> getAsIndexOpFoldResult(MLIRContext *ctx,
1148afe6f7bSNicolas Vasilache                                                  ArrayRef<int64_t> values) {
115aafb52d7SNicolas Vasilache   return llvm::to_vector(llvm::map_range(
1168afe6f7bSNicolas Vasilache       values, [ctx](int64_t v) { return getAsIndexOpFoldResult(ctx, v); }));
1178afe6f7bSNicolas Vasilache }
1188afe6f7bSNicolas Vasilache 
1190813700dSMatthias Springer /// If ofr is a constant integer or an IntegerAttr, return the integer.
12022426110SRamkumar Ramachandra std::optional<int64_t> getConstantIntValue(OpFoldResult ofr) {
1210813700dSMatthias Springer   // Case 1: Check for Constant integer.
12268f58812STres Popp   if (auto val = llvm::dyn_cast_if_present<Value>(ofr)) {
1230813700dSMatthias Springer     APSInt intVal;
1240813700dSMatthias Springer     if (matchPattern(val, m_ConstantInt(&intVal)))
1250813700dSMatthias Springer       return intVal.getSExtValue();
1261a36588eSKazu Hirata     return std::nullopt;
1270813700dSMatthias Springer   }
1280813700dSMatthias Springer   // Case 2: Check for IntegerAttr.
12968f58812STres Popp   Attribute attr = llvm::dyn_cast_if_present<Attribute>(ofr);
1305550c821STres Popp   if (auto intAttr = dyn_cast_or_null<IntegerAttr>(attr))
1310813700dSMatthias Springer     return intAttr.getValue().getSExtValue();
1321a36588eSKazu Hirata   return std::nullopt;
1330813700dSMatthias Springer }
1340813700dSMatthias Springer 
13590ecfa2aSNicolas Vasilache std::optional<SmallVector<int64_t>>
13690ecfa2aSNicolas Vasilache getConstantIntValues(ArrayRef<OpFoldResult> ofrs) {
13790ecfa2aSNicolas Vasilache   bool failed = false;
13890ecfa2aSNicolas Vasilache   SmallVector<int64_t> res = llvm::map_to_vector(ofrs, [&](OpFoldResult ofr) {
13990ecfa2aSNicolas Vasilache     auto cv = getConstantIntValue(ofr);
14090ecfa2aSNicolas Vasilache     if (!cv.has_value())
14190ecfa2aSNicolas Vasilache       failed = true;
142b52885bcSKazu Hirata     return cv.value_or(0);
14390ecfa2aSNicolas Vasilache   });
14490ecfa2aSNicolas Vasilache   if (failed)
14590ecfa2aSNicolas Vasilache     return std::nullopt;
14690ecfa2aSNicolas Vasilache   return res;
14790ecfa2aSNicolas Vasilache }
14890ecfa2aSNicolas Vasilache 
149f3676c32SIvan Butygin bool isConstantIntValue(OpFoldResult ofr, int64_t value) {
150f3676c32SIvan Butygin   auto val = getConstantIntValue(ofr);
151f3676c32SIvan Butygin   return val && *val == value;
152f3676c32SIvan Butygin }
153f3676c32SIvan Butygin 
15498e838a8SMax191 bool areAllConstantIntValue(ArrayRef<OpFoldResult> ofrs, int64_t value) {
15598e838a8SMax191   return llvm::all_of(
15698e838a8SMax191       ofrs, [&](OpFoldResult ofr) { return isConstantIntValue(ofr, value); });
15798e838a8SMax191 }
15898e838a8SMax191 
15998e838a8SMax191 bool areConstantIntValues(ArrayRef<OpFoldResult> ofrs,
16098e838a8SMax191                           ArrayRef<int64_t> values) {
16198e838a8SMax191   if (ofrs.size() != values.size())
16298e838a8SMax191     return false;
16398e838a8SMax191   std::optional<SmallVector<int64_t>> constOfrs = getConstantIntValues(ofrs);
16498e838a8SMax191   return constOfrs && llvm::equal(constOfrs.value(), values);
16598e838a8SMax191 }
16698e838a8SMax191 
1670813700dSMatthias Springer /// Return true if ofr1 and ofr2 are the same integer constant attribute values
1680813700dSMatthias Springer /// or the same SSA value.
1690813700dSMatthias Springer /// Ignore integer bitwidth and type mismatch that come from the fact there is
1700813700dSMatthias Springer /// no IndexAttr and that IndexType has no bitwidth.
1710813700dSMatthias Springer bool isEqualConstantIntOrValue(OpFoldResult ofr1, OpFoldResult ofr2) {
1720813700dSMatthias Springer   auto cst1 = getConstantIntValue(ofr1), cst2 = getConstantIntValue(ofr2);
1730813700dSMatthias Springer   if (cst1 && cst2 && *cst1 == *cst2)
1740813700dSMatthias Springer     return true;
17568f58812STres Popp   auto v1 = llvm::dyn_cast_if_present<Value>(ofr1),
17668f58812STres Popp        v2 = llvm::dyn_cast_if_present<Value>(ofr2);
1770813700dSMatthias Springer   return v1 && v1 == v2;
1780813700dSMatthias Springer }
1794db3a649SLorenzo Chelini 
1804521b113SNicolas Vasilache bool isEqualConstantIntOrValueArray(ArrayRef<OpFoldResult> ofrs1,
1814521b113SNicolas Vasilache                                     ArrayRef<OpFoldResult> ofrs2) {
1824521b113SNicolas Vasilache   if (ofrs1.size() != ofrs2.size())
1834521b113SNicolas Vasilache     return false;
1844521b113SNicolas Vasilache   for (auto [ofr1, ofr2] : llvm::zip_equal(ofrs1, ofrs2))
1854521b113SNicolas Vasilache     if (!isEqualConstantIntOrValue(ofr1, ofr2))
1864521b113SNicolas Vasilache       return false;
1874521b113SNicolas Vasilache   return true;
1884521b113SNicolas Vasilache }
1894521b113SNicolas Vasilache 
190a9733b8aSLorenzo Chelini /// Return a vector of OpFoldResults with the same size a staticValues, but all
191a9733b8aSLorenzo Chelini /// elements for which ShapedType::isDynamic is true, will be replaced by
192a9733b8aSLorenzo Chelini /// dynamicValues.
193a9733b8aSLorenzo Chelini SmallVector<OpFoldResult> getMixedValues(ArrayRef<int64_t> staticValues,
194*092372daSMaheshRavishankar                                          ValueRange dynamicValues,
195*092372daSMaheshRavishankar                                          MLIRContext *context) {
196a9733b8aSLorenzo Chelini   SmallVector<OpFoldResult> res;
197a9733b8aSLorenzo Chelini   res.reserve(staticValues.size());
198a9733b8aSLorenzo Chelini   unsigned numDynamic = 0;
199a9733b8aSLorenzo Chelini   unsigned count = static_cast<unsigned>(staticValues.size());
200a9733b8aSLorenzo Chelini   for (unsigned idx = 0; idx < count; ++idx) {
201a9733b8aSLorenzo Chelini     int64_t value = staticValues[idx];
202a9733b8aSLorenzo Chelini     res.push_back(ShapedType::isDynamic(value)
203a9733b8aSLorenzo Chelini                       ? OpFoldResult{dynamicValues[numDynamic++]}
204*092372daSMaheshRavishankar                       : OpFoldResult{IntegerAttr::get(
205*092372daSMaheshRavishankar                             IntegerType::get(context, 64), staticValues[idx])});
206a9733b8aSLorenzo Chelini   }
207a9733b8aSLorenzo Chelini   return res;
208a9733b8aSLorenzo Chelini }
209*092372daSMaheshRavishankar SmallVector<OpFoldResult> getMixedValues(ArrayRef<int64_t> staticValues,
210*092372daSMaheshRavishankar                                          ValueRange dynamicValues, Builder &b) {
211*092372daSMaheshRavishankar   return getMixedValues(staticValues, dynamicValues, b.getContext());
212*092372daSMaheshRavishankar }
213a9733b8aSLorenzo Chelini 
214a9733b8aSLorenzo Chelini /// Decompose a vector of mixed static or dynamic values into the corresponding
215a9733b8aSLorenzo Chelini /// pair of arrays. This is the inverse function of `getMixedValues`.
21697069a86SGaurav Shukla std::pair<SmallVector<int64_t>, SmallVector<Value>>
21797069a86SGaurav Shukla decomposeMixedValues(const SmallVectorImpl<OpFoldResult> &mixedValues) {
218a9733b8aSLorenzo Chelini   SmallVector<int64_t> staticValues;
219a9733b8aSLorenzo Chelini   SmallVector<Value> dynamicValues;
220a9733b8aSLorenzo Chelini   for (const auto &it : mixedValues) {
221129f1001SKazu Hirata     if (auto attr = dyn_cast<Attribute>(it)) {
222129f1001SKazu Hirata       staticValues.push_back(cast<IntegerAttr>(attr).getInt());
223a9733b8aSLorenzo Chelini     } else {
224a9733b8aSLorenzo Chelini       staticValues.push_back(ShapedType::kDynamic);
225129f1001SKazu Hirata       dynamicValues.push_back(cast<Value>(it));
226a9733b8aSLorenzo Chelini     }
227a9733b8aSLorenzo Chelini   }
22897069a86SGaurav Shukla   return {staticValues, dynamicValues};
229a9733b8aSLorenzo Chelini }
230a9733b8aSLorenzo Chelini 
231aafb52d7SNicolas Vasilache /// Helper to sort `values` according to matching `keys`.
232aafb52d7SNicolas Vasilache template <typename K, typename V>
233aafb52d7SNicolas Vasilache static SmallVector<V>
234aafb52d7SNicolas Vasilache getValuesSortedByKeyImpl(ArrayRef<K> keys, ArrayRef<V> values,
235aafb52d7SNicolas Vasilache                          llvm::function_ref<bool(K, K)> compare) {
236aafb52d7SNicolas Vasilache   if (keys.empty())
237aafb52d7SNicolas Vasilache     return SmallVector<V>{values};
238aafb52d7SNicolas Vasilache   assert(keys.size() == values.size() && "unexpected mismatching sizes");
239aafb52d7SNicolas Vasilache   auto indices = llvm::to_vector(llvm::seq<int64_t>(0, values.size()));
240aafb52d7SNicolas Vasilache   std::sort(indices.begin(), indices.end(),
241aafb52d7SNicolas Vasilache             [&](int64_t i, int64_t j) { return compare(keys[i], keys[j]); });
242aafb52d7SNicolas Vasilache   SmallVector<V> res;
243aafb52d7SNicolas Vasilache   res.reserve(values.size());
244aafb52d7SNicolas Vasilache   for (int64_t i = 0, e = indices.size(); i < e; ++i)
245aafb52d7SNicolas Vasilache     res.push_back(values[indices[i]]);
246aafb52d7SNicolas Vasilache   return res;
247aafb52d7SNicolas Vasilache }
248aafb52d7SNicolas Vasilache 
249aafb52d7SNicolas Vasilache SmallVector<Value>
250aafb52d7SNicolas Vasilache getValuesSortedByKey(ArrayRef<Attribute> keys, ArrayRef<Value> values,
251aafb52d7SNicolas Vasilache                      llvm::function_ref<bool(Attribute, Attribute)> compare) {
252aafb52d7SNicolas Vasilache   return getValuesSortedByKeyImpl(keys, values, compare);
253aafb52d7SNicolas Vasilache }
254aafb52d7SNicolas Vasilache 
255aafb52d7SNicolas Vasilache SmallVector<OpFoldResult>
256aafb52d7SNicolas Vasilache getValuesSortedByKey(ArrayRef<Attribute> keys, ArrayRef<OpFoldResult> values,
257aafb52d7SNicolas Vasilache                      llvm::function_ref<bool(Attribute, Attribute)> compare) {
258aafb52d7SNicolas Vasilache   return getValuesSortedByKeyImpl(keys, values, compare);
259aafb52d7SNicolas Vasilache }
260aafb52d7SNicolas Vasilache 
261768615bbSNicolas Vasilache SmallVector<int64_t>
262768615bbSNicolas Vasilache getValuesSortedByKey(ArrayRef<Attribute> keys, ArrayRef<int64_t> values,
263768615bbSNicolas Vasilache                      llvm::function_ref<bool(Attribute, Attribute)> compare) {
264768615bbSNicolas Vasilache   return getValuesSortedByKeyImpl(keys, values, compare);
265768615bbSNicolas Vasilache }
266768615bbSNicolas Vasilache 
2673a8f161aSAlexander Belyaev /// Return the number of iterations for a loop with a lower bound `lb`, upper
2683a8f161aSAlexander Belyaev /// bound `ub` and step `step`.
2693a8f161aSAlexander Belyaev std::optional<int64_t> constantTripCount(OpFoldResult lb, OpFoldResult ub,
2703a8f161aSAlexander Belyaev                                          OpFoldResult step) {
2713a8f161aSAlexander Belyaev   if (lb == ub)
2723a8f161aSAlexander Belyaev     return 0;
2733a8f161aSAlexander Belyaev 
2743a8f161aSAlexander Belyaev   std::optional<int64_t> lbConstant = getConstantIntValue(lb);
2753a8f161aSAlexander Belyaev   if (!lbConstant)
2763a8f161aSAlexander Belyaev     return std::nullopt;
2773a8f161aSAlexander Belyaev   std::optional<int64_t> ubConstant = getConstantIntValue(ub);
2783a8f161aSAlexander Belyaev   if (!ubConstant)
2793a8f161aSAlexander Belyaev     return std::nullopt;
2803a8f161aSAlexander Belyaev   std::optional<int64_t> stepConstant = getConstantIntValue(step);
2813a8f161aSAlexander Belyaev   if (!stepConstant)
2823a8f161aSAlexander Belyaev     return std::nullopt;
2833a8f161aSAlexander Belyaev 
2840fb216fbSRamkumar Ramachandra   return llvm::divideCeilSigned(*ubConstant - *lbConstant, *stepConstant);
2853a8f161aSAlexander Belyaev }
2863a8f161aSAlexander Belyaev 
28768f0bc6fSRik Huijzer bool hasValidSizesOffsets(SmallVector<int64_t> sizesOrOffsets) {
28868f0bc6fSRik Huijzer   return llvm::none_of(sizesOrOffsets, [](int64_t value) {
28968f0bc6fSRik Huijzer     return !ShapedType::isDynamic(value) && value < 0;
29068f0bc6fSRik Huijzer   });
29168f0bc6fSRik Huijzer }
29268f0bc6fSRik Huijzer 
29368f0bc6fSRik Huijzer bool hasValidStrides(SmallVector<int64_t> strides) {
29468f0bc6fSRik Huijzer   return llvm::none_of(strides, [](int64_t value) {
29568f0bc6fSRik Huijzer     return !ShapedType::isDynamic(value) && value == 0;
29668f0bc6fSRik Huijzer   });
29768f0bc6fSRik Huijzer }
29868f0bc6fSRik Huijzer 
29968386a74SMatthias Springer LogicalResult foldDynamicIndexList(SmallVectorImpl<OpFoldResult> &ofrs,
30068f0bc6fSRik Huijzer                                    bool onlyNonNegative, bool onlyNonZero) {
301b2826c02SMatthias Springer   bool valuesChanged = false;
302b2826c02SMatthias Springer   for (OpFoldResult &ofr : ofrs) {
303129f1001SKazu Hirata     if (isa<Attribute>(ofr))
304b2826c02SMatthias Springer       continue;
305b2826c02SMatthias Springer     Attribute attr;
306129f1001SKazu Hirata     if (matchPattern(cast<Value>(ofr), m_Constant(&attr))) {
30768386a74SMatthias Springer       // Note: All ofrs have index type.
30868386a74SMatthias Springer       if (onlyNonNegative && *getConstantIntValue(attr) < 0)
30968386a74SMatthias Springer         continue;
31068f0bc6fSRik Huijzer       if (onlyNonZero && *getConstantIntValue(attr) == 0)
31168f0bc6fSRik Huijzer         continue;
312b2826c02SMatthias Springer       ofr = attr;
313b2826c02SMatthias Springer       valuesChanged = true;
314b2826c02SMatthias Springer     }
315b2826c02SMatthias Springer   }
316b2826c02SMatthias Springer   return success(valuesChanged);
317b2826c02SMatthias Springer }
318b2826c02SMatthias Springer 
31968f0bc6fSRik Huijzer LogicalResult
32068f0bc6fSRik Huijzer foldDynamicOffsetSizeList(SmallVectorImpl<OpFoldResult> &offsetsOrSizes) {
32168f0bc6fSRik Huijzer   return foldDynamicIndexList(offsetsOrSizes, /*onlyNonNegative=*/true,
32268f0bc6fSRik Huijzer                               /*onlyNonZero=*/false);
32368f0bc6fSRik Huijzer }
32468f0bc6fSRik Huijzer 
32568f0bc6fSRik Huijzer LogicalResult foldDynamicStrideList(SmallVectorImpl<OpFoldResult> &strides) {
32668f0bc6fSRik Huijzer   return foldDynamicIndexList(strides, /*onlyNonNegative=*/false,
32768f0bc6fSRik Huijzer                               /*onlyNonZero=*/true);
32868f0bc6fSRik Huijzer }
32968f0bc6fSRik Huijzer 
3300813700dSMatthias Springer } // namespace mlir
331