mirror of
https://github.com/intel/llvm.git
synced 2026-01-26 12:26:52 +08:00
Drop unusued HyperRectangularSet.h/.cpp, given the new design being worked on.
- drop these ununsed/incomplete sketches given the new design @albertcohen is working on, and given that FlatAffineConstraints is now stable and fast enough for all the analyses/transforms that depend on it. PiperOrigin-RevId: 227322739
This commit is contained in:
committed by
jpienaar
parent
f12182157e
commit
18fbc3e170
@@ -1,321 +0,0 @@
|
||||
//===- HyperRectangularSet.h - MLIR HyperRectangle Class --------*- C++ -*-===//
|
||||
//
|
||||
// Copyright 2019 The MLIR Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
//
|
||||
// A symbolic hyper-rectangular set of integer points for analysis.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef MLIR_ANALYSIS_HYPER_RECTANGULAR_SET_H
|
||||
#define MLIR_ANALYSIS_HYPER_RECTANGULAR_SET_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "mlir/Analysis/AffineStructures.h"
|
||||
#include "mlir/IR/AffineExpr.h"
|
||||
#include "mlir/IR/IntegerSet.h"
|
||||
#include "llvm/ADT/ilist.h"
|
||||
#include "llvm/ADT/ilist_node.h"
|
||||
|
||||
namespace mlir {
|
||||
|
||||
class AffineApplyOp;
|
||||
class AffineBound;
|
||||
class AffineCondition;
|
||||
class AffineMap;
|
||||
class IntegerSet;
|
||||
class MLIRContext;
|
||||
class MutableIntegerSet;
|
||||
class FlatAffineConstraints;
|
||||
class HyperRectangleList;
|
||||
class Value;
|
||||
|
||||
/// A list of affine bounds.
|
||||
// Not using a MutableAffineMap here since numSymbols is the same as the
|
||||
// containing HyperRectangularSet's numSymbols, and its numDims is 0.
|
||||
using AffineBoundExprList = SmallVector<AffineExpr, 4>;
|
||||
|
||||
/// A HyperRectangularSet is a symbolic set of integer points contained in a
|
||||
/// hyper-rectangular space. It supports set manipulation operations
|
||||
/// and other queries to aid analysis of multi-dimensional integer sets that can
|
||||
/// be represented as integer points inside a symbolic hyper-rectangle, i.e.,
|
||||
/// an interval is associated with each dimension, and the lower and upper
|
||||
/// bounds of each interval are symbolic affine expressions. The bounds on
|
||||
/// a 'dimension' can't depend on other 'dimensions'. The fields of this set are
|
||||
/// always maintained in an irredundant form (no redundant bounds), and the
|
||||
/// bounds are simplified under its context field.
|
||||
//
|
||||
// Example: dims: (d0, d1), symbols: (M, N)
|
||||
// 0 <= d0 <= 511
|
||||
// max(128,M) <= d1 <= min(N-1,256)
|
||||
//
|
||||
// Symbols here aren't necessarily associated with Function's symbols; they
|
||||
// could also correspond to outer loop IVs for example or anything abstract. The
|
||||
// binding to SSA values for dimensions/symbols is optional, and these are in an
|
||||
// abstract integer domain. As an example, to describe data accessed in a tile
|
||||
// surrounded by loop i0, i1, the following set symbolic in i0, i1 is a
|
||||
// hyper-rectangular set:
|
||||
//
|
||||
// 128*i <= d0 <= min(128*i0 + 127, N-1)
|
||||
// 128*i <= d1 <= min(128*i1 + 127, N-1)
|
||||
//
|
||||
// The context field specifies constraints on the symbols, and the set is always
|
||||
// kept in a form simplified under 'context', i.e., information implied by
|
||||
// context is used to simplify bounds. For eg., if the context includes (N >=
|
||||
// 0), a bound such as d0 >= max(0, N) will never arise. This would be
|
||||
// simplified to d0 >= N at construction time or when the context is updated.
|
||||
// As another example, if N%128 = 0, M <= N-1 floordiv 128 is specified, we will
|
||||
// never have a bound such as d0 <= min(128*M + 127, N-1); this would be
|
||||
// simplified to d0 <= 128*M + 127 (since 128*M + 127 is always <= N-1 under
|
||||
// such circumstances). In the context of code generation, such simplification
|
||||
// leads to code that explicitly scans "full" tiles / no boundary case and with
|
||||
// lower control overhead.
|
||||
//
|
||||
class HyperRectangularSet
|
||||
: public llvm::ilist_node_with_parent<HyperRectangularSet,
|
||||
HyperRectangleList> {
|
||||
public:
|
||||
/// Construct a hyper-rectangular set from FlatAffineConstraints if possible;
|
||||
/// returns nullptr if it cannot.
|
||||
static std::unique_ptr<HyperRectangularSet>
|
||||
getFromFlatAffineConstraints(const FlatAffineConstraints &cst);
|
||||
|
||||
HyperRectangularSet(unsigned numDims, unsigned numSymbols,
|
||||
ArrayRef<ArrayRef<AffineExpr>> lbs,
|
||||
ArrayRef<ArrayRef<AffineExpr>> ubs, MLIRContext *context,
|
||||
IntegerSet symbolContext = IntegerSet());
|
||||
|
||||
unsigned getNumDims() const { return numDims; }
|
||||
unsigned getNumSymbols() const { return numSymbols; }
|
||||
|
||||
ArrayRef<AffineBoundExprList> getLowerBounds() const { return lowerBounds; }
|
||||
ArrayRef<AffineBoundExprList> getUpperBounds() const { return upperBounds; }
|
||||
|
||||
AffineBoundExprList &getLowerBound(unsigned idx) { return lowerBounds[idx]; }
|
||||
AffineBoundExprList &getUpperBound(unsigned idx) { return upperBounds[idx]; }
|
||||
|
||||
const AffineBoundExprList &getLowerBound(unsigned idx) const {
|
||||
return lowerBounds[idx];
|
||||
}
|
||||
const AffineBoundExprList &getUpperBound(unsigned idx) const {
|
||||
return upperBounds[idx];
|
||||
}
|
||||
|
||||
/// Intersects 'rhs' with this set.
|
||||
void intersect(const HyperRectangularSet &rhs);
|
||||
|
||||
/// Performs a union of 'rhs' with this set.
|
||||
void unionize(const HyperRectangularSet &rhs);
|
||||
|
||||
/// Project out num dimensions starting from 'idx'. This is equivalent to
|
||||
/// taking an image of this set on the remaining dimensions.
|
||||
void projectOut(unsigned idx, unsigned num);
|
||||
|
||||
/// Returns true if the set has no integer points in it.
|
||||
bool empty() const;
|
||||
|
||||
/// Add a lower bound expression to dimension position 'idx'.
|
||||
void addLowerBoundExpr(unsigned idx, AffineExpr expr);
|
||||
|
||||
/// Add an upper bound expression to dimension position 'idx'.
|
||||
void addUpperBoundExpr(unsigned idx, AffineExpr expr);
|
||||
|
||||
/// Clear this set's context, i.e., make it the universal set.
|
||||
void clearContext() { context.clear(); }
|
||||
|
||||
void print(raw_ostream &os) const;
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
/// Simplify this set under the symbolic context 'context'.
|
||||
void simplifyUnderContext() {}
|
||||
|
||||
/// The lower bound along any dimension is a max of several pure
|
||||
/// symbolic/constant affine expressions. A bound cannot be mutated from
|
||||
/// outside the class, it has to be to be updated through
|
||||
/// addLowerBoundExpr/addUpperBoundExpr.
|
||||
std::vector<AffineBoundExprList> lowerBounds;
|
||||
// Each upper bound is a min of several pure symbolic/constant affine
|
||||
// expressions.
|
||||
std::vector<AffineBoundExprList> upperBounds;
|
||||
|
||||
Optional<SmallVector<Value *, 8>> dims = None;
|
||||
Optional<SmallVector<Value *, 4>> symbols = None;
|
||||
|
||||
/// Number of real dimensions.
|
||||
unsigned numDims;
|
||||
|
||||
/// Number of symbols (unknown but constant)
|
||||
unsigned numSymbols;
|
||||
|
||||
// Constraints on the symbols. The representation of the set is kept
|
||||
// simplified under this context.
|
||||
MutableIntegerSet context;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Out of place operations.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
static std::unique_ptr<HyperRectangularSet>
|
||||
intersection(const HyperRectangularSet &lhs, const HyperRectangularSet &rhs);
|
||||
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
intersection(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
/// Performs a union of 'lhs' and 'rhs'.
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
unionize(const HyperRectangularSet &lhs, const HyperRectangularSet &rhs);
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
unionize(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
/// Subtract 'rhs' from this lhs and return the result.
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
difference(const HyperRectangularSet &lhs, const HyperRectangularSet &rhs);
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
difference(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
/// Project out num dimensions starting from 'idx'. This is equivalent to
|
||||
/// taking an image of this set on the remaining dimensions.
|
||||
static std::unique_ptr<HyperRectangularSet>
|
||||
projectOut(const HyperRectangularSet &set, unsigned idx, unsigned num);
|
||||
|
||||
} // namespace mlir
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <> struct ilist_traits<::mlir::HyperRectangularSet> {
|
||||
using HyperRectangularSet = ::mlir::HyperRectangularSet;
|
||||
using set_iterator = simple_ilist<HyperRectangularSet>::iterator;
|
||||
|
||||
static void deleteNode(HyperRectangularSet *set) { delete set; }
|
||||
|
||||
void addNodeToList(HyperRectangularSet *set);
|
||||
void removeNodeFromList(HyperRectangularSet *set);
|
||||
void transferNodesFromList(ilist_traits<HyperRectangularSet> &otherList,
|
||||
set_iterator first, set_iterator last);
|
||||
|
||||
private:
|
||||
mlir::HyperRectangleList *getContainingBlock();
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
namespace mlir {
|
||||
|
||||
/// A list of hyper-rectangular sets lying in the same space of dimensional
|
||||
/// and symbolic identifiers. The individual set elements are always kept
|
||||
/// disjoint (re-evaluate choice) and minimal, i.e., the union of any subset of
|
||||
/// the contained hyperrectangles can't be coalesced into a single
|
||||
/// hyper-rectangle.
|
||||
class HyperRectangleList {
|
||||
public:
|
||||
/// Construct a constraint system reserving memory for the specified number of
|
||||
/// constraints and identifiers.
|
||||
explicit HyperRectangleList(const FlatAffineConstraints &cst);
|
||||
|
||||
HyperRectangleList(unsigned numDims, unsigned numSymbols,
|
||||
ArrayRef<std::unique_ptr<HyperRectangularSet>> sets);
|
||||
|
||||
unsigned getNumDims() const { return numDims; }
|
||||
unsigned getNumSymbols() const { return numSymbols; }
|
||||
|
||||
// In-place operations.
|
||||
|
||||
/// Intersects a hyper rectangular set list 'rhs' with this set.
|
||||
void intersect(const HyperRectangleList &rhs);
|
||||
|
||||
/// Intersects 'rhs' with this set.
|
||||
void intersect(const HyperRectangularSet &rhs);
|
||||
|
||||
/// Performs a union of 'rhs' with this set.
|
||||
void unionize(const HyperRectangleList &rhs);
|
||||
|
||||
/// Performs a union of 'rhs' with this set.
|
||||
void unionize(const HyperRectangularSet &rhs);
|
||||
|
||||
/// Project out num dimensions starting from 'idx'. This is equivalent to
|
||||
/// taking an image of this set on the remaining dimensions.
|
||||
void projectOut(unsigned idx, unsigned num);
|
||||
|
||||
/// Returns true if all the sets are empty.
|
||||
bool empty() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Hyper-rectangular set list management.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// These are for the list of hyper-rectangular set elements.
|
||||
using HyperRectangleListTy = ::llvm::iplist<HyperRectangularSet>;
|
||||
HyperRectangleListTy &getRectangles() { return hyperRectangles; }
|
||||
|
||||
// Iteration over the instructions in the block.
|
||||
using const_iterator = HyperRectangleListTy::const_iterator;
|
||||
|
||||
const_iterator begin() const { return hyperRectangles.begin(); }
|
||||
const_iterator end() const { return hyperRectangles.end(); }
|
||||
|
||||
bool listEmpty() const { return hyperRectangles.empty(); }
|
||||
|
||||
void addSet(std::unique_ptr<HyperRectangularSet> set) {
|
||||
set->clearContext();
|
||||
hyperRectangles.push_back(set.release());
|
||||
}
|
||||
|
||||
private:
|
||||
// Mutable versions of the iterators are private.
|
||||
using iterator = HyperRectangleListTy::iterator;
|
||||
iterator begin() { return hyperRectangles.begin(); }
|
||||
iterator end() { return hyperRectangles.end(); }
|
||||
|
||||
/// Simplify under the symbolic context 'context'.
|
||||
void simplifyUnderContext() {}
|
||||
|
||||
/// Number of identifiers corresponding to real dimensions.
|
||||
unsigned numDims;
|
||||
|
||||
/// Number of identifiers corresponding to symbols (unknown but constant)
|
||||
unsigned numSymbols;
|
||||
|
||||
/// The list of hyper-rectangular sets contained.
|
||||
HyperRectangleListTy hyperRectangles;
|
||||
|
||||
// Constraints on the symbols. The representation of the set is kept
|
||||
// simplified under this context.
|
||||
MutableIntegerSet context;
|
||||
};
|
||||
|
||||
// Out of place operations.
|
||||
|
||||
// Return a bounding box of this list of hyper-rectangles. This is notionally
|
||||
// equivanelt to a rectangular/convex hull.
|
||||
std::unique_ptr<HyperRectangularSet> boundingBox();
|
||||
|
||||
/// Intersects and returns the result.
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
intersection(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
/// Performs a union and returns the result.
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
unionize(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
/// Subtracts 'rhs' from this lhs and return the result.
|
||||
static std::unique_ptr<HyperRectangleList>
|
||||
difference(const HyperRectangleList &lhs, const HyperRectangleList &rhs);
|
||||
|
||||
} // end namespace mlir.
|
||||
|
||||
#endif // MLIR_ANALYSIS_HYPER_RECTANGULAR_SET_H
|
||||
@@ -1,199 +0,0 @@
|
||||
//===- HyperRectangularSet.cpp - MLIR HyperRectangularSet Class -----------===//
|
||||
//
|
||||
// Copyright 2019 The MLIR Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
// =============================================================================
|
||||
//
|
||||
// Structures for affine/polyhedral analysis of MLIR functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "mlir/Analysis/HyperRectangularSet.h"
|
||||
#include "mlir/IR/AffineExpr.h"
|
||||
#include "mlir/IR/IntegerSet.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <algorithm>
|
||||
using namespace mlir;
|
||||
|
||||
// TODO(bondhugula): clean this code up.
|
||||
// Get the constant bound that is either the min or max (depending on 'cmp').
|
||||
static Optional<int64_t>
|
||||
getReducedConstBound(const HyperRectangularSet &set, unsigned *idx,
|
||||
std::function<bool(int64_t, int64_t)> const &cmp) {
|
||||
Optional<int64_t> val = None;
|
||||
|
||||
for (unsigned i = 0, n = set.getNumDims(); i < n; i++) {
|
||||
auto &ubs = set.getLowerBound(i);
|
||||
unsigned j = 0;
|
||||
AffineBoundExprList::const_iterator it, e;
|
||||
for (it = ubs.begin(), e = ubs.end(); it != e; it++, j++) {
|
||||
if (auto cExpr = it->dyn_cast<AffineConstantExpr>()) {
|
||||
if (val == None) {
|
||||
val = cExpr.getValue();
|
||||
*idx = j;
|
||||
} else if (cmp(cExpr.getValue(), val.getValue())) {
|
||||
val = cExpr.getValue();
|
||||
*idx = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
// Merge the two lists of AffineExpr's into a single one, avoiding
|
||||
// duplicates. lb specifies whether the bound lists are for a lower bound or an
|
||||
// upper bound.
|
||||
// TODO(bondhugula): clean this code up.
|
||||
static void mergeBounds(const HyperRectangularSet &set,
|
||||
AffineBoundExprList &lhsList,
|
||||
const AffineBoundExprList &rhsList, bool lb) {
|
||||
// The list of bounds is going to be small. Just a linear search
|
||||
// should be enough to create a list without duplicates.
|
||||
for (auto expr : rhsList) {
|
||||
AffineBoundExprList::const_iterator it;
|
||||
for (it = lhsList.begin(); it != lhsList.end(); it++) {
|
||||
if (expr == *it)
|
||||
break;
|
||||
}
|
||||
if (it == lhsList.end()) {
|
||||
// There can only be one constant affine expr in this bound list.
|
||||
if (auto cExpr = expr.dyn_cast<AffineConstantExpr>()) {
|
||||
unsigned idx;
|
||||
if (lb) {
|
||||
auto cb = getReducedConstBound(
|
||||
set, &idx,
|
||||
[](int64_t newVal, int64_t oldVal) { return newVal < oldVal; });
|
||||
if (!cb.hasValue()) {
|
||||
lhsList.push_back(expr);
|
||||
continue;
|
||||
}
|
||||
if (cExpr.getValue() < cb)
|
||||
lhsList[idx] = expr;
|
||||
// A constant value >= the existing bound constant.
|
||||
continue;
|
||||
}
|
||||
// Upper bound case.
|
||||
auto cb =
|
||||
getReducedConstBound(set, &idx, [](int64_t newVal, int64_t oldVal) {
|
||||
return newVal > oldVal;
|
||||
});
|
||||
if (!cb.hasValue()) {
|
||||
lhsList.push_back(expr);
|
||||
continue;
|
||||
}
|
||||
if (cExpr.getValue() > cb)
|
||||
lhsList[idx] = expr;
|
||||
continue;
|
||||
}
|
||||
// Not a constant expression; push it.
|
||||
// TODO(bondhugula): check if this was implied by an existing symbolic
|
||||
// expression or by the context.
|
||||
lhsList.push_back(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HyperRectangularSet::HyperRectangularSet(unsigned numDims, unsigned numSymbols,
|
||||
ArrayRef<ArrayRef<AffineExpr>> lbs,
|
||||
ArrayRef<ArrayRef<AffineExpr>> ubs,
|
||||
MLIRContext *context,
|
||||
IntegerSet symbolContext)
|
||||
: context(symbolContext ? MutableIntegerSet(symbolContext, context)
|
||||
: MutableIntegerSet(numDims, numSymbols, context)) {
|
||||
unsigned d = 0;
|
||||
for (auto boundList : lbs) {
|
||||
AffineBoundExprList lb;
|
||||
for (auto expr : boundList) {
|
||||
assert(expr.isSymbolicOrConstant() &&
|
||||
"bound expression should be symbolic or constant");
|
||||
lb.push_back(expr);
|
||||
}
|
||||
mergeBounds(*this, lowerBounds[d++], lb, true);
|
||||
}
|
||||
|
||||
d = 0;
|
||||
for (auto boundList : ubs) {
|
||||
AffineBoundExprList ub;
|
||||
for (auto expr : boundList) {
|
||||
assert(expr.isSymbolicOrConstant() &&
|
||||
"bound expression should be symbolic or constant");
|
||||
ub.push_back(expr);
|
||||
}
|
||||
mergeBounds(*this, upperBounds[d++], ub, false);
|
||||
}
|
||||
|
||||
simplifyUnderContext();
|
||||
}
|
||||
|
||||
void HyperRectangularSet::projectOut(unsigned idx, unsigned num) {
|
||||
// Erase the bounds along the projected out dimensions.
|
||||
lowerBounds.erase(lowerBounds.begin() + idx, lowerBounds.begin() + idx + num);
|
||||
upperBounds.erase(upperBounds.begin() + idx, upperBounds.begin() + idx + num);
|
||||
numDims -= num;
|
||||
}
|
||||
|
||||
void HyperRectangularSet::intersect(const HyperRectangularSet &rhs) {
|
||||
assert(rhs.getNumSymbols() == getNumSymbols() &&
|
||||
rhs.getNumDims() == getNumDims() && "operand space does not match");
|
||||
|
||||
// Intersection is just a concatenation of distinct bounds.
|
||||
for (unsigned i = 0, n = getNumDims(); i < n; i++) {
|
||||
mergeBounds(*this, getLowerBound(i), rhs.getLowerBound(i), true);
|
||||
mergeBounds(*this, getUpperBound(i), rhs.getUpperBound(i), false);
|
||||
}
|
||||
}
|
||||
|
||||
void HyperRectangularSet::print(raw_ostream &os) const {
|
||||
os << "Hyper rectangular set: " << numDims << "dimensions, " << numSymbols
|
||||
<< "symbols\n";
|
||||
os << "Lower bounds\n";
|
||||
unsigned d = 0;
|
||||
for (auto &lb : lowerBounds) {
|
||||
os << "Dim " << d++ << "\n";
|
||||
for (auto expr : lb) {
|
||||
expr.print(os);
|
||||
}
|
||||
}
|
||||
d = 0;
|
||||
os << "Upper bounds\n";
|
||||
for (auto &lb : upperBounds) {
|
||||
os << "Dim " << d++ << "\n";
|
||||
for (auto expr : lb) {
|
||||
expr.print(os);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HyperRectangleList::projectOut(unsigned idx, unsigned num) {
|
||||
for (auto &elt : hyperRectangles) {
|
||||
elt.projectOut(idx, num);
|
||||
}
|
||||
// TODO: after a project out, some of the sets may be identical. Remove those.
|
||||
}
|
||||
|
||||
bool HyperRectangleList::empty() const {
|
||||
for (auto &set : hyperRectangles) {
|
||||
if (!set.empty())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HyperRectangularSet::empty() const {
|
||||
assert(0 && "unimplemented");
|
||||
return false;
|
||||
}
|
||||
|
||||
void HyperRectangularSet::dump() const { print(llvm::errs()); }
|
||||
Reference in New Issue
Block a user