Add tblgen::Type to wrap around TableGen Type defs

This CL added a tblgen::Type class to wrap around raw TableGen
Record getValue*() calls on Type defs, which will provide a
nicer API for handling TableGen Record.

The PredCNF class is also updated to work together with
tblgen::Type.
PiperOrigin-RevId: 228429090
This commit is contained in:
Lei Zhang 2019-01-08 17:19:22 -08:00 committed by jpienaar
parent 2b902f1288
commit b2cc2c344e
6 changed files with 181 additions and 33 deletions

View File

@ -25,22 +25,46 @@
#include "mlir/Support/LLVM.h"
namespace llvm {
class Init;
class ListInit;
class Record;
} // end namespace llvm
namespace mlir {
// Predicate in conjunctive normal form.
// Predicate in Conjunctive Normal Form (CNF).
//
// CNF is an AND of ORs. That means there are two levels of lists: the inner
// list contains predicate atoms, which are ORed. Then outer list ANDs its inner
// lists.
// An empty CNF is defined as always true, thus matching everything.
class PredCNF {
public:
PredCNF(llvm::ListInit *conditions) : conditions(conditions) {}
// Constructs an empty predicate CNF.
explicit PredCNF() : def(nullptr) {}
// Return template string to construct matcher corresponding to predicate in
// CNF form with '{0}' representing the type.
explicit PredCNF(const llvm::Record *def) : def(def) {}
// Constructs a predicate CNF out of the given TableGen initializer.
// The initializer is allowed to be unset initializer (?); then we are
// constructing an empty predicate CNF.
explicit PredCNF(const llvm::Init *init);
// Returns true if this is an empty predicate CNF.
bool isEmpty() const { return !def; }
// Returns the conditions inside this predicate CNF. Returns nullptr if
// this is an empty predicate CNF.
const llvm::ListInit *getConditions() const;
// Returns the template string to construct the matcher corresponding to this
// predicate CNF. The string uses '{0}' to represent the type.
std::string createTypeMatcherTemplate() const;
private:
llvm::ListInit *conditions;
// The TableGen definition of this predicate CNF. nullptr means an empty
// predicate CNF.
const llvm::Record *def;
};
} // end namespace mlir

View File

@ -0,0 +1,66 @@
//===- Type.h - Type 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.
// =============================================================================
//
// Type wrapper to simplify using TableGen Record defining a MLIR Type.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_TABLEGEN_TYPE_H_
#define MLIR_TABLEGEN_TYPE_H_
#include "mlir/Support/LLVM.h"
#include "mlir/TableGen/Predicate.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class DefInit;
class Record;
} // end namespace llvm
namespace mlir {
namespace tblgen {
// Wrapper class providing helper methods for accessing MLIR Type defined
// in TableGen. This class should closely reflect what is defined as
// class Type in TableGen.
class Type {
public:
explicit Type(const llvm::Record &def);
explicit Type(const llvm::Record *def) : Type(*def) {}
explicit Type(const llvm::DefInit *init);
// Returns the TableGen def name for this type.
StringRef getTableGenDefName() const;
// Returns the method call to invoke upon a MLIR pattern rewriter to
// construct this type. Returns an empty StringRef if the method call
// is undefined or unset.
StringRef getBuilderCall() const;
// Returns this type's predicate CNF, which is used for checking the
// validity of this type.
PredCNF getPredicate() const;
private:
// The TableGen definition of this type.
const llvm::Record &def;
};
} // end namespace tblgen
} // end namespace mlir
#endif // MLIR_TABLEGEN_TYPE_H_

View File

@ -21,6 +21,7 @@
#include "mlir/TableGen/Operator.h"
#include "mlir/TableGen/Predicate.h"
#include "mlir/TableGen/Type.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/TableGen/Error.h"
@ -159,13 +160,9 @@ StringRef mlir::Operator::Attribute::getStorageType() const {
}
bool mlir::Operator::Operand::hasMatcher() const {
llvm::Init *matcher = defInit->getDef()->getValue("predicate")->getValue();
return !isa<llvm::UnsetInit>(matcher);
return !tblgen::Type(defInit).getPredicate().isEmpty();
}
std::string mlir::Operator::Operand::createTypeMatcherTemplate() const {
auto predicate = defInit->getDef()->getValue("predicate")->getValue();
auto predCnf = cast<llvm::DefInit>(predicate);
PredCNF pred(predCnf->getDef()->getValueAsListInit("conditions"));
return pred.createTypeMatcherTemplate();
return tblgen::Type(defInit).getPredicate().createTypeMatcherTemplate();
}

View File

@ -27,10 +27,28 @@
using namespace mlir;
std::string mlir::PredCNF::createTypeMatcherTemplate() const {
PredCNF::PredCNF(const llvm::Init *init) : def(nullptr) {
if (const auto *defInit = dyn_cast<llvm::DefInit>(init)) {
def = defInit->getDef();
assert(def->isSubClassOf("PredCNF") &&
"must be subclass of TableGen 'PredCNF' class");
}
}
const llvm::ListInit *PredCNF::getConditions() const {
if (!def)
return nullptr;
return def->getValueAsListInit("conditions");
}
std::string PredCNF::createTypeMatcherTemplate() const {
const auto *conjunctiveList = getConditions();
if (!conjunctiveList)
return "true";
std::string outString;
llvm::raw_string_ostream ss(outString);
auto conjunctiveList = conditions;
bool firstDisjunctive = true;
for (auto disjunctiveInit : *conjunctiveList) {
ss << (firstDisjunctive ? "(" : " && (");

View File

@ -0,0 +1,51 @@
//===- Type.cpp - Type 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.
// =============================================================================
//
// Type wrapper to simplify using TableGen Record defining a MLIR Type.
//
//===----------------------------------------------------------------------===//
#include "mlir/TableGen/Type.h"
#include "llvm/TableGen/Record.h"
using namespace mlir;
tblgen::Type::Type(const llvm::Record &def) : def(def) {
assert(def.isSubClassOf("Type") &&
"must be subclass of TableGen 'Type' class");
}
tblgen::Type::Type(const llvm::DefInit *init) : Type(*init->getDef()) {}
StringRef tblgen::Type::getTableGenDefName() const { return def.getName(); }
StringRef tblgen::Type::getBuilderCall() const {
const auto *val = def.getValue("builderCall");
assert(val && "TableGen 'Type' class should have 'builderCall' field");
if (const auto *builder = dyn_cast<llvm::CodeInit>(val->getValue()))
return builder->getValue();
return {};
}
PredCNF tblgen::Type::getPredicate() const {
auto *val = def.getValue("predicate");
assert(val && "TableGen 'Type' class should have 'predicate' field");
const auto *pred = dyn_cast<llvm::DefInit>(val->getValue());
return PredCNF(pred);
}

View File

@ -22,6 +22,7 @@
#include "mlir/TableGen/GenInfo.h"
#include "mlir/TableGen/Operator.h"
#include "mlir/TableGen/Predicate.h"
#include "mlir/TableGen/Type.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/CommandLine.h"
@ -88,7 +89,7 @@ private:
void Pattern::emitAttributeValue(Record *constAttr) {
Record *attr = constAttr->getValueAsDef("attr");
auto value = constAttr->getValue("value");
Record *type = attr->getValueAsDef("type");
tblgen::Type type(attr->getValueAsDef("type"));
auto storageType = attr->getValueAsString("storageType").trim();
// For attributes stored as strings we do not need to query builder etc.
@ -98,20 +99,15 @@ void Pattern::emitAttributeValue(Record *constAttr) {
return;
}
// Construct the attribute based on storage type and builder.
if (auto b = type->getValue("builderCall")) {
if (isa<UnsetInit>(b->getValue()))
PrintFatalError(pattern->getLoc(),
"no builder specified for " + type->getName());
CodeInit *builder = cast<CodeInit>(b->getValue());
// TODO(jpienaar): Verify the constants here
os << formatv("{0}::get(rewriter.{1}, {2})", storageType,
builder->getValue(),
value->getValue()->getAsUnquotedString());
return;
}
auto builder = type.getBuilderCall();
if (builder.empty())
PrintFatalError(pattern->getLoc(),
"no builder specified for " + type.getTableGenDefName());
PrintFatalError(pattern->getLoc(), "unable to emit attribute");
// Construct the attribute based on storage type and builder.
// TODO(jpienaar): Verify the constants here
os << formatv("{0}::get(rewriter.{1}, {2})", storageType, builder,
value->getValue()->getAsUnquotedString());
}
void Pattern::collectBoundArguments(DagInit *tree) {
@ -174,12 +170,8 @@ static void matchOp(Record *pattern, DagInit *tree, int depth,
PrintFatalError(pattern->getLoc(),
"type argument required for operand");
// TODO(jpienaar): Factor out type class and move these there.
auto predicate = defInit->getDef()->getValue("predicate")->getValue();
auto predCnf = cast<DefInit>(predicate);
auto conjunctiveList =
predCnf->getDef()->getValueAsListInit("conditions");
PredCNF pred(conjunctiveList);
auto pred = tblgen::Type(defInit).getPredicate();
os.indent(indent)
<< "if (!("
<< formatv(pred.createTypeMatcherTemplate().c_str(),