forked from OSchip/llvm-project
Refactor common code getting memref access in getMemRefRegion - NFC
- use getAccessMap() instead of repeating it - fold getMemRefRegion into MemRefRegion ctor (more natural, avoid heap allocation and unique_ptr where possible) - change extractForInductionVars - MutableArrayRef -> ArrayRef for the arguments. Since the method is just returning copies of 'Value *', the client can't mutate the pointers themselves; it's fine to mutate the 'Value''s themselves, but that doesn't mutate the pointers to those. - change the way extractForInductionVars returns (see b/123437690) PiperOrigin-RevId: 232359277
This commit is contained in:
parent
99d6ee02b9
commit
0f50414fa4
|
@ -201,10 +201,10 @@ bool isForInductionVar(const Value *val);
|
||||||
OpPointer<AffineForOp> getForInductionVarOwner(Value *val);
|
OpPointer<AffineForOp> getForInductionVarOwner(Value *val);
|
||||||
ConstOpPointer<AffineForOp> getForInductionVarOwner(const Value *val);
|
ConstOpPointer<AffineForOp> getForInductionVarOwner(const Value *val);
|
||||||
|
|
||||||
/// Extracts the induction variables from a list of AffineForOps and returns
|
/// Extracts the induction variables from a list of AffineForOps and places them
|
||||||
/// them.
|
/// in the output argument `ivs`.
|
||||||
SmallVector<Value *, 8>
|
void extractForInductionVars(ArrayRef<OpPointer<AffineForOp>> forInsts,
|
||||||
extractForInductionVars(MutableArrayRef<OpPointer<AffineForOp>> forInsts);
|
SmallVectorImpl<Value *> *ivs);
|
||||||
|
|
||||||
/// AffineBound represents a lower or upper bound in the for instruction.
|
/// AffineBound represents a lower or upper bound in the for instruction.
|
||||||
/// This class does not own the underlying operands. Instead, it refers
|
/// This class does not own the underlying operands. Instead, it refers
|
||||||
|
|
|
@ -117,8 +117,8 @@ bool getIndexSet(llvm::MutableArrayRef<OpPointer<AffineForOp>> forOps,
|
||||||
|
|
||||||
/// Encapsulates a memref load or store access information.
|
/// Encapsulates a memref load or store access information.
|
||||||
struct MemRefAccess {
|
struct MemRefAccess {
|
||||||
const Value *memref;
|
Value *memref;
|
||||||
const Instruction *opInst;
|
Instruction *opInst;
|
||||||
llvm::SmallVector<Value *, 4> indices;
|
llvm::SmallVector<Value *, 4> indices;
|
||||||
|
|
||||||
/// Constructs a MemRefAccess from a load or store operation instruction.
|
/// Constructs a MemRefAccess from a load or store operation instruction.
|
||||||
|
@ -126,6 +126,11 @@ struct MemRefAccess {
|
||||||
// return MemRefAccess, i.e., loadOp->getAccess(), dmaOp->getRead/WriteAccess.
|
// return MemRefAccess, i.e., loadOp->getAccess(), dmaOp->getRead/WriteAccess.
|
||||||
explicit MemRefAccess(Instruction *opInst);
|
explicit MemRefAccess(Instruction *opInst);
|
||||||
|
|
||||||
|
// Returns the rank of the memref associated with this access.
|
||||||
|
unsigned getRank() const;
|
||||||
|
// Returns true if this access is of a store op.
|
||||||
|
bool isStore() const;
|
||||||
|
|
||||||
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
|
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
|
||||||
// 'indices'.
|
// 'indices'.
|
||||||
void getAccessMap(AffineValueMap *accessMap) const;
|
void getAccessMap(AffineValueMap *accessMap) const;
|
||||||
|
|
|
@ -76,8 +76,30 @@ unsigned getNestingDepth(const Instruction &stmt);
|
||||||
// The last field is a 2-d FlatAffineConstraints symbolic in %i.
|
// The last field is a 2-d FlatAffineConstraints symbolic in %i.
|
||||||
//
|
//
|
||||||
struct MemRefRegion {
|
struct MemRefRegion {
|
||||||
MemRefRegion(Value *memref, Location loc, bool write)
|
explicit MemRefRegion(Location loc) : loc(loc) {}
|
||||||
: memref(memref), write(write), loc(loc) {}
|
|
||||||
|
/// Computes the memory region accessed by this memref with the region
|
||||||
|
/// represented as constraints symbolic/parameteric in 'loopDepth' loops
|
||||||
|
/// surrounding opInst. Returns false if this fails due to yet unimplemented
|
||||||
|
/// cases. The computed region's 'cst' field has exactly as many dimensional
|
||||||
|
/// identifiers as the rank of the memref, and *potentially* additional
|
||||||
|
/// symbolic identifiers which could include any of the loop IVs surrounding
|
||||||
|
/// opInst up until 'loopDepth' and another additional Function symbols
|
||||||
|
/// involved with the access (for eg., those appear in affine_apply's, loop
|
||||||
|
/// bounds, etc.).
|
||||||
|
/// For example, the memref region for this operation at loopDepth = 1 will
|
||||||
|
/// be:
|
||||||
|
///
|
||||||
|
/// for %i = 0 to 32 {
|
||||||
|
/// for %ii = %i to (d0) -> (d0 + 8) (%i) {
|
||||||
|
/// load %A[%ii]
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// {memref = %A, write = false, {%i <= m0 <= %i + 7} }
|
||||||
|
/// The last field is a 2-d FlatAffineConstraints symbolic in %i.
|
||||||
|
///
|
||||||
|
bool compute(Instruction *inst, unsigned loopDepth);
|
||||||
|
|
||||||
FlatAffineConstraints *getConstraints() { return &cst; }
|
FlatAffineConstraints *getConstraints() { return &cst; }
|
||||||
const FlatAffineConstraints *getConstraints() const { return &cst; }
|
const FlatAffineConstraints *getConstraints() const { return &cst; }
|
||||||
|
@ -132,28 +154,6 @@ struct MemRefRegion {
|
||||||
FlatAffineConstraints cst;
|
FlatAffineConstraints cst;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Computes the memory region accessed by this memref with the region
|
|
||||||
/// represented as constraints symbolic/parameteric in 'loopDepth' loops
|
|
||||||
/// surrounding opInst. Returns nullptr if this fails due to yet unimplemented
|
|
||||||
/// cases. The computed region's 'cst' field has exactly as many dimensional
|
|
||||||
/// identifiers as the rank of the memref, and *potentially* additional symbolic
|
|
||||||
/// identifiers which could include any of the loop IVs surrounding opInst up
|
|
||||||
/// until 'loopDepth' and another additional Function symbols involved with
|
|
||||||
/// the access (for eg., those appear in affine_apply's, loop bounds, etc.).
|
|
||||||
/// For example, the memref region for this operation at loopDepth = 1 will be:
|
|
||||||
///
|
|
||||||
/// for %i = 0 to 32 {
|
|
||||||
/// for %ii = %i to (d0) -> (d0 + 8) (%i) {
|
|
||||||
/// load %A[%ii]
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// {memref = %A, write = false, {%i <= m0 <= %i + 7} }
|
|
||||||
/// The last field is a 2-d FlatAffineConstraints symbolic in %i.
|
|
||||||
///
|
|
||||||
std::unique_ptr<MemRefRegion> getMemRefRegion(Instruction *opInst,
|
|
||||||
unsigned loopDepth);
|
|
||||||
|
|
||||||
/// Returns the size of memref data in bytes if it's statically shaped, None
|
/// Returns the size of memref data in bytes if it's statically shaped, None
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
Optional<uint64_t> getMemRefSizeInBytes(MemRefType memRefType);
|
Optional<uint64_t> getMemRefSizeInBytes(MemRefType memRefType);
|
||||||
|
|
|
@ -462,12 +462,11 @@ ConstOpPointer<AffineForOp> mlir::getForInductionVarOwner(const Value *val) {
|
||||||
|
|
||||||
/// Extracts the induction variables from a list of AffineForOps and returns
|
/// Extracts the induction variables from a list of AffineForOps and returns
|
||||||
/// them.
|
/// them.
|
||||||
SmallVector<Value *, 8> mlir::extractForInductionVars(
|
void mlir::extractForInductionVars(ArrayRef<OpPointer<AffineForOp>> forInsts,
|
||||||
MutableArrayRef<OpPointer<AffineForOp>> forInsts) {
|
SmallVectorImpl<Value *> *ivs) {
|
||||||
SmallVector<Value *, 8> results;
|
ivs->reserve(forInsts.size());
|
||||||
for (auto forInst : forInsts)
|
for (auto forInst : forInsts)
|
||||||
results.push_back(forInst->getInductionVar());
|
ivs->push_back(forInst->getInductionVar());
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -557,7 +557,8 @@ void mlir::getReachableAffineApplyOps(
|
||||||
// setExprStride(ArrayRef<int64_t> expr, int64_t stride)
|
// setExprStride(ArrayRef<int64_t> expr, int64_t stride)
|
||||||
bool mlir::getIndexSet(MutableArrayRef<OpPointer<AffineForOp>> forOps,
|
bool mlir::getIndexSet(MutableArrayRef<OpPointer<AffineForOp>> forOps,
|
||||||
FlatAffineConstraints *domain) {
|
FlatAffineConstraints *domain) {
|
||||||
auto indices = extractForInductionVars(forOps);
|
SmallVector<Value *, 4> indices;
|
||||||
|
extractForInductionVars(forOps, &indices);
|
||||||
// Reset while associated Values in 'indices' to the domain.
|
// Reset while associated Values in 'indices' to the domain.
|
||||||
domain->reset(forOps.size(), /*numSymbols=*/0, /*numLocals=*/0, indices);
|
domain->reset(forOps.size(), /*numSymbols=*/0, /*numLocals=*/0, indices);
|
||||||
for (auto forOp : forOps) {
|
for (auto forOp : forOps) {
|
||||||
|
|
|
@ -122,55 +122,36 @@ bool MemRefRegion::unionBoundingBox(const MemRefRegion &other) {
|
||||||
//
|
//
|
||||||
// TODO(bondhugula): extend this to any other memref dereferencing ops
|
// TODO(bondhugula): extend this to any other memref dereferencing ops
|
||||||
// (dma_start, dma_wait).
|
// (dma_start, dma_wait).
|
||||||
std::unique_ptr<MemRefRegion> mlir::getMemRefRegion(Instruction *opInst,
|
bool MemRefRegion::compute(Instruction *inst, unsigned loopDepth) {
|
||||||
unsigned loopDepth) {
|
assert((inst->isa<LoadOp>() || inst->isa<StoreOp>()) &&
|
||||||
unsigned rank;
|
"load/store op expected");
|
||||||
std::unique_ptr<MemRefRegion> region;
|
|
||||||
SmallVector<Value *, 4> indices;
|
MemRefAccess access(inst);
|
||||||
if (auto loadOp = opInst->dyn_cast<LoadOp>()) {
|
memref = access.memref;
|
||||||
rank = loadOp->getMemRefType().getRank();
|
write = access.isStore();
|
||||||
indices.reserve(rank);
|
|
||||||
indices.append(loadOp->getIndices().begin(), loadOp->getIndices().end());
|
unsigned rank = access.getRank();
|
||||||
region = std::make_unique<MemRefRegion>(loadOp->getMemRef(),
|
|
||||||
loadOp->getLoc(), false);
|
if (rank == 0) {
|
||||||
} else if (auto storeOp = opInst->dyn_cast<StoreOp>()) {
|
SmallVector<OpPointer<AffineForOp>, 4> ivs;
|
||||||
rank = storeOp->getMemRefType().getRank();
|
getLoopIVs(*inst, &ivs);
|
||||||
indices.reserve(rank);
|
SmallVector<Value *, 8> regionSymbols;
|
||||||
indices.append(storeOp->getIndices().begin(), storeOp->getIndices().end());
|
extractForInductionVars(ivs, ®ionSymbols);
|
||||||
region = std::make_unique<MemRefRegion>(storeOp->getMemRef(),
|
// A rank 0 memref has a 0-d region.
|
||||||
storeOp->getLoc(), true);
|
cst.reset(rank, loopDepth, 0, regionSymbols);
|
||||||
} else {
|
return true;
|
||||||
assert(false && "expected load or store op");
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the constraints for this region.
|
// Build the constraints for this region.
|
||||||
FlatAffineConstraints *regionCst = region->getConstraints();
|
AffineValueMap accessValueMap;
|
||||||
|
access.getAccessMap(&accessValueMap);
|
||||||
if (rank == 0) {
|
|
||||||
// A rank 0 memref has a 0-d region.
|
|
||||||
SmallVector<OpPointer<AffineForOp>, 4> ivs;
|
|
||||||
getLoopIVs(*opInst, &ivs);
|
|
||||||
|
|
||||||
SmallVector<Value *, 8> regionSymbols = extractForInductionVars(ivs);
|
|
||||||
regionCst->reset(0, loopDepth, 0, regionSymbols);
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
FuncBuilder b(opInst);
|
|
||||||
auto idMap = b.getMultiDimIdentityMap(rank);
|
|
||||||
// Initialize 'accessValueMap' and compose with reachable AffineApplyOps.
|
|
||||||
fullyComposeAffineMapAndOperands(&idMap, &indices);
|
|
||||||
// Remove any duplicates.
|
|
||||||
canonicalizeMapAndOperands(&idMap, &indices);
|
|
||||||
AffineValueMap accessValueMap(idMap, indices);
|
|
||||||
AffineMap accessMap = accessValueMap.getAffineMap();
|
AffineMap accessMap = accessValueMap.getAffineMap();
|
||||||
|
|
||||||
// We'll first associate the dims and symbols of the access map to the dims
|
// We'll first associate the dims and symbols of the access map to the dims
|
||||||
// and symbols resp. of regionCst. This will change below once regionCst is
|
// and symbols resp. of cst. This will change below once cst is
|
||||||
// fully constructed out.
|
// fully constructed out.
|
||||||
regionCst->reset(accessMap.getNumDims(), accessMap.getNumSymbols(), 0,
|
cst.reset(accessMap.getNumDims(), accessMap.getNumSymbols(), 0,
|
||||||
accessValueMap.getOperands());
|
accessValueMap.getOperands());
|
||||||
|
|
||||||
// Add equality constraints.
|
// Add equality constraints.
|
||||||
unsigned numDims = accessMap.getNumDims();
|
unsigned numDims = accessMap.getNumDims();
|
||||||
|
@ -178,65 +159,63 @@ std::unique_ptr<MemRefRegion> mlir::getMemRefRegion(Instruction *opInst,
|
||||||
// Add inequalties for loop lower/upper bounds.
|
// Add inequalties for loop lower/upper bounds.
|
||||||
for (unsigned i = 0; i < numDims + numSymbols; ++i) {
|
for (unsigned i = 0; i < numDims + numSymbols; ++i) {
|
||||||
if (auto loop = getForInductionVarOwner(accessValueMap.getOperand(i))) {
|
if (auto loop = getForInductionVarOwner(accessValueMap.getOperand(i))) {
|
||||||
// Note that regionCst can now have more dimensions than accessMap if the
|
// Note that cst can now have more dimensions than accessMap if the
|
||||||
// bounds expressions involve outer loops or other symbols.
|
// bounds expressions involve outer loops or other symbols.
|
||||||
// TODO(bondhugula): rewrite this to use getInstIndexSet; this way
|
// TODO(bondhugula): rewrite this to use getInstIndexSet; this way
|
||||||
// conditionals will be handled when the latter supports it.
|
// conditionals will be handled when the latter supports it.
|
||||||
if (!regionCst->addAffineForOpDomain(loop))
|
if (!cst.addAffineForOpDomain(loop))
|
||||||
return nullptr;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// Has to be a valid symbol.
|
// Has to be a valid symbol.
|
||||||
auto *symbol = accessValueMap.getOperand(i);
|
auto *symbol = accessValueMap.getOperand(i);
|
||||||
assert(symbol->isValidSymbol());
|
assert(symbol->isValidSymbol());
|
||||||
// Check if the symbol is a constant.
|
// Check if the symbol is a constant.
|
||||||
if (auto *opInst = symbol->getDefiningInst()) {
|
if (auto *inst = symbol->getDefiningInst()) {
|
||||||
if (auto constOp = opInst->dyn_cast<ConstantIndexOp>()) {
|
if (auto constOp = inst->dyn_cast<ConstantIndexOp>()) {
|
||||||
regionCst->setIdToConstant(*symbol, constOp->getValue());
|
cst.setIdToConstant(*symbol, constOp->getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add access function equalities to connect loop IVs to data dimensions.
|
// Add access function equalities to connect loop IVs to data dimensions.
|
||||||
if (!regionCst->composeMap(&accessValueMap)) {
|
if (!cst.composeMap(&accessValueMap)) {
|
||||||
LLVM_DEBUG(llvm::dbgs() << "getMemRefRegion: compose affine map failed\n");
|
LLVM_DEBUG(llvm::dbgs() << "getMemRefRegion: compose affine map failed\n");
|
||||||
LLVM_DEBUG(accessValueMap.getAffineMap().dump());
|
LLVM_DEBUG(accessValueMap.getAffineMap().dump());
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Eliminate any loop IVs other than the outermost 'loopDepth' IVs, on which
|
// Eliminate any loop IVs other than the outermost 'loopDepth' IVs, on which
|
||||||
// this memref region is symbolic.
|
// this memref region is symbolic.
|
||||||
SmallVector<OpPointer<AffineForOp>, 4> outerIVs;
|
SmallVector<OpPointer<AffineForOp>, 4> outerIVs;
|
||||||
getLoopIVs(*opInst, &outerIVs);
|
getLoopIVs(*inst, &outerIVs);
|
||||||
assert(loopDepth <= outerIVs.size() && "invalid loop depth");
|
assert(loopDepth <= outerIVs.size() && "invalid loop depth");
|
||||||
outerIVs.resize(loopDepth);
|
outerIVs.resize(loopDepth);
|
||||||
for (auto *operand : accessValueMap.getOperands()) {
|
for (auto *operand : accessValueMap.getOperands()) {
|
||||||
OpPointer<AffineForOp> iv;
|
OpPointer<AffineForOp> iv;
|
||||||
if ((iv = getForInductionVarOwner(operand)) &&
|
if ((iv = getForInductionVarOwner(operand)) &&
|
||||||
llvm::is_contained(outerIVs, iv) == false) {
|
llvm::is_contained(outerIVs, iv) == false) {
|
||||||
regionCst->projectOut(operand);
|
cst.projectOut(operand);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Project out any local variables (these would have been added for any
|
// Project out any local variables (these would have been added for any
|
||||||
// mod/divs).
|
// mod/divs).
|
||||||
regionCst->projectOut(regionCst->getNumDimAndSymbolIds(),
|
cst.projectOut(cst.getNumDimAndSymbolIds(), cst.getNumLocalIds());
|
||||||
regionCst->getNumLocalIds());
|
|
||||||
|
|
||||||
// Set all identifiers appearing after the first 'rank' identifiers as
|
// Set all identifiers appearing after the first 'rank' identifiers as
|
||||||
// symbolic identifiers - so that the ones correspoding to the memref
|
// symbolic identifiers - so that the ones correspoding to the memref
|
||||||
// dimensions are the dimensional identifiers for the memref region.
|
// dimensions are the dimensional identifiers for the memref region.
|
||||||
regionCst->setDimSymbolSeparation(regionCst->getNumDimAndSymbolIds() - rank);
|
cst.setDimSymbolSeparation(cst.getNumDimAndSymbolIds() - rank);
|
||||||
|
|
||||||
// Constant fold any symbolic identifiers.
|
// Constant fold any symbolic identifiers.
|
||||||
regionCst->constantFoldIdRange(/*pos=*/regionCst->getNumDimIds(),
|
cst.constantFoldIdRange(/*pos=*/cst.getNumDimIds(),
|
||||||
/*num=*/regionCst->getNumSymbolIds());
|
/*num=*/cst.getNumSymbolIds());
|
||||||
|
|
||||||
assert(regionCst->getNumDimIds() == rank && "unexpected MemRefRegion format");
|
assert(cst.getNumDimIds() == rank && "unexpected MemRefRegion format");
|
||||||
|
|
||||||
LLVM_DEBUG(llvm::dbgs() << "Memory region:\n");
|
LLVM_DEBUG(llvm::dbgs() << "Memory region:\n");
|
||||||
LLVM_DEBUG(region->getConstraints()->dump());
|
LLVM_DEBUG(cst.dump());
|
||||||
|
return true;
|
||||||
return region;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(mlir-team): improve/complete this when we have target data.
|
// TODO(mlir-team): improve/complete this when we have target data.
|
||||||
|
@ -282,19 +261,19 @@ bool mlir::boundCheckLoadOrStoreOp(LoadOrStoreOpPointer loadOrStoreOp,
|
||||||
|
|
||||||
Instruction *opInst = loadOrStoreOp->getInstruction();
|
Instruction *opInst = loadOrStoreOp->getInstruction();
|
||||||
|
|
||||||
auto region = getMemRefRegion(opInst, /*loopDepth=*/0);
|
MemRefRegion region(opInst->getLoc());
|
||||||
if (!region)
|
if (!region.compute(opInst, /*loopDepth=*/0))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
LLVM_DEBUG(llvm::dbgs() << "Memory region");
|
LLVM_DEBUG(llvm::dbgs() << "Memory region");
|
||||||
LLVM_DEBUG(region->getConstraints()->dump());
|
LLVM_DEBUG(region.getConstraints()->dump());
|
||||||
|
|
||||||
bool outOfBounds = false;
|
bool outOfBounds = false;
|
||||||
unsigned rank = loadOrStoreOp->getMemRefType().getRank();
|
unsigned rank = loadOrStoreOp->getMemRefType().getRank();
|
||||||
|
|
||||||
// For each dimension, check for out of bounds.
|
// For each dimension, check for out of bounds.
|
||||||
for (unsigned r = 0; r < rank; r++) {
|
for (unsigned r = 0; r < rank; r++) {
|
||||||
FlatAffineConstraints ucst(*region->getConstraints());
|
FlatAffineConstraints ucst(*region.getConstraints());
|
||||||
|
|
||||||
// Intersect memory region with constraint capturing out of bounds (both out
|
// Intersect memory region with constraint capturing out of bounds (both out
|
||||||
// of upper and out of lower), and check if the constraint system is
|
// of upper and out of lower), and check if the constraint system is
|
||||||
|
@ -314,7 +293,7 @@ bool mlir::boundCheckLoadOrStoreOp(LoadOrStoreOpPointer loadOrStoreOp,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for a negative index.
|
// Check for a negative index.
|
||||||
FlatAffineConstraints lcst(*region->getConstraints());
|
FlatAffineConstraints lcst(*region.getConstraints());
|
||||||
std::fill(ineq.begin(), ineq.end(), 0);
|
std::fill(ineq.begin(), ineq.end(), 0);
|
||||||
// d_i <= -1;
|
// d_i <= -1;
|
||||||
lcst.addConstantUpperBound(r, -1);
|
lcst.addConstantUpperBound(r, -1);
|
||||||
|
@ -521,6 +500,12 @@ MemRefAccess::MemRefAccess(Instruction *loadOrStoreOpInst) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned MemRefAccess::getRank() const {
|
||||||
|
return memref->getType().cast<MemRefType>().getRank();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MemRefAccess::isStore() const { return opInst->isa<StoreOp>(); }
|
||||||
|
|
||||||
/// Returns the nesting depth of this statement, i.e., the number of loops
|
/// Returns the nesting depth of this statement, i.e., the number of loops
|
||||||
/// surrounding this statement.
|
/// surrounding this statement.
|
||||||
unsigned mlir::getNestingDepth(const Instruction &inst) {
|
unsigned mlir::getNestingDepth(const Instruction &inst) {
|
||||||
|
@ -600,8 +585,8 @@ Optional<int64_t> mlir::getMemoryFootprintBytes(const Block &block,
|
||||||
// all regions for a given memref instead of creating one region per
|
// all regions for a given memref instead of creating one region per
|
||||||
// memory op. This way we would be allocating O(num of memref's) sets
|
// memory op. This way we would be allocating O(num of memref's) sets
|
||||||
// instead of O(num of load/store op's).
|
// instead of O(num of load/store op's).
|
||||||
auto region = getMemRefRegion(opInst, 0);
|
auto region = std::make_unique<MemRefRegion>(opInst->getLoc());
|
||||||
if (!region) {
|
if (!region->compute(opInst, /*loopDepth=*/0)) {
|
||||||
LLVM_DEBUG(llvm::dbgs() << "Error obtaining memory region\n");
|
LLVM_DEBUG(llvm::dbgs() << "Error obtaining memory region\n");
|
||||||
// TODO: stop the walk if an error occurred.
|
// TODO: stop the walk if an error occurred.
|
||||||
error = true;
|
error = true;
|
||||||
|
|
|
@ -183,7 +183,8 @@ static bool getFullMemRefAsRegion(Instruction *opInst, unsigned numParamLoopIVs,
|
||||||
SmallVector<OpPointer<AffineForOp>, 4> ivs;
|
SmallVector<OpPointer<AffineForOp>, 4> ivs;
|
||||||
getLoopIVs(*opInst, &ivs);
|
getLoopIVs(*opInst, &ivs);
|
||||||
ivs.resize(numParamLoopIVs);
|
ivs.resize(numParamLoopIVs);
|
||||||
SmallVector<Value *, 4> symbols = extractForInductionVars(ivs);
|
SmallVector<Value *, 4> symbols;
|
||||||
|
extractForInductionVars(ivs, &symbols);
|
||||||
regionCst->reset(rank, numParamLoopIVs, 0);
|
regionCst->reset(rank, numParamLoopIVs, 0);
|
||||||
regionCst->setIdValues(rank, rank + numParamLoopIVs, symbols);
|
regionCst->setIdValues(rank, rank + numParamLoopIVs, symbols);
|
||||||
|
|
||||||
|
@ -576,8 +577,8 @@ uint64_t DmaGeneration::runOnBlock(Block::iterator begin, Block::iterator end) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the MemRefRegion accessed.
|
// Compute the MemRefRegion accessed.
|
||||||
auto region = getMemRefRegion(opInst, dmaDepth);
|
auto region = std::make_unique<MemRefRegion>(opInst->getLoc());
|
||||||
if (!region) {
|
if (!region->compute(opInst, dmaDepth)) {
|
||||||
LLVM_DEBUG(llvm::dbgs()
|
LLVM_DEBUG(llvm::dbgs()
|
||||||
<< "Error obtaining memory region: semi-affine maps?\n");
|
<< "Error obtaining memory region: semi-affine maps?\n");
|
||||||
LLVM_DEBUG(llvm::dbgs() << "over-approximating to the entire memref\n");
|
LLVM_DEBUG(llvm::dbgs() << "over-approximating to the entire memref\n");
|
||||||
|
|
|
@ -921,7 +921,8 @@ static Value *createPrivateMemRef(OpPointer<AffineForOp> forOp,
|
||||||
unsigned rank = oldMemRefType.getRank();
|
unsigned rank = oldMemRefType.getRank();
|
||||||
|
|
||||||
// Compute MemRefRegion for 'srcStoreOpInst' at depth 'dstLoopDepth'.
|
// Compute MemRefRegion for 'srcStoreOpInst' at depth 'dstLoopDepth'.
|
||||||
auto region = getMemRefRegion(srcStoreOpInst, dstLoopDepth);
|
MemRefRegion region(srcStoreOpInst->getLoc());
|
||||||
|
region.compute(srcStoreOpInst, dstLoopDepth);
|
||||||
SmallVector<int64_t, 4> newShape;
|
SmallVector<int64_t, 4> newShape;
|
||||||
std::vector<SmallVector<int64_t, 4>> lbs;
|
std::vector<SmallVector<int64_t, 4>> lbs;
|
||||||
SmallVector<int64_t, 8> lbDivisors;
|
SmallVector<int64_t, 8> lbDivisors;
|
||||||
|
@ -929,11 +930,11 @@ static Value *createPrivateMemRef(OpPointer<AffineForOp> forOp,
|
||||||
// Query 'region' for 'newShape' and lower bounds of MemRefRegion accessed
|
// Query 'region' for 'newShape' and lower bounds of MemRefRegion accessed
|
||||||
// by 'srcStoreOpInst' at depth 'dstLoopDepth'.
|
// by 'srcStoreOpInst' at depth 'dstLoopDepth'.
|
||||||
Optional<int64_t> numElements =
|
Optional<int64_t> numElements =
|
||||||
region->getConstantBoundingSizeAndShape(&newShape, &lbs, &lbDivisors);
|
region.getConstantBoundingSizeAndShape(&newShape, &lbs, &lbDivisors);
|
||||||
assert(numElements.hasValue() &&
|
assert(numElements.hasValue() &&
|
||||||
"non-constant number of elts in local buffer");
|
"non-constant number of elts in local buffer");
|
||||||
|
|
||||||
const FlatAffineConstraints *cst = region->getConstraints();
|
const FlatAffineConstraints *cst = region.getConstraints();
|
||||||
// 'outerIVs' holds the values that this memory region is symbolic/paramteric
|
// 'outerIVs' holds the values that this memory region is symbolic/paramteric
|
||||||
// on; this would correspond to loop IVs surrounding the level at which the
|
// on; this would correspond to loop IVs surrounding the level at which the
|
||||||
// slice is being materialized.
|
// slice is being materialized.
|
||||||
|
|
|
@ -201,7 +201,8 @@ UtilResult mlir::tileCodeGen(MutableArrayRef<OpPointer<AffineForOp>> band,
|
||||||
// Move the loop body of the original nest to the new one.
|
// Move the loop body of the original nest to the new one.
|
||||||
moveLoopBody(origLoops[origLoops.size() - 1], innermostPointLoop);
|
moveLoopBody(origLoops[origLoops.size() - 1], innermostPointLoop);
|
||||||
|
|
||||||
SmallVector<Value *, 8> origLoopIVs = extractForInductionVars(band);
|
SmallVector<Value *, 8> origLoopIVs;
|
||||||
|
extractForInductionVars(band, &origLoopIVs);
|
||||||
SmallVector<Optional<Value *>, 6> ids(origLoopIVs.begin(), origLoopIVs.end());
|
SmallVector<Optional<Value *>, 6> ids(origLoopIVs.begin(), origLoopIVs.end());
|
||||||
FlatAffineConstraints cst;
|
FlatAffineConstraints cst;
|
||||||
getIndexSet(band, &cst);
|
getIndexSet(band, &cst);
|
||||||
|
|
|
@ -178,8 +178,9 @@ void MemRefDataFlowOpt::visitInstruction(Instruction *opInst) {
|
||||||
// is trivially loading from a single location at that depth; so there
|
// is trivially loading from a single location at that depth; so there
|
||||||
// isn't a need to call isRangeOneToOne.
|
// isn't a need to call isRangeOneToOne.
|
||||||
if (getNestingDepth(*storeOpInst) < loadOpDepth) {
|
if (getNestingDepth(*storeOpInst) < loadOpDepth) {
|
||||||
auto region = getMemRefRegion(loadOpInst, nsLoops);
|
MemRefRegion region(loadOpInst->getLoc());
|
||||||
if (!region->getConstraints()->isRangeOneToOne(
|
region.compute(loadOpInst, nsLoops);
|
||||||
|
if (!region.getConstraints()->isRangeOneToOne(
|
||||||
/*start=*/0, /*limit=*/loadOp->getMemRefType().getRank()))
|
/*start=*/0, /*limit=*/loadOp->getMemRefType().getRank()))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue