llvm-project/mlir/lib/TableGen/Attribute.cpp

171 lines
5.3 KiB
C++
Raw Normal View History

//===- Attribute.cpp - Attribute wrapper 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.
// =============================================================================
//
// Attribute wrapper to simplify using TableGen Record defining a MLIR
// Attribute.
//
//===----------------------------------------------------------------------===//
#include "mlir/TableGen/Format.h"
#include "mlir/TableGen/Operator.h"
#include "llvm/TableGen/Record.h"
using namespace mlir;
using llvm::CodeInit;
using llvm::DefInit;
using llvm::Init;
using llvm::Record;
using llvm::StringInit;
// Returns the initializer's value as string if the given TableGen initializer
// is a code or string initializer. Returns the empty StringRef otherwise.
static StringRef getValueAsString(const Init *init) {
if (const auto *code = dyn_cast<CodeInit>(init))
return code->getValue().trim();
else if (const auto *str = dyn_cast<StringInit>(init))
return str->getValue().trim();
return {};
}
tblgen::AttrConstraint::AttrConstraint(const Record *record)
: Constraint(Constraint::CK_Attr, record) {
assert(def->isSubClassOf("AttrConstraint") &&
"must be subclass of TableGen 'AttrConstraint' class");
}
tblgen::Attribute::Attribute(const Record *record) : AttrConstraint(record) {
assert(record->isSubClassOf("Attr") &&
"must be subclass of TableGen 'Attr' class");
}
tblgen::Attribute::Attribute(const DefInit *init) : Attribute(init->getDef()) {}
bool tblgen::Attribute::isDerivedAttr() const {
return def->isSubClassOf("DerivedAttr");
}
bool tblgen::Attribute::isTypeAttr() const {
return def->isSubClassOf("TypeAttrBase");
}
bool tblgen::Attribute::hasStorageType() const {
const auto *init = def->getValueInit("storageType");
return !getValueAsString(init).empty();
}
StringRef tblgen::Attribute::getStorageType() const {
const auto *init = def->getValueInit("storageType");
auto type = getValueAsString(init);
if (type.empty())
return "Attribute";
return type;
}
StringRef tblgen::Attribute::getReturnType() const {
const auto *init = def->getValueInit("returnType");
return getValueAsString(init);
}
StringRef tblgen::Attribute::getConvertFromStorageCall() const {
const auto *init = def->getValueInit("convertFromStorage");
return getValueAsString(init);
}
bool tblgen::Attribute::isConstBuildable() const {
const auto *init = def->getValueInit("constBuilderCall");
return !getValueAsString(init).empty();
}
StringRef tblgen::Attribute::getConstBuilderTemplate() const {
const auto *init = def->getValueInit("constBuilderCall");
return getValueAsString(init);
}
bool tblgen::Attribute::hasDefaultValueInitializer() const {
const auto *init = def->getValueInit("defaultValue");
return !getValueAsString(init).empty();
}
StringRef tblgen::Attribute::getDefaultValueInitializer() const {
const auto *init = def->getValueInit("defaultValue");
return getValueAsString(init);
Spike to define real math ops and lowering of one variant of add to corresponding integer ops. The only reason in starting with a fixedpoint add is that it is the absolute simplest variant and illustrates the level of abstraction I'm aiming for. The overall flow would be: 1. Determine quantization parameters (out of scope of this cl). 2. Source dialect rules to lower supported math ops to the quantization dialect (out of scope of this cl). 3. Quantization passes: [-quant-convert-const, -quant-lower-uniform-real-math, -quant-lower-unsupported-to-float] (the last one not implemented yet) 4. Target specific lowering of the integral arithmetic ops (roughly at the level of gemmlowp) to more fundamental operations (i.e. calls to gemmlowp, simd instructions, DSP instructions, etc). How I'm doing this should facilitate implementation of just about any kind of backend except TFLite, which has a very course, adhoc surface area for its quantized kernels. Options there include (I'm not taking an opinion on this - just trying to provide options): a) Not using any of this: just match q/dbarrier + tf math ops to the supported TFLite quantized op set. b) Implement the more fundamental integer math ops on TFLite and convert to those instead of the current op set. Note that I've hand-waved over the process of choosing appropriate quantization parameters. Getting to that next. As you can see, different implementations will likely have different magic combinations of specific math support, and we will need the target system that has been discussed for some of the esoteric cases (i.e. many DSPs only support POT fixedpoint). Two unrelated changes to the overall goal of this CL and can be broken out of desired: - Adding optional attribute support to TabelGen - Allowing TableGen native rewrite hooks to return nullptr, signalling that no rewrite has been done. PiperOrigin-RevId: 235267229
2019-02-23 07:11:00 +08:00
}
bool tblgen::Attribute::isOptional() const {
return def->getValueAsBit("isOptional");
}
StringRef tblgen::Attribute::getAttrDefName() const {
if (def->isAnonymous() && (isOptional() || hasDefaultValueInitializer()))
return getValueAsString(def->getValueInit("baseAttr"));
return def->getName();
}
StringRef tblgen::Attribute::getDerivedCodeBody() const {
assert(isDerivedAttr() && "only derived attribute has 'body' field");
return def->getValueAsString("body");
}
tblgen::ConstantAttr::ConstantAttr(const DefInit *init) : def(init->getDef()) {
assert(def->isSubClassOf("ConstantAttr") &&
"must be subclass of TableGen 'ConstantAttr' class");
}
tblgen::Attribute tblgen::ConstantAttr::getAttribute() const {
return Attribute(def->getValueAsDef("attr"));
}
StringRef tblgen::ConstantAttr::getConstantValue() const {
return def->getValueAsString("value");
}
tblgen::EnumAttrCase::EnumAttrCase(const llvm::DefInit *init)
: Attribute(init) {
assert(def->isSubClassOf("EnumAttrCase") &&
"must be subclass of TableGen 'EnumAttrCase' class");
}
StringRef tblgen::EnumAttrCase::getSymbol() const {
return def->getValueAsString("symbol");
}
tblgen::EnumAttr::EnumAttr(const llvm::Record *record) : Attribute(record) {
assert(def->isSubClassOf("EnumAttr") &&
"must be subclass of TableGen 'EnumAttr' class");
}
tblgen::EnumAttr::EnumAttr(const llvm::DefInit *init)
: EnumAttr(init->getDef()) {}
StringRef tblgen::EnumAttr::getEnumClassName() const {
return def->getValueAsString("className");
}
std::vector<tblgen::EnumAttrCase> tblgen::EnumAttr::getAllCases() const {
const auto *inits = def->getValueAsListInit("enumerants");
std::vector<tblgen::EnumAttrCase> cases;
cases.reserve(inits->size());
for (const llvm::Init *init : *inits) {
cases.push_back(tblgen::EnumAttrCase(cast<llvm::DefInit>(init)));
}
return cases;
}