|
54 | 54 |
|
55 | 55 | #include "llvm/ADT/MapVector.h" |
56 | 56 | #include <cstddef> |
| 57 | +#include <cstdint> |
57 | 58 | #include <iterator> |
58 | 59 | #include <mlir/IR/BuiltinAttributes.h> |
59 | 60 | #include <mlir/IR/Value.h> |
@@ -16832,6 +16833,180 @@ struct DUSDUSToDUSPad |
16832 | 16833 | } |
16833 | 16834 | }; |
16834 | 16835 |
|
| 16836 | +struct DUSDUSSubsuming |
| 16837 | + : public ChceckOpRewritePattern<stablehlo::DynamicUpdateSliceOp, |
| 16838 | + DUSDUSSubsuming> { |
| 16839 | + using CheckedOpRewritePattern::CheckedOpRewritePattern; |
| 16840 | + |
| 16841 | + std::tuple<Value, SmallVector<int64_t>, SmallVector<int64_t>> |
| 16842 | + getPaddingAmount(Value value) { |
| 16843 | + if (auto pad = value.getDefiningOp<stablehlo::PadOp>()) { |
| 16844 | + auto [nested, nestedLow, nestedHigh] = getPaddingAmount(pad.getOperand()); |
| 16845 | + if (!nested) |
| 16846 | + return std::make_tuple(pad.getOperand(), |
| 16847 | + llvm::to_vector(pad.getEdgePaddingLow()), |
| 16848 | + llvm::to_vector(pad.getEdgePaddingHigh())); |
| 16849 | + |
| 16850 | + for (auto [i, v] : llvm::enumerate(pad.getEdgePaddingLow())) { |
| 16851 | + nestedLow[i] += v; |
| 16852 | + } |
| 16853 | + for (auto [i, v] : llvm::enumerate(pad.getEdgePaddingHigh())) { |
| 16854 | + nestedHigh[i] += v; |
| 16855 | + } |
| 16856 | + return std::make_tuple(nested, nestedLow, nestedHigh); |
| 16857 | + } |
| 16858 | + if (auto extend = value.getDefiningOp<enzymexla::ExtendOp>()) { |
| 16859 | + auto rank = |
| 16860 | + cast<RankedTensorType>(extend.getOperand().getType()).getRank(); |
| 16861 | + SmallVector<int64_t> low(rank, 0); |
| 16862 | + SmallVector<int64_t> high(rank, 0); |
| 16863 | + low[extend.getDimension()] = extend.getLow(); |
| 16864 | + high[extend.getDimension()] = extend.getHigh(); |
| 16865 | + |
| 16866 | + auto [nested, nestedLow, nestedHigh] = |
| 16867 | + getPaddingAmount(extend.getOperand()); |
| 16868 | + if (!nested) |
| 16869 | + return std::make_tuple(extend.getOperand(), low, high); |
| 16870 | + |
| 16871 | + for (auto [i, v] : llvm::enumerate(low)) { |
| 16872 | + nestedLow[i] += v; |
| 16873 | + } |
| 16874 | + for (auto [i, v] : llvm::enumerate(high)) { |
| 16875 | + nestedHigh[i] += v; |
| 16876 | + } |
| 16877 | + return std::make_tuple(nested, nestedLow, nestedHigh); |
| 16878 | + } |
| 16879 | + return std::make_tuple(Value(), SmallVector<int64_t>(), |
| 16880 | + SmallVector<int64_t>()); |
| 16881 | + } |
| 16882 | + |
| 16883 | + LogicalResult matchAndRewriteImpl(stablehlo::DynamicUpdateSliceOp dus, |
| 16884 | + PatternRewriter &rewriter) const { |
| 16885 | + auto dus2 = |
| 16886 | + dus.getOperand().getDefiningOp<stablehlo::DynamicUpdateSliceOp>(); |
| 16887 | + |
| 16888 | + if (!dus2) |
| 16889 | + return failure(); |
| 16890 | + |
| 16891 | + auto pad2 = dus2.getUpdate().getDefiningOp<stablehlo::PadOp>(); |
| 16892 | + if (!pad2) |
| 16893 | + return failure(); |
| 16894 | + |
| 16895 | + // TODO: potentially relax this |
| 16896 | + auto pad = dus.getUpdate().getDefiningOp<stablehlo::PadOp>(); |
| 16897 | + if (!pad) |
| 16898 | + return failure(); |
| 16899 | + |
| 16900 | + if (pad.getPaddingValue() != pad2.getPaddingValue()) |
| 16901 | + return failure(); |
| 16902 | + |
| 16903 | + if (!llvm::all_of(pad.getInteriorPadding(), |
| 16904 | + [](int64_t v) { return v == 0; })) |
| 16905 | + return failure(); |
| 16906 | + if (!llvm::all_of(pad2.getInteriorPadding(), |
| 16907 | + [](int64_t v) { return v == 0; })) |
| 16908 | + return failure(); |
| 16909 | + |
| 16910 | + // Only applies if we can analyze sizes. |
| 16911 | + SmallVector<int64_t> starts, extents, starts2, extents2; |
| 16912 | + auto extractDUSStartAndExtents = [](stablehlo::DynamicUpdateSliceOp dus, |
| 16913 | + SmallVectorImpl<int64_t> starts, |
| 16914 | + SmallVectorImpl<int64_t> extents) { |
| 16915 | + for (auto [s, e] : llvm::zip_equal( |
| 16916 | + dus.getStartIndices(), dus.getUpdate().getType().getShape())) { |
| 16917 | + DenseIntElementsAttr startattr; |
| 16918 | + if (!matchPattern(s, m_Constant(&startattr))) |
| 16919 | + return failure(); |
| 16920 | + int64_t ival = (*startattr.begin()).getSExtValue(); |
| 16921 | + starts.push_back(ival); |
| 16922 | + extents.push_back(e); |
| 16923 | + return success(); |
| 16924 | + } |
| 16925 | + }; |
| 16926 | + if (failed(dus, starts, extents)) |
| 16927 | + return failure(); |
| 16928 | + if (failed(dus2, starts2, extents2)) |
| 16929 | + return failure(); |
| 16930 | + |
| 16931 | + // The update of dus should be a padded version of dus2's update, |
| 16932 | + // and the interfering reads should not be accessing that padding. |
| 16933 | + auto [source, low, high] = getPaddingAmount(dus.getUpdate()); |
| 16934 | + auto [source2, low2, high2] = getPaddingAmount(dus2.getUpdate()); |
| 16935 | + if (source != source2 || !source || !source2) |
| 16936 | + return failure(); |
| 16937 | + |
| 16938 | + // // Find the non-subsumed part and check whether it comes from a pad. The |
| 16939 | + // // tuple is (dimension, start, extent) of the non-subsummed part. |
| 16940 | + // SmallVecor<std::tuple<unsigned, int64_t, int64_t>> nonSubsummed; |
| 16941 | + // for (auto [dim, s, e, s2, e2] : |
| 16942 | + // llvm::enumerate(starts, extents, starts2, extents2)) { |
| 16943 | + // if (s <= s2 && s + e >= s2 + e2) { |
| 16944 | + // // dus subsumes dus2 in this dimension, we are okay with this |
| 16945 | + // continue; |
| 16946 | + // } |
| 16947 | + |
| 16948 | + // if (s2 < s && pad2.getEdgePaddingLow()[dim] >= (s - s2)) { |
| 16949 | + // nonSubsummed.emplace_back(dim, s2, s - s2); |
| 16950 | + // continue; |
| 16951 | + // } |
| 16952 | + // if (s2 + e2 > s + e && |
| 16953 | + // pad2.getEdgePaddingHigh()[dim] >= (s2 + e2 - (s + e))) { |
| 16954 | + // nonSubsummed.emplace_back(dim, s + e, s2 + e2 - (s + e)); |
| 16955 | + // continue; |
| 16956 | + // } |
| 16957 | + |
| 16958 | + // return failure(); |
| 16959 | + // } |
| 16960 | + |
| 16961 | + // The pair is (start, extent). |
| 16962 | + SmallVector<std::pair<int64_t, int64_t>> forwardedToDus2; |
| 16963 | + for (auto [l2, h2, start, extent] : |
| 16964 | + llvm::zip_equal(low2, high2, start2, extents2)) |
| 16965 | + forwardedToDus2.emplace_back(start2 + low2, extent - low2 - high2); |
| 16966 | + } |
| 16967 | + |
| 16968 | + DominanceInfo domInfo; |
| 16969 | + for (Operation *user : dus2.getResult().getUsers()) { |
| 16970 | + if (user == dus) |
| 16971 | + continue; |
| 16972 | + auto slice = dyn_cast<stablehlo::SliceOp>(user); |
| 16973 | + if (!slice) |
| 16974 | + return failure(); |
| 16975 | + |
| 16976 | + if (!domInfo.dominates(user, dus)) |
| 16977 | + continue; |
| 16978 | + |
| 16979 | + // Find the if there is a part of the slice that is not reading from the |
| 16980 | + // forwarded or the padding. |
| 16981 | + for (auto &&[dim, sliceStart, sliceLimit, forwardedPair : |
| 16982 | + llvm::enumerate(slice.getStartIndices(), slice.getLimitInidices(), forwardedToDus)) { |
| 16983 | + auto [forwardedStart, forwardedExtent] = forwardedPair; |
| 16984 | + if (sliceStart < forwardedStart) { |
| 16985 | + if ((forwardedStart - sliceStart) <= pad2.getEdgePaddingLow()[dim]) |
| 16986 | + continue; |
| 16987 | + } |
| 16988 | + if (sliceLimit >= forwardedStart + forwardedExtent) { |
| 16989 | + if ((sliceLimit - (forwardedStart + forwardedExtent)) <= |
| 16990 | + pad2.getEdgePaddingHigh()[dim]) |
| 16991 | + continue; |
| 16992 | + } |
| 16993 | + return failure(); |
| 16994 | + } |
| 16995 | + |
| 16996 | + // Find if there is any user of the slice that cannot be moved. |
| 16997 | + for (Operation *sliceUser : slice.getResult().getUsers()) { |
| 16998 | + if (domInfo.dominates(sliceUser, dus)) |
| 16999 | + return failure(); |
| 17000 | + } |
| 17001 | + |
| 17002 | + // TODO: otherwise this slice should be fine to move after the dus, but we |
| 17003 | + // need to make sure the padding is sufficient. |
| 17004 | + } |
| 17005 | + |
| 17006 | + return success(); |
| 17007 | +} |
| 17008 | +} |
| 17009 | + |
16835 | 17010 | struct SinkDUS : public CheckedOpRewritePattern<stablehlo::WhileOp, SinkDUS> { |
16836 | 17011 | using CheckedOpRewritePattern::CheckedOpRewritePattern; |
16837 | 17012 |
|
|
0 commit comments