CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
314 lines
11 KiB
C++
314 lines
11 KiB
C++
//===- MemorySlot.cpp - Memory Slot interface implementations for SCF -----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/Dialect/SCF/IR/SCF.h"
|
|
#include "mlir/Interfaces/Utils/MemorySlotUtils.h"
|
|
|
|
using namespace mlir;
|
|
using namespace mlir::scf;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ExecuteRegionOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool ExecuteRegionOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
return true;
|
|
}
|
|
|
|
void ExecuteRegionOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
regionsToProcess.insert({&getRegion(), reachingDef});
|
|
}
|
|
|
|
Value ExecuteRegionOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
if (!hasValueStores)
|
|
return reachingDef;
|
|
|
|
// Update the yield terminators to return the newly defined reaching
|
|
// definition.
|
|
for (Block &block : getRegion().getBlocks())
|
|
if (isa<YieldOp>(block.getTerminator()))
|
|
memoryslot::updateTerminator(&block, reachingDef, reachingAtBlockEnd);
|
|
|
|
SmallVector<Type> resultTypes(getResultTypes());
|
|
resultTypes.push_back(slot.elemType);
|
|
|
|
IRRewriter rewriter(builder);
|
|
Operation *newOp =
|
|
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
|
|
return newOp->getResults().back();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ForOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool ForOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
return true;
|
|
}
|
|
|
|
void ForOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
Region &bodyRegion = getBodyRegion();
|
|
if (!hasValueStores) {
|
|
regionsToProcess.insert({&bodyRegion, reachingDef});
|
|
return;
|
|
}
|
|
|
|
getInitArgsMutable().append(reachingDef);
|
|
bodyRegion.addArgument(slot.elemType, slot.ptr.getLoc());
|
|
regionsToProcess.insert({&bodyRegion, bodyRegion.getArguments().back()});
|
|
}
|
|
|
|
Value ForOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
if (!hasValueStores)
|
|
return reachingDef;
|
|
|
|
// Update the yield terminator to return the newly defined reaching
|
|
// definition.
|
|
memoryslot::updateTerminator(getBody(), reachingDef, reachingAtBlockEnd);
|
|
|
|
SmallVector<Type> resultTypes(getResultTypes());
|
|
resultTypes.push_back(slot.elemType);
|
|
|
|
IRRewriter rewriter(builder);
|
|
Operation *newOp =
|
|
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
|
|
return newOp->getResults().back();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ForallOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool ForallOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
// The ForallOp body can be ran in parallel, thus does not support sequenced
|
|
// value passing. Therefore only loads can be handled.
|
|
return !hasValueStores;
|
|
}
|
|
|
|
void ForallOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
assert(!hasValueStores && "ForallOp does not support stores");
|
|
regionsToProcess.insert({&getBodyRegion(), reachingDef});
|
|
}
|
|
|
|
Value ForallOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
assert(!hasValueStores && "ForallOp does not support stores");
|
|
return reachingDef;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// IfOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool IfOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
return true;
|
|
}
|
|
|
|
void IfOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
regionsToProcess.insert({&getThenRegion(), reachingDef});
|
|
regionsToProcess.insert({&getElseRegion(), reachingDef});
|
|
}
|
|
|
|
Value IfOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
if (!hasValueStores)
|
|
return reachingDef;
|
|
|
|
IRRewriter rewriter(builder);
|
|
|
|
// Update the yield terminators to return the newly defined reaching
|
|
// definition.
|
|
memoryslot::updateTerminator(&getThenRegion().back(), reachingDef,
|
|
reachingAtBlockEnd);
|
|
if (getElseRegion().hasOneBlock()) {
|
|
memoryslot::updateTerminator(&getElseRegion().back(), reachingDef,
|
|
reachingAtBlockEnd);
|
|
} else {
|
|
OpBuilder::InsertionGuard guard(rewriter);
|
|
rewriter.createBlock(&getElseRegion());
|
|
YieldOp::create(rewriter, getOperation()->getLoc(), reachingDef);
|
|
}
|
|
|
|
SmallVector<Type> resultTypes(getResultTypes());
|
|
resultTypes.push_back(slot.elemType);
|
|
|
|
Operation *newOp =
|
|
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
|
|
return newOp->getResults().back();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// IndexSwitchOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool IndexSwitchOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
return true;
|
|
}
|
|
|
|
void IndexSwitchOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
regionsToProcess.insert({&getDefaultRegion(), reachingDef});
|
|
for (Region &caseRegion : getCaseRegions())
|
|
regionsToProcess.insert({&caseRegion, reachingDef});
|
|
}
|
|
|
|
Value IndexSwitchOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
if (!hasValueStores)
|
|
return reachingDef;
|
|
|
|
IRRewriter rewriter(builder);
|
|
|
|
// Update the yield terminators to return the newly defined reaching
|
|
// definition.
|
|
memoryslot::updateTerminator(&getDefaultRegion().back(), reachingDef,
|
|
reachingAtBlockEnd);
|
|
for (Region &caseRegion : getCaseRegions())
|
|
memoryslot::updateTerminator(&caseRegion.back(), reachingDef,
|
|
reachingAtBlockEnd);
|
|
|
|
SmallVector<Type> resultTypes(getResultTypes());
|
|
resultTypes.push_back(slot.elemType);
|
|
|
|
Operation *newOp =
|
|
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
|
|
return newOp->getResults().back();
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ParallelOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool ParallelOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
// The ParallelOp body can be ran in parallel, thus does not support sequenced
|
|
// value passing. Therefore only loads can be handled.
|
|
return !hasValueStores;
|
|
}
|
|
|
|
void ParallelOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
assert(!hasValueStores && "ParallelOp does not support stores");
|
|
regionsToProcess.insert({&getBodyRegion(), reachingDef});
|
|
}
|
|
|
|
Value ParallelOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
assert(!hasValueStores && "ParallelOp does not support stores");
|
|
return reachingDef;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ReduceOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool ReduceOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
// The ReduceOp body can be ran in parallel, thus does not support sequenced
|
|
// value passing. Therefore only loads can be handled.
|
|
return !hasValueStores;
|
|
}
|
|
|
|
void ReduceOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
assert(!hasValueStores && "ReduceOp does not support stores");
|
|
for (Region &reduction : getReductions())
|
|
regionsToProcess.insert({&reduction, reachingDef});
|
|
}
|
|
|
|
Value ReduceOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
assert(!hasValueStores && "ReduceOp does not support stores");
|
|
return reachingDef;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// WhileOp
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
bool WhileOp::isRegionPromotable(const MemorySlot &slot, Region *region,
|
|
bool hasValueStores) {
|
|
return true;
|
|
}
|
|
|
|
void WhileOp::setupPromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
llvm::SmallMapVector<Region *, Value, 2> ®ionsToProcess) {
|
|
Region &beforeRegion = getBefore();
|
|
Region &afterRegion = getAfter();
|
|
if (!hasValueStores) {
|
|
regionsToProcess.insert({&beforeRegion, reachingDef});
|
|
regionsToProcess.insert({&afterRegion, reachingDef});
|
|
return;
|
|
}
|
|
|
|
getInitsMutable().append(reachingDef);
|
|
|
|
beforeRegion.addArgument(slot.elemType, slot.ptr.getLoc());
|
|
regionsToProcess.insert({&beforeRegion, beforeRegion.getArguments().back()});
|
|
|
|
afterRegion.addArgument(slot.elemType, slot.ptr.getLoc());
|
|
regionsToProcess.insert({&afterRegion, afterRegion.getArguments().back()});
|
|
}
|
|
|
|
Value WhileOp::finalizePromotion(
|
|
const MemorySlot &slot, Value reachingDef, bool hasValueStores,
|
|
const llvm::DenseMap<Block *, Value> &reachingAtBlockEnd,
|
|
OpBuilder &builder) {
|
|
if (!hasValueStores)
|
|
return reachingDef;
|
|
|
|
// Update the yield terminators to return the newly defined reaching
|
|
// definition.
|
|
memoryslot::updateTerminator(&getBefore().back(),
|
|
getBefore().getArguments().back(),
|
|
reachingAtBlockEnd);
|
|
memoryslot::updateTerminator(
|
|
&getAfter().back(), getAfter().getArguments().back(), reachingAtBlockEnd);
|
|
|
|
SmallVector<Type> resultTypes(getResultTypes());
|
|
resultTypes.push_back(slot.elemType);
|
|
|
|
IRRewriter rewriter(builder);
|
|
Operation *newOp =
|
|
memoryslot::replaceWithNewResults(rewriter, getOperation(), resultTypes);
|
|
return newOp->getResults().back();
|
|
}
|