Make GlobalOp's value attribute optional.

Make GlobalOp's value attribute an OptionalAttr. Change code that uses the value to handle 'nullopt'. Translate an unitialized value attribute to llvm::UndefValue.

PiperOrigin-RevId: 270423646
This commit is contained in:
Christian Sigg 2019-09-21 01:19:43 -07:00 committed by A. Unique TensorFlower
parent 3a643de92b
commit 33a3a91ba2
5 changed files with 34 additions and 19 deletions

View File

@ -487,7 +487,7 @@ def LLVM_AddressOfOp
def LLVM_GlobalOp
: LLVM_ZeroResultOp<"mlir.global">,
Arguments<(ins TypeAttr:$type, UnitAttr:$constant, StrAttr:$sym_name,
AnyAttr:$value,
OptionalAttr<AnyAttr>:$value,
DefaultValuedAttr<NonNegativeI32Attr, "0">:$addr_space)> {
let builders = [
@ -501,6 +501,10 @@ def LLVM_GlobalOp
LLVMType getType() {
return type().cast<LLVMType>();
}
/// Return the value attribute if it exists, or a null attribute.
Attribute getValueOrNull() {
return value().getValueOr(Attribute());
}
}];
let printer = "printGlobalOp(p, *this);";

View File

@ -881,20 +881,21 @@ static void printGlobalOp(OpAsmPrinter &p, GlobalOp op) {
if (op.constant())
p << "constant ";
p << '@' << op.sym_name() << '(';
p.printAttribute(op.value());
if (auto value = op.getValueOrNull())
p.printAttribute(value);
p << ')';
p.printOptionalAttrDict(op.getAttrs(), {SymbolTable::getSymbolAttrName(),
"type", "constant", "value"});
// Print the trailing type unless it's a string global.
if (op.value().isa<StringAttr>())
if (op.getValueOrNull().dyn_cast_or_null<StringAttr>())
return;
p << " : ";
p.printType(op.type());
}
// <operation> ::= `llvm.mlir.global` `constant`? `@` identifier
// `(` attribute `)` attribute-list? (`:` type)?
// `(` attribute? `)` attribute-list? (`:` type)?
//
// The type can be omitted for string attributes, in which case it will be
// inferred from the value of the string as [strlen(value) x i8].
@ -902,15 +903,21 @@ static ParseResult parseGlobalOp(OpAsmParser &parser, OperationState &result) {
if (succeeded(parser.parseOptionalKeyword("constant")))
result.addAttribute("constant", parser.getBuilder().getUnitAttr());
Attribute value;
StringAttr name;
SmallVector<Type, 1> types;
if (parser.parseSymbolName(name, SymbolTable::getSymbolAttrName(),
result.attributes) ||
parser.parseLParen() ||
parser.parseAttribute(value, "value", result.attributes) ||
parser.parseRParen() ||
parser.parseOptionalAttributeDict(result.attributes) ||
parser.parseLParen())
return failure();
Attribute value;
if (parser.parseOptionalRParen()) {
if (parser.parseAttribute(value, "value", result.attributes) ||
parser.parseRParen())
return failure();
}
SmallVector<Type, 1> types;
if (parser.parseOptionalAttributeDict(result.attributes) ||
parser.parseOptionalColonTypeList(types))
return failure();
@ -918,7 +925,7 @@ static ParseResult parseGlobalOp(OpAsmParser &parser, OperationState &result) {
return parser.emitError(parser.getNameLoc(), "expected zero or one type");
if (types.empty()) {
if (auto strAttr = value.dyn_cast<StringAttr>()) {
if (auto strAttr = value.dyn_cast_or_null<StringAttr>()) {
MLIRContext *context = parser.getBuilder().getContext();
auto *dialect = context->getRegisteredDialect<LLVMDialect>();
auto arrayType = LLVM::LLVMType::getArrayTy(
@ -940,7 +947,8 @@ static LogicalResult verify(GlobalOp op) {
"expects type to be a valid element type for an LLVM pointer");
if (op.getParentOp() && !isa<ModuleOp>(op.getParentOp()))
return op.emitOpError("must appear at the module level");
if (auto strAttr = op.value().dyn_cast<StringAttr>()) {
if (auto strAttr = op.getValueOrNull().dyn_cast_or_null<StringAttr>()) {
auto type = op.getType();
if (!type.getUnderlyingType()->isArrayTy() ||
!type.getArrayElementType().getUnderlyingType()->isIntegerTy(8) ||

View File

@ -78,6 +78,8 @@ static llvm::FunctionType *convertFunctionType(llvm::LLVMContext &llvmContext,
llvm::Constant *ModuleTranslation::getLLVMConstant(llvm::Type *llvmType,
Attribute attr,
Location loc) {
if (!attr)
return llvm::UndefValue::get(llvmType);
if (auto intAttr = attr.dyn_cast<IntegerAttr>())
return llvm::ConstantInt::get(llvmType, intAttr.getValue());
if (auto floatAttr = attr.dyn_cast<FloatAttr>())
@ -317,13 +319,13 @@ void ModuleTranslation::convertGlobals() {
llvm::Type *type;
// String attributes are treated separately because they cannot appear as
// in-function constants and are thus not supported by getLLVMConstant.
if (auto strAttr = op.value().dyn_cast<StringAttr>()) {
if (auto strAttr = op.getValueOrNull().dyn_cast_or_null<StringAttr>()) {
cst = llvm::ConstantDataArray::getString(
llvmModule->getContext(), strAttr.getValue(), /*AddNull=*/false);
type = cst->getType();
} else {
type = op.getType().getUnderlyingType();
cst = getLLVMConstant(type, op.value(), op.getLoc());
cst = getLLVMConstant(type, op.getValueOrNull(), op.getLoc());
}
auto addrSpace = op.addr_space().getLimitedValue();

View File

@ -12,6 +12,9 @@ llvm.mlir.global constant @string("foobar") : !llvm<"[6 x i8]">
// CHECK: llvm.mlir.global @string_notype("1234567")
llvm.mlir.global @string_notype("1234567")
// CHECK: llvm.mlir.global @global_undef()
llvm.mlir.global @global_undef() : !llvm.i64
// CHECK-LABEL: references
func @references() {
// CHECK: llvm.mlir.addressof @global : !llvm<"i64*">
@ -35,11 +38,6 @@ func @references() {
// -----
// expected-error @+1 {{op requires attribute 'value'}}
"llvm.mlir.global"() {sym_name = "foo", type = !llvm.i64, constant} : () -> ()
// -----
// expected-error @+1 {{expects type to be a valid element type for an LLVM pointer}}
llvm.mlir.global constant @constant(37.0) : !llvm<"label">

View File

@ -21,6 +21,9 @@ llvm.mlir.global @float_global_array(dense<[-5.0]> : vector<1xf32>) : !llvm<"[1
// CHECK: @string_const = internal constant [6 x i8] c"foobar"
llvm.mlir.global constant @string_const("foobar") : !llvm<"[6 x i8]">
// CHECK: @int_global_undef = internal global i64 undef
llvm.mlir.global @int_global_undef() : !llvm.i64
//
// Declarations of the allocation functions to be linked against.
//