54 if (deallocOp.getMemrefs() == memrefs &&
55 deallocOp.getConditions() == conditions)
59 deallocOp.getMemrefsMutable().assign(memrefs);
60 deallocOp.getConditionsMutable().assign(conditions);
77 if (
auto bbArg = dyn_cast<BlockArgument>(v2))
78 if (bbArg.getOwner()->findAncestorOpInBlock(*op))
82 return areDistinct(v1Base, v2Base) || areDistinct(v2Base, v1Base);
90 for (
auto other : otherList) {
93 std::optional<bool> analysisResult =
94 analysis.isSameAllocation(other,
memref);
95 if (!analysisResult.has_value() || analysisResult ==
true)
136struct RemoveDeallocMemrefsContainedInRetained
138 RemoveDeallocMemrefsContainedInRetained(
MLIRContext *context,
148 LogicalResult handleOneMemref(DeallocOp deallocOp, Value memref, Value cond,
149 PatternRewriter &rewriter)
const {
155 bool atLeastOneMustAlias =
false;
156 for (Value retained : deallocOp.getRetained()) {
157 std::optional<bool> analysisResult =
158 analysis.isSameAllocation(retained, memref);
159 if (!analysisResult.has_value())
161 if (analysisResult ==
true)
162 atLeastOneMustAlias =
true;
164 if (!atLeastOneMustAlias)
170 for (
auto [i, retained] : llvm::enumerate(deallocOp.getRetained())) {
171 Value updatedCondition = deallocOp.getUpdatedConditions()[i];
172 std::optional<bool> analysisResult =
173 analysis.isSameAllocation(retained, memref);
174 if (analysisResult ==
true) {
175 auto disjunction = arith::OrIOp::create(rewriter, deallocOp.getLoc(),
176 updatedCondition, cond);
185 LogicalResult matchAndRewrite(DeallocOp deallocOp,
186 PatternRewriter &rewriter)
const override {
190 deallocOp.getRetained().end());
191 if (retained.size() != deallocOp.getRetained().size())
194 SmallVector<Value> newMemrefs, newConditions;
195 for (
auto [memref, cond] :
196 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
198 if (succeeded(handleOneMemref(deallocOp, memref, cond, rewriter)))
203 if (succeeded(handleOneMemref(deallocOp, extractOp.getOperand(), cond,
207 newMemrefs.push_back(memref);
208 newConditions.push_back(cond);
218 BufferOriginAnalysis &analysis;
237struct RemoveRetainedMemrefsGuaranteedToNotAlias
239 RemoveRetainedMemrefsGuaranteedToNotAlias(MLIRContext *context,
240 BufferOriginAnalysis &analysis)
241 : OpRewritePattern<DeallocOp>(context), analysis(analysis) {}
243 LogicalResult matchAndRewrite(DeallocOp deallocOp,
244 PatternRewriter &rewriter)
const override {
245 SmallVector<Value> newRetainedMemrefs, replacements;
247 for (
auto retainedMemref : deallocOp.getRetained()) {
250 newRetainedMemrefs.push_back(retainedMemref);
251 replacements.push_back({});
255 replacements.push_back(arith::ConstantOp::create(
256 rewriter, deallocOp.getLoc(), rewriter.
getBoolAttr(
false)));
259 if (newRetainedMemrefs.size() == deallocOp.getRetained().size())
263 DeallocOp::create(rewriter, deallocOp.getLoc(), deallocOp.getMemrefs(),
264 deallocOp.getConditions(), newRetainedMemrefs);
266 for (
auto &repl : replacements) {
268 repl = newDeallocOp.getUpdatedConditions()[i++];
271 rewriter.
replaceOp(deallocOp, replacements);
276 BufferOriginAnalysis &analysis;
306struct SplitDeallocWhenNotAliasingAnyOther
308 SplitDeallocWhenNotAliasingAnyOther(MLIRContext *context,
309 BufferOriginAnalysis &analysis)
310 : OpRewritePattern<DeallocOp>(context), analysis(analysis) {}
312 LogicalResult matchAndRewrite(DeallocOp deallocOp,
313 PatternRewriter &rewriter)
const override {
314 Location loc = deallocOp.getLoc();
315 if (deallocOp.getMemrefs().size() <= 1)
322 SmallVector<Value> knownRoots;
323 knownRoots.reserve(deallocOp.getMemrefs().size());
324 llvm::DenseMap<Value, int64_t> rootUseCount;
325 bool allRootsKnown =
true;
326 for (Value memref : deallocOp.getMemrefs()) {
329 allRootsKnown =
false;
332 knownRoots.push_back(root);
333 ++rootUseCount[root];
336 SmallVector<Value> remainingMemrefs, remainingConditions;
337 SmallVector<SmallVector<Value>> updatedConditions;
338 for (int64_t i = 0, e = deallocOp.getMemrefs().size(); i < e; ++i) {
339 Value memref = deallocOp.getMemrefs()[i];
340 Value cond = deallocOp.getConditions()[i];
343 mayAlias = rootUseCount.lookup(knownRoots[i]) > 1;
345 SmallVector<Value> otherMemrefs(deallocOp.getMemrefs());
346 otherMemrefs.erase(otherMemrefs.begin() + i);
352 remainingMemrefs.push_back(memref);
353 remainingConditions.push_back(cond);
358 auto newDeallocOp = DeallocOp::create(rewriter, loc, memref, cond,
359 deallocOp.getRetained());
360 updatedConditions.push_back(
361 llvm::to_vector(
ValueRange(newDeallocOp.getUpdatedConditions())));
365 if (remainingMemrefs.size() == deallocOp.getMemrefs().size())
370 DeallocOp::create(rewriter, loc, remainingMemrefs, remainingConditions,
371 deallocOp.getRetained());
374 SmallVector<Value> replacements =
375 llvm::to_vector(
ValueRange(newDeallocOp.getUpdatedConditions()));
376 for (
auto additionalConditions : updatedConditions) {
377 assert(replacements.size() == additionalConditions.size() &&
378 "expected same number of updated conditions");
379 for (int64_t i = 0, e = replacements.size(); i < e; ++i) {
380 replacements[i] = arith::OrIOp::create(rewriter, loc, replacements[i],
381 additionalConditions[i]);
384 rewriter.
replaceOp(deallocOp, replacements);
389 BufferOriginAnalysis &analysis;
415struct RetainedMemrefAliasingAlwaysDeallocatedMemref
417 RetainedMemrefAliasingAlwaysDeallocatedMemref(MLIRContext *context,
418 BufferOriginAnalysis &analysis)
419 : OpRewritePattern<DeallocOp>(context), analysis(analysis) {}
421 LogicalResult matchAndRewrite(DeallocOp deallocOp,
422 PatternRewriter &rewriter)
const override {
423 BitVector aliasesWithConstTrueMemref(deallocOp.getRetained().size());
424 SmallVector<Value> newMemrefs, newConditions;
425 for (
auto [memref, cond] :
426 llvm::zip(deallocOp.getMemrefs(), deallocOp.getConditions())) {
427 bool canDropMemref =
false;
428 for (
auto [i, retained, res] : llvm::enumerate(
429 deallocOp.getRetained(), deallocOp.getUpdatedConditions())) {
433 std::optional<bool> analysisResult =
434 analysis.isSameAllocation(retained, memref);
435 if (analysisResult ==
true) {
437 aliasesWithConstTrueMemref[i] =
true;
438 canDropMemref =
true;
449 std::optional<bool> extractAnalysisResult =
450 analysis.isSameAllocation(retained, extractOp.getOperand());
451 if (extractAnalysisResult ==
true) {
453 aliasesWithConstTrueMemref[i] =
true;
454 canDropMemref =
true;
458 if (!canDropMemref) {
459 newMemrefs.push_back(memref);
460 newConditions.push_back(cond);
463 if (!aliasesWithConstTrueMemref.all())
471 BufferOriginAnalysis &analysis;
485struct BufferDeallocationSimplificationPass
487 BufferDeallocationSimplificationPass> {
488 void runOnOperation()
override {
489 BufferOriginAnalysis
analysis(getOperation());
491 patterns.add<RemoveDeallocMemrefsContainedInRetained,
492 RemoveRetainedMemrefsGuaranteedToNotAlias,
493 SplitDeallocWhenNotAliasingAnyOther,
494 RetainedMemrefAliasingAlwaysDeallocatedMemref>(&
getContext(),
501 getOperation(), std::move(patterns),
502 GreedyRewriteConfig()
503 .setRegionSimplificationLevel(GreedySimplifyRegionLevel::Normal)
504 .enableFolding(
false))))
510 RewritePatternSet canonicalizationPatterns(&
getContext());
514 getOperation(), std::move(canonicalizationPatterns),
515 GreedyRewriteConfig().setRegionSimplificationLevel(
516 GreedySimplifyRegionLevel::Normal))))