EDSC: unify Expr storage

EDSC expressions evolved to have different types of underlying storage.
Separate classes are used for unary, binary, ternary and variadic expressions.
The latter covers all the needs of the three special cases.  Remove these
special cases and use a single ExprStorage class everywhere while maintaining
the same APIs at the Expr level (ExprStorage is an internal implementation
class).

This is step 1/n to converging EDSC expressions and Ops and making EDSCs
support custom operations.

PiperOrigin-RevId: 233704912
This commit is contained in:
Alex Zinenko
2019-02-13 00:54:55 -08:00
committed by jpienaar
parent 465746f262
commit bc184cff3f
2 changed files with 53 additions and 67 deletions

View File

@@ -41,11 +41,6 @@ namespace edsc {
namespace detail {
struct ExprStorage;
struct UnaryExprStorage;
struct BinaryExprStorage;
struct TernaryExprStorage;
struct VariadicExprStorage;
struct StmtStorage;
} // namespace detail
@@ -182,8 +177,6 @@ public:
template <typename U> U dyn_cast() const;
template <typename U> U cast() const;
MLIRContext *getContext() const;
/// Returns the classification for this type.
ExprKind getKind() const;
unsigned getId() const;
@@ -221,7 +214,6 @@ private:
};
struct UnaryExpr : public Expr {
using ImplType = detail::UnaryExprStorage;
friend class Expr;
UnaryExpr(ExprKind kind, Expr expr);
@@ -234,7 +226,6 @@ protected:
};
struct BinaryExpr : public Expr {
using ImplType = detail::BinaryExprStorage;
friend class Expr;
BinaryExpr(ExprKind kind, Expr lhs, Expr rhs);
Expr getLHS() const;
@@ -247,7 +238,6 @@ protected:
};
struct TernaryExpr : public Expr {
using ImplType = detail::TernaryExprStorage;
friend class Expr;
TernaryExpr(ExprKind kind, Expr cond, Expr lhs, Expr rhs);
Expr getCond() const;
@@ -261,7 +251,6 @@ protected:
};
struct VariadicExpr : public Expr {
using ImplType = detail::VariadicExprStorage;
friend class Expr;
VariadicExpr(ExprKind kind, llvm::ArrayRef<Expr> exprs,
llvm::ArrayRef<Type> types = {});
@@ -275,7 +264,6 @@ protected:
};
struct StmtBlockLikeExpr : public Expr {
using ImplType = detail::VariadicExprStorage; // same storage as variadic
friend class Expr;
StmtBlockLikeExpr(ExprKind kind, llvm::ArrayRef<Expr> exprs,
llvm::ArrayRef<Type> types = {});

View File

@@ -39,35 +39,45 @@ namespace edsc {
namespace detail {
struct ExprStorage {
ExprStorage(ExprKind kind, unsigned id = Expr::newId())
: kind(kind), id(id) {}
// Note: this structure is similar to OperationState, but stores lists in a
// EDSC bump allocator.
ExprKind kind;
unsigned id;
};
struct UnaryExprStorage : public ExprStorage {
UnaryExprStorage(ExprKind k, Expr expr) : ExprStorage(k), expr(expr) {}
Expr expr;
};
ArrayRef<Expr> operands;
ArrayRef<Type> resultTypes;
ArrayRef<NamedAttribute> attributes;
struct BinaryExprStorage : public ExprStorage {
BinaryExprStorage(ExprKind k, Expr lhs, Expr rhs)
: ExprStorage(k), lhs(lhs), rhs(rhs) {}
Expr lhs, rhs;
};
ExprStorage(ExprKind kind, ArrayRef<Type> results, ArrayRef<Expr> children,
ArrayRef<NamedAttribute> attrs, unsigned exprId = Expr::newId())
: kind(kind), id(exprId) {
if (!children.empty()) {
auto exprStorage =
Expr::globalAllocator()->Allocate<Expr>(children.size());
std::uninitialized_copy(children.begin(), children.end(), exprStorage);
operands = llvm::makeArrayRef(exprStorage, children.size());
} else {
operands = ArrayRef<Expr>();
}
struct TernaryExprStorage : public ExprStorage {
TernaryExprStorage(ExprKind k, Expr cond, Expr lhs, Expr rhs)
: ExprStorage(k), cond(cond), lhs(lhs), rhs(rhs) {}
Expr cond, lhs, rhs;
};
if (!results.empty()) {
auto typeStorage =
Expr::globalAllocator()->Allocate<Type>(results.size());
std::uninitialized_copy(results.begin(), results.end(), typeStorage);
resultTypes = llvm::makeArrayRef(typeStorage, results.size());
} else {
resultTypes = ArrayRef<Type>();
}
struct VariadicExprStorage : public ExprStorage {
VariadicExprStorage(ExprKind k, ArrayRef<Expr> exprs, ArrayRef<Type> types)
: ExprStorage(k), exprs(exprs.begin(), exprs.end()),
types(types.begin(), types.end()) {}
ArrayRef<Expr> exprs;
ArrayRef<Type> types;
if (!attrs.empty()) {
auto attrStorage =
Expr::globalAllocator()->Allocate<NamedAttribute>(attrs.size());
std::uninitialized_copy(attrs.begin(), attrs.end(), attrStorage);
attributes = llvm::makeArrayRef(attrStorage, attrs.size());
} else {
attributes = ArrayRef<NamedAttribute>();
}
}
};
struct StmtStorage {
@@ -94,7 +104,7 @@ mlir::edsc::ScopedEDSCContext::~ScopedEDSCContext() {
mlir::edsc::Expr::Expr() {
// Initialize with placement new.
storage = Expr::globalAllocator()->Allocate<detail::ExprStorage>();
new (storage) detail::ExprStorage(ExprKind::Unbound);
new (storage) detail::ExprStorage(ExprKind::Unbound, {}, {}, {});
}
ExprKind mlir::edsc::Expr::getKind() const { return storage->kind; }
@@ -409,76 +419,64 @@ llvm::raw_ostream &mlir::edsc::operator<<(llvm::raw_ostream &os,
edsc_expr_t makeBindable() { return Bindable(Expr()); }
mlir::edsc::UnaryExpr::UnaryExpr(ExprKind kind, Expr expr)
: Expr(Expr::globalAllocator()->Allocate<detail::UnaryExprStorage>()) {
: Expr(Expr::globalAllocator()->Allocate<detail::ExprStorage>()) {
// Initialize with placement new.
new (storage) detail::UnaryExprStorage{kind, expr};
new (storage) detail::ExprStorage(kind, {}, {expr}, {});
}
Expr mlir::edsc::UnaryExpr::getExpr() const {
return static_cast<ImplType *>(storage)->expr;
return static_cast<ImplType *>(storage)->operands.front();
}
mlir::edsc::BinaryExpr::BinaryExpr(ExprKind kind, Expr lhs, Expr rhs)
: Expr(Expr::globalAllocator()->Allocate<detail::BinaryExprStorage>()) {
: Expr(Expr::globalAllocator()->Allocate<detail::ExprStorage>()) {
// Initialize with placement new.
new (storage) detail::BinaryExprStorage{kind, lhs, rhs};
new (storage) detail::ExprStorage(kind, {}, {lhs, rhs}, {});
}
Expr mlir::edsc::BinaryExpr::getLHS() const {
return static_cast<ImplType *>(storage)->lhs;
return static_cast<ImplType *>(storage)->operands.front();
}
Expr mlir::edsc::BinaryExpr::getRHS() const {
return static_cast<ImplType *>(storage)->rhs;
return static_cast<ImplType *>(storage)->operands.back();
}
mlir::edsc::TernaryExpr::TernaryExpr(ExprKind kind, Expr cond, Expr lhs,
Expr rhs)
: Expr(Expr::globalAllocator()->Allocate<detail::TernaryExprStorage>()) {
: Expr(Expr::globalAllocator()->Allocate<detail::ExprStorage>()) {
// Initialize with placement new.
new (storage) detail::TernaryExprStorage{kind, cond, lhs, rhs};
new (storage) detail::ExprStorage(kind, {}, {cond, lhs, rhs}, {});
}
Expr mlir::edsc::TernaryExpr::getCond() const {
return static_cast<ImplType *>(storage)->cond;
return static_cast<ImplType *>(storage)->operands[0];
}
Expr mlir::edsc::TernaryExpr::getLHS() const {
return static_cast<ImplType *>(storage)->lhs;
return static_cast<ImplType *>(storage)->operands[1];
}
Expr mlir::edsc::TernaryExpr::getRHS() const {
return static_cast<ImplType *>(storage)->rhs;
return static_cast<ImplType *>(storage)->operands[2];
}
mlir::edsc::VariadicExpr::VariadicExpr(ExprKind kind, ArrayRef<Expr> exprs,
ArrayRef<Type> types)
: Expr(Expr::globalAllocator()->Allocate<detail::VariadicExprStorage>()) {
: Expr(Expr::globalAllocator()->Allocate<detail::ExprStorage>()) {
// Initialize with placement new.
auto exprStorage = Expr::globalAllocator()->Allocate<Expr>(exprs.size());
std::uninitialized_copy(exprs.begin(), exprs.end(), exprStorage);
auto typeStorage = Expr::globalAllocator()->Allocate<Type>(types.size());
std::uninitialized_copy(types.begin(), types.end(), typeStorage);
new (storage) detail::VariadicExprStorage{
kind, ArrayRef<Expr>(exprStorage, exprs.size()),
ArrayRef<Type>(typeStorage, types.size())};
new (storage) detail::ExprStorage(kind, types, exprs, {});
}
ArrayRef<Expr> mlir::edsc::VariadicExpr::getExprs() const {
return static_cast<ImplType *>(storage)->exprs;
return static_cast<ImplType *>(storage)->operands;
}
ArrayRef<Type> mlir::edsc::VariadicExpr::getTypes() const {
return static_cast<ImplType *>(storage)->types;
return static_cast<ImplType *>(storage)->resultTypes;
}
mlir::edsc::StmtBlockLikeExpr::StmtBlockLikeExpr(ExprKind kind,
ArrayRef<Expr> exprs,
ArrayRef<Type> types)
: Expr(Expr::globalAllocator()->Allocate<detail::VariadicExprStorage>()) {
: Expr(Expr::globalAllocator()->Allocate<detail::ExprStorage>()) {
// Initialize with placement new.
auto exprStorage = Expr::globalAllocator()->Allocate<Expr>(exprs.size());
std::uninitialized_copy(exprs.begin(), exprs.end(), exprStorage);
auto typeStorage = Expr::globalAllocator()->Allocate<Type>(types.size());
std::uninitialized_copy(types.begin(), types.end(), typeStorage);
new (storage) detail::VariadicExprStorage{
kind, ArrayRef<Expr>(exprStorage, exprs.size()),
ArrayRef<Type>(typeStorage, types.size())};
new (storage) detail::ExprStorage(kind, types, exprs, {});
}
ArrayRef<Expr> mlir::edsc::StmtBlockLikeExpr::getExprs() const {
return static_cast<ImplType *>(storage)->exprs;
return static_cast<ImplType *>(storage)->operands;
}
mlir::edsc::Stmt::Stmt(const Bindable &lhs, const Expr &rhs,