[fir][NFC] Update and move fir.freemem and fir.store

Move fir.freemem and fir.store to the Memory SSA operations sections.
Move parser, printer and verifier of fir.store to the .cpp file.

This patch is part of the upstreaming effort from fir-dev branch.

Co-authored-by: Jean Perier <jperier@nvidia.com>
Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D110816
This commit is contained in:
Valentin Clement 2021-09-30 16:25:21 +02:00
parent 93a6b49d38
commit ccc0f62d1b
No known key found for this signature in database
GPG Key ID: 086D54783C928776
2 changed files with 89 additions and 89 deletions

View File

@ -376,6 +376,28 @@ def fir_AllocMemOp : fir_Op<"allocmem",
}];
}
def fir_FreeMemOp : fir_Op<"freemem", [MemoryEffects<[MemFree]>]> {
let summary = "free a heap object";
let description = [{
Deallocates a heap memory reference that was allocated by an `allocmem`.
The memory object that is deallocated is placed in an undefined state
after `fir.freemem`. Optimizations may treat the loading of an object
in the undefined state as undefined behavior. This includes aliasing
references, such as the result of an `fir.embox`.
```mlir
%21 = fir.allocmem !fir.type<ZT(p:i32){field:i32}>
...
fir.freemem %21 : !fir.heap<!fir.type<ZT>>
```
}];
let arguments = (ins Arg<fir_HeapType, "", [MemFree]>:$heapref);
let assemblyFormat = "$heapref attr-dict `:` type($heapref)";
}
def fir_LoadOp : fir_OneResultOp<"load"> {
let summary = "load a value from a memory reference";
let description = [{
@ -405,6 +427,39 @@ def fir_LoadOp : fir_OneResultOp<"load"> {
}];
}
def fir_StoreOp : fir_Op<"store", []> {
let summary = "store an SSA-value to a memory location";
let description = [{
Store an ssa-value (virtual register) to a memory reference. The stored
value must be of the same type as the referent type of the memory
reference.
```mlir
%v = ... : f64
%p = ... : !fir.ptr<f64>
fir.store %v to %p : !fir.ptr<f64>
```
The above store changes the value to which the pointer is pointing and not
the pointer itself. The operation is undefined if the memory reference,
`%p`, is undefined or null.
}];
let arguments = (ins AnyType:$value,
Arg<AnyReferenceLike, "", [MemWrite]>:$memref);
let parser = "return parseStoreOp(parser, result);";
let printer = "::print(p, *this);";
let verifier = "return ::verify(*this);";
let extraClassDeclaration = [{
static mlir::Type elementType(mlir::Type refType);
}];
}
def fir_SaveResultOp : fir_Op<"save_result", [AttrSizedOperandSegments]> {
let summary = [{
save an array, box, or record function result SSA-value to a memory location
@ -454,66 +509,6 @@ def fir_SaveResultOp : fir_Op<"save_result", [AttrSizedOperandSegments]> {
let verifier = [{ return ::verify(*this); }];
}
def fir_StoreOp : fir_Op<"store", []> {
let summary = "store an SSA-value to a memory location";
let description = [{
Store an ssa-value (virtual register) to a memory reference. The stored
value must be of the same type as the referent type of the memory
reference.
```mlir
%v = ... : f64
%p = ... : !fir.ptr<f64>
fir.store %v to %p : !fir.ptr<f64>
```
The above store changes the value to which the pointer is pointing and not
the pointer itself. The operation is undefined if the memory reference,
`%p`, is undefined or null.
}];
let arguments = (ins AnyType:$value,
Arg<AnyReferenceLike, "", [MemWrite]>:$memref);
let parser = [{
mlir::Type type;
mlir::OpAsmParser::OperandType oper;
mlir::OpAsmParser::OperandType store;
if (parser.parseOperand(oper) ||
parser.parseKeyword("to") ||
parser.parseOperand(store) ||
parser.parseOptionalAttrDict(result.attributes) ||
parser.parseColonType(type) ||
parser.resolveOperand(oper, elementType(type),
result.operands) ||
parser.resolveOperand(store, type, result.operands))
return mlir::failure();
return mlir::success();
}];
let printer = [{
p << ' ';
p.printOperand(value());
p << " to ";
p.printOperand(memref());
p.printOptionalAttrDict((*this)->getAttrs(), {});
p << " : " << memref().getType();
}];
let verifier = [{
if (value().getType() != fir::dyn_cast_ptrEleTy(memref().getType()))
return emitOpError("store value type must match memory reference type");
if (fir::isa_unknown_size_box(value().getType()))
return emitOpError("cannot store !fir.box of unknown rank or type");
return mlir::success();
}];
let extraClassDeclaration = [{
static mlir::Type elementType(mlir::Type refType);
}];
}
def fir_UndefOp : fir_OneResultOp<"undefined", [NoSideEffect]> {
let summary = "explicit undefined value of some type";
let description = [{
@ -557,28 +552,6 @@ def fir_ZeroOp : fir_OneResultOp<"zero_bits", [NoSideEffect]> {
let assemblyFormat = "type($intype) attr-dict";
}
def fir_FreeMemOp : fir_Op<"freemem", [MemoryEffects<[MemFree]>]> {
let summary = "free a heap object";
let description = [{
Deallocates a heap memory reference that was allocated by an `allocmem`.
The memory object that is deallocated is placed in an undefined state
after `fir.freemem`. Optimizations may treat the loading of an object
in the undefined state as undefined behavior. This includes aliasing
references, such as the result of an `fir.embox`.
```mlir
%21 = fir.allocmem !fir.type<ZT(p:i32){field:i32}>
...
fir.freemem %21 : !fir.heap<!fir.type<ZT>>
```
}];
let arguments = (ins Arg<fir_HeapType, "", [MemFree]>:$heapref);
let assemblyFormat = "$heapref attr-dict `:` type($heapref)";
}
//===----------------------------------------------------------------------===//
// Terminator operations
//===----------------------------------------------------------------------===//

View File

@ -2673,13 +2673,40 @@ static mlir::LogicalResult verify(fir::SliceOp &op) {
//===----------------------------------------------------------------------===//
mlir::Type fir::StoreOp::elementType(mlir::Type refType) {
if (auto ref = refType.dyn_cast<ReferenceType>())
return ref.getEleTy();
if (auto ref = refType.dyn_cast<PointerType>())
return ref.getEleTy();
if (auto ref = refType.dyn_cast<HeapType>())
return ref.getEleTy();
return {};
return fir::dyn_cast_ptrEleTy(refType);
}
static mlir::ParseResult parseStoreOp(mlir::OpAsmParser &parser,
mlir::OperationState &result) {
mlir::Type type;
mlir::OpAsmParser::OperandType oper;
mlir::OpAsmParser::OperandType store;
if (parser.parseOperand(oper) || parser.parseKeyword("to") ||
parser.parseOperand(store) ||
parser.parseOptionalAttrDict(result.attributes) ||
parser.parseColonType(type) ||
parser.resolveOperand(oper, fir::StoreOp::elementType(type),
result.operands) ||
parser.resolveOperand(store, type, result.operands))
return mlir::failure();
return mlir::success();
}
static void print(mlir::OpAsmPrinter &p, fir::StoreOp &op) {
p << ' ';
p.printOperand(op.value());
p << " to ";
p.printOperand(op.memref());
p.printOptionalAttrDict(op.getOperation()->getAttrs(), {});
p << " : " << op.memref().getType();
}
static mlir::LogicalResult verify(fir::StoreOp &op) {
if (op.value().getType() != fir::dyn_cast_ptrEleTy(op.memref().getType()))
return op.emitOpError("store value type must match memory reference type");
if (fir::isa_unknown_size_box(op.value().getType()))
return op.emitOpError("cannot store !fir.box of unknown rank or type");
return mlir::success();
}
//===----------------------------------------------------------------------===//