[mlir][NFC] Update OpenACC/OpenMP operations to use `hasVerifier` instead of `verifier`

The verifier field is deprecated, and slated for removal.

Differential Revision: https://reviews.llvm.org/D118825
This commit is contained in:
River Riddle 2022-02-02 10:22:57 -08:00
parent b98dc0351a
commit ef72cf4413
5 changed files with 171 additions and 186 deletions

View File

@ -37,7 +37,6 @@ class OpenACC_Op<string mnemonic, list<Trait> traits = []> :
Op<OpenACC_Dialect, mnemonic, traits> {
let printer = [{ return ::print(p, *this); }];
let verifier = [{ return ::verify(*this); }];
let parser = [{ return ::parse$cppClass(parser, result); }];
}
@ -153,8 +152,6 @@ def OpenACC_ParallelOp : OpenACC_Op<"parallel",
/// The i-th data operand passed.
Value getDataOperand(unsigned i);
}];
let verifier = ?;
}
//===----------------------------------------------------------------------===//
@ -225,6 +222,7 @@ def OpenACC_DataOp : OpenACC_Op<"data",
( `attach` `(` $attachOperands^ `:` type($attachOperands) `)` )?
$region attr-dict-with-keyword
}];
let hasVerifier = 1;
}
def OpenACC_TerminatorOp : OpenACC_Op<"terminator", [Terminator]> {
@ -237,8 +235,6 @@ def OpenACC_TerminatorOp : OpenACC_Op<"terminator", [Terminator]> {
to the enclosing op.
}];
let verifier = ?;
let assemblyFormat = "attr-dict";
}
@ -292,6 +288,7 @@ def OpenACC_EnterDataOp : OpenACC_Op<"enter_data", [AttrSizedOperandSegments]> {
}];
let hasCanonicalizer = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -342,6 +339,7 @@ def OpenACC_ExitDataOp : OpenACC_Op<"exit_data", [AttrSizedOperandSegments]> {
}];
let hasCanonicalizer = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -406,8 +404,7 @@ def OpenACC_LoopOp : OpenACC_Op<"loop",
static StringRef getPrivateKeyword() { return "private"; }
static StringRef getReductionKeyword() { return "reduction"; }
}];
let verifier = [{ return ::verifyLoopOp(*this); }];
let hasVerifier = 1;
}
// Yield operation for the acc.loop and acc.parallel operations.
@ -425,8 +422,6 @@ def OpenACC_YieldOp : OpenACC_Op<"yield", [Terminator,
let builders = [OpBuilder<(ins), [{ /* nothing to do */ }]>];
let verifier = ?;
let assemblyFormat = "attr-dict ($operands^ `:` type($operands))?";
}
@ -458,6 +453,7 @@ def OpenACC_InitOp : OpenACC_Op<"init", [AttrSizedOperandSegments]> {
( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
}];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -488,6 +484,7 @@ def OpenACC_ShutdownOp : OpenACC_Op<"shutdown", [AttrSizedOperandSegments]> {
( `device_num` `(` $deviceNumOperand^ `:` type($deviceNumOperand) `)` )?
( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
}];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -542,6 +539,7 @@ def OpenACC_UpdateOp : OpenACC_Op<"update", [AttrSizedOperandSegments]> {
}];
let hasCanonicalizer = 1;
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -575,6 +573,7 @@ def OpenACC_WaitOp : OpenACC_Op<"wait", [AttrSizedOperandSegments]> {
( `wait_devnum` `(` $waitDevnum^ `:` type($waitDevnum) `)` )?
( `if` `(` $ifCond^ `)` )? attr-dict-with-keyword
}];
let hasVerifier = 1;
}
#endif // OPENACC_OPS

View File

@ -128,7 +128,7 @@ def ParallelOp : OpenMP_Op<"parallel", [AttrSizedOperandSegments,
];
let parser = [{ return parseParallelOp(parser, result); }];
let printer = [{ return printParallelOp(p, *this); }];
let verifier = [{ return ::verifyParallelOp(*this); }];
let hasVerifier = 1;
}
def TerminatorOp : OpenMP_Op<"terminator", [Terminator]> {
@ -217,7 +217,7 @@ def SectionsOp : OpenMP_Op<"sections", [AttrSizedOperandSegments]> {
let parser = [{ return parseSectionsOp(parser, result); }];
let printer = [{ return printSectionsOp(p, *this); }];
let verifier = [{ return verifySectionsOp(*this); }];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -336,7 +336,7 @@ def WsLoopOp : OpenMP_Op<"wsloop", [AttrSizedOperandSegments,
}];
let parser = [{ return parseWsLoopOp(parser, result); }];
let printer = [{ return printWsLoopOp(p, *this); }];
let verifier = [{ return ::verifyWsLoopOp(*this); }];
let hasVerifier = 1;
}
def YieldOp : OpenMP_Op<"yield",
@ -457,8 +457,7 @@ def CriticalDeclareOp : OpenMP_Op<"critical.declare", [Symbol]> {
let assemblyFormat = [{
$sym_name custom<SynchronizationHint>($hint) attr-dict
}];
let verifier = "return verifyCriticalDeclareOp(*this);";
let hasVerifier = 1;
}
@ -476,8 +475,7 @@ def CriticalOp : OpenMP_Op<"critical"> {
let assemblyFormat = [{
(`(` $name^ `)`)? $region attr-dict
}];
let verifier = "return ::verifyCriticalOp(*this);";
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -540,8 +538,7 @@ def OrderedOp : OpenMP_Op<"ordered"> {
( `depend_vec` `(` $depend_vec_vars^ `:` type($depend_vec_vars) `)` )?
attr-dict
}];
let verifier = "return ::verifyOrderedOp(*this);";
let hasVerifier = 1;
}
def OrderedRegionOp : OpenMP_Op<"ordered_region"> {
@ -561,8 +558,7 @@ def OrderedRegionOp : OpenMP_Op<"ordered_region"> {
let regions = (region AnyRegion:$region);
let assemblyFormat = [{ ( `simd` $simd^ )? $region attr-dict}];
let verifier = "return ::verifyOrderedRegionOp(*this);";
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -614,7 +610,7 @@ def AtomicReadOp : OpenMP_Op<"atomic.read"> {
OptionalAttr<MemoryOrderKindAttr>:$memory_order);
let parser = [{ return parseAtomicReadOp(parser, result); }];
let printer = [{ return printAtomicReadOp(p, *this); }];
let verifier = [{ return verifyAtomicReadOp(*this); }];
let hasVerifier = 1;
}
def AtomicWriteOp : OpenMP_Op<"atomic.write"> {
@ -643,7 +639,7 @@ def AtomicWriteOp : OpenMP_Op<"atomic.write"> {
OptionalAttr<MemoryOrderKindAttr>:$memory_order);
let parser = [{ return parseAtomicWriteOp(parser, result); }];
let printer = [{ return printAtomicWriteOp(p, *this); }];
let verifier = [{ return verifyAtomicWriteOp(*this); }];
let hasVerifier = 1;
}
// TODO: autogenerate from OMP.td in future if possible.
@ -708,7 +704,7 @@ def AtomicUpdateOp : OpenMP_Op<"atomic.update"> {
OptionalAttr<MemoryOrderKindAttr>:$memory_order);
let parser = [{ return parseAtomicUpdateOp(parser, result); }];
let printer = [{ return printAtomicUpdateOp(p, *this); }];
let verifier = [{ return verifyAtomicUpdateOp(*this); }];
let hasVerifier = 1;
}
def AtomicCaptureOp : OpenMP_Op<"atomic.capture",
@ -752,7 +748,7 @@ def AtomicCaptureOp : OpenMP_Op<"atomic.capture",
let regions = (region SizedRegion<1>:$region);
let parser = [{ return parseAtomicCaptureOp(parser, result); }];
let printer = [{ return printAtomicCaptureOp(p, *this); }];
let verifier = [{ return verifyAtomicCaptureOp(*this); }];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -789,7 +785,6 @@ def ReductionDeclareOp : OpenMP_Op<"reduction.declare", [Symbol]> {
let regions = (region AnyRegion:$initializerRegion,
AnyRegion:$reductionRegion,
AnyRegion:$atomicReductionRegion);
let verifier = "return ::verifyReductionDeclareOp(*this);";
let assemblyFormat = "$sym_name `:` $type attr-dict-with-keyword "
"`init` $initializerRegion "
@ -804,6 +799,7 @@ def ReductionDeclareOp : OpenMP_Op<"reduction.declare", [Symbol]> {
return atomicReductionRegion().front().getArgument(0).getType();
}
}];
let hasVerifier = 1;
}
//===----------------------------------------------------------------------===//
@ -826,7 +822,7 @@ def ReductionOp : OpenMP_Op<"reduction", [
let arguments= (ins AnyType:$operand, OpenMP_PointerLikeType:$accumulator);
let assemblyFormat =
"$operand `,` $accumulator attr-dict `:` type($accumulator)";
let verifier = "return ::verifyReductionOp(*this);";
let hasVerifier = 1;
}
#endif // OPENMP_OPS

View File

@ -668,28 +668,22 @@ static void print(OpAsmPrinter &printer, LoopOp &op) {
LoopOp::getOperandSegmentSizeAttr()});
}
static LogicalResult verifyLoopOp(acc::LoopOp loopOp) {
LogicalResult acc::LoopOp::verify() {
// auto, independent and seq attribute are mutually exclusive.
if ((loopOp.auto_() && (loopOp.independent() || loopOp.seq())) ||
(loopOp.independent() && loopOp.seq())) {
loopOp.emitError("only one of " + acc::LoopOp::getAutoAttrName() + ", " +
if ((auto_() && (independent() || seq())) || (independent() && seq())) {
return emitError("only one of " + acc::LoopOp::getAutoAttrName() + ", " +
acc::LoopOp::getIndependentAttrName() + ", " +
acc::LoopOp::getSeqAttrName() +
" can be present at the same time");
return failure();
}
// Gang, worker and vector are incompatible with seq.
if (loopOp.seq() && loopOp.exec_mapping() != OpenACCExecMapping::NONE) {
loopOp.emitError("gang, worker or vector cannot appear with the seq attr");
return failure();
}
if (seq() && exec_mapping() != OpenACCExecMapping::NONE)
return emitError("gang, worker or vector cannot appear with the seq attr");
// Check non-empty body().
if (loopOp.region().empty()) {
loopOp.emitError("expected non-empty body.");
return failure();
}
if (region().empty())
return emitError("expected non-empty body.");
return success();
}
@ -698,13 +692,13 @@ static LogicalResult verifyLoopOp(acc::LoopOp loopOp) {
// DataOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::DataOp dataOp) {
LogicalResult acc::DataOp::verify() {
// 2.6.5. Data Construct restriction
// At least one copy, copyin, copyout, create, no_create, present, deviceptr,
// attach, or default clause must appear on a data construct.
if (dataOp.getOperands().empty() && !dataOp.defaultAttr())
return dataOp.emitError("at least one operand or the default attribute "
"must appear on the data operation");
if (getOperands().empty() && !defaultAttr())
return emitError("at least one operand or the default attribute "
"must appear on the data operation");
return success();
}
@ -726,28 +720,28 @@ Value DataOp::getDataOperand(unsigned i) {
// ExitDataOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::ExitDataOp op) {
LogicalResult acc::ExitDataOp::verify() {
// 2.6.6. Data Exit Directive restriction
// At least one copyout, delete, or detach clause must appear on an exit data
// directive.
if (op.copyoutOperands().empty() && op.deleteOperands().empty() &&
op.detachOperands().empty())
return op.emitError(
if (copyoutOperands().empty() && deleteOperands().empty() &&
detachOperands().empty())
return emitError(
"at least one operand in copyout, delete or detach must appear on the "
"exit data operation");
// The async attribute represent the async clause without value. Therefore the
// attribute and operand cannot appear at the same time.
if (op.asyncOperand() && op.async())
return op.emitError("async attribute cannot appear with asyncOperand");
if (asyncOperand() && async())
return emitError("async attribute cannot appear with asyncOperand");
// The wait attribute represent the wait clause without values. Therefore the
// attribute and operands cannot appear at the same time.
if (!op.waitOperands().empty() && op.wait())
return op.emitError("wait attribute cannot appear with waitOperands");
if (!waitOperands().empty() && wait())
return emitError("wait attribute cannot appear with waitOperands");
if (op.waitDevnum() && op.waitOperands().empty())
return op.emitError("wait_devnum cannot appear without waitOperands");
if (waitDevnum() && waitOperands().empty())
return emitError("wait_devnum cannot appear without waitOperands");
return success();
}
@ -773,28 +767,28 @@ void ExitDataOp::getCanonicalizationPatterns(RewritePatternSet &results,
// EnterDataOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::EnterDataOp op) {
LogicalResult acc::EnterDataOp::verify() {
// 2.6.6. Data Enter Directive restriction
// At least one copyin, create, or attach clause must appear on an enter data
// directive.
if (op.copyinOperands().empty() && op.createOperands().empty() &&
op.createZeroOperands().empty() && op.attachOperands().empty())
return op.emitError(
if (copyinOperands().empty() && createOperands().empty() &&
createZeroOperands().empty() && attachOperands().empty())
return emitError(
"at least one operand in copyin, create, "
"create_zero or attach must appear on the enter data operation");
// The async attribute represent the async clause without value. Therefore the
// attribute and operand cannot appear at the same time.
if (op.asyncOperand() && op.async())
return op.emitError("async attribute cannot appear with asyncOperand");
if (asyncOperand() && async())
return emitError("async attribute cannot appear with asyncOperand");
// The wait attribute represent the wait clause without values. Therefore the
// attribute and operands cannot appear at the same time.
if (!op.waitOperands().empty() && op.wait())
return op.emitError("wait attribute cannot appear with waitOperands");
if (!waitOperands().empty() && wait())
return emitError("wait attribute cannot appear with waitOperands");
if (op.waitDevnum() && op.waitOperands().empty())
return op.emitError("wait_devnum cannot appear without waitOperands");
if (waitDevnum() && waitOperands().empty())
return emitError("wait_devnum cannot appear without waitOperands");
return success();
}
@ -820,12 +814,11 @@ void EnterDataOp::getCanonicalizationPatterns(RewritePatternSet &results,
// InitOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::InitOp initOp) {
Operation *currOp = initOp;
while ((currOp = currOp->getParentOp())) {
LogicalResult acc::InitOp::verify() {
Operation *currOp = *this;
while ((currOp = currOp->getParentOp()))
if (isComputeOperation(currOp))
return initOp.emitOpError("cannot be nested in a compute operation");
}
return emitOpError("cannot be nested in a compute operation");
return success();
}
@ -833,12 +826,11 @@ static LogicalResult verify(acc::InitOp initOp) {
// ShutdownOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::ShutdownOp op) {
Operation *currOp = op;
while ((currOp = currOp->getParentOp())) {
LogicalResult acc::ShutdownOp::verify() {
Operation *currOp = *this;
while ((currOp = currOp->getParentOp()))
if (isComputeOperation(currOp))
return op.emitOpError("cannot be nested in a compute operation");
}
return emitOpError("cannot be nested in a compute operation");
return success();
}
@ -846,25 +838,24 @@ static LogicalResult verify(acc::ShutdownOp op) {
// UpdateOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::UpdateOp updateOp) {
LogicalResult acc::UpdateOp::verify() {
// At least one of host or device should have a value.
if (updateOp.hostOperands().empty() && updateOp.deviceOperands().empty())
return updateOp.emitError("at least one value must be present in"
" hostOperands or deviceOperands");
if (hostOperands().empty() && deviceOperands().empty())
return emitError(
"at least one value must be present in hostOperands or deviceOperands");
// The async attribute represent the async clause without value. Therefore the
// attribute and operand cannot appear at the same time.
if (updateOp.asyncOperand() && updateOp.async())
return updateOp.emitError("async attribute cannot appear with "
" asyncOperand");
if (asyncOperand() && async())
return emitError("async attribute cannot appear with asyncOperand");
// The wait attribute represent the wait clause without values. Therefore the
// attribute and operands cannot appear at the same time.
if (!updateOp.waitOperands().empty() && updateOp.wait())
return updateOp.emitError("wait attribute cannot appear with waitOperands");
if (!waitOperands().empty() && wait())
return emitError("wait attribute cannot appear with waitOperands");
if (updateOp.waitDevnum() && updateOp.waitOperands().empty())
return updateOp.emitError("wait_devnum cannot appear without waitOperands");
if (waitDevnum() && waitOperands().empty())
return emitError("wait_devnum cannot appear without waitOperands");
return success();
}
@ -890,14 +881,14 @@ void UpdateOp::getCanonicalizationPatterns(RewritePatternSet &results,
// WaitOp
//===----------------------------------------------------------------------===//
static LogicalResult verify(acc::WaitOp waitOp) {
LogicalResult acc::WaitOp::verify() {
// The async attribute represent the async clause without value. Therefore the
// attribute and operand cannot appear at the same time.
if (waitOp.asyncOperand() && waitOp.async())
return waitOp.emitError("async attribute cannot appear with asyncOperand");
if (asyncOperand() && async())
return emitError("async attribute cannot appear with asyncOperand");
if (waitOp.waitDevnum() && waitOp.waitOperands().empty())
return waitOp.emitError("wait_devnum cannot appear without waitOperands");
if (waitDevnum() && waitOperands().empty())
return emitError("wait_devnum cannot appear without waitOperands");
return success();
}

View File

@ -165,9 +165,9 @@ static void printAllocateAndAllocator(OpAsmPrinter &p,
}
}
static LogicalResult verifyParallelOp(ParallelOp op) {
if (op.allocate_vars().size() != op.allocators_vars().size())
return op.emitError(
LogicalResult ParallelOp::verify() {
if (allocate_vars().size() != allocators_vars().size())
return emitError(
"expected equal sizes for allocate and allocator variables");
return success();
}
@ -1072,31 +1072,31 @@ static void printSectionsOp(OpAsmPrinter &p, SectionsOp op) {
p.printRegion(op.region());
}
static LogicalResult verifySectionsOp(SectionsOp op) {
LogicalResult SectionsOp::verify() {
// A list item may not appear in more than one clause on the same directive,
// except that it may be specified in both firstprivate and lastprivate
// clauses.
for (auto var : op.private_vars()) {
if (llvm::is_contained(op.firstprivate_vars(), var))
return op.emitOpError()
for (auto var : private_vars()) {
if (llvm::is_contained(firstprivate_vars(), var))
return emitOpError()
<< "operand used in both private and firstprivate clauses";
if (llvm::is_contained(op.lastprivate_vars(), var))
return op.emitOpError()
if (llvm::is_contained(lastprivate_vars(), var))
return emitOpError()
<< "operand used in both private and lastprivate clauses";
}
if (op.allocate_vars().size() != op.allocators_vars().size())
return op.emitError(
if (allocate_vars().size() != allocators_vars().size())
return emitError(
"expected equal sizes for allocate and allocator variables");
for (auto &inst : *op.region().begin()) {
if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst)))
op.emitOpError()
<< "expected omp.section op or terminator op inside region";
for (auto &inst : *region().begin()) {
if (!(isa<SectionOp>(inst) || isa<TerminatorOp>(inst))) {
return emitOpError()
<< "expected omp.section op or terminator op inside region";
}
}
return verifyReductionVarList(op, op.reductions(), op.reduction_vars());
return verifyReductionVarList(*this, reductions(), reduction_vars());
}
/// Parses an OpenMP Workshare Loop operation
@ -1224,65 +1224,65 @@ static void printAtomicReductionRegion(OpAsmPrinter &printer,
printer.printRegion(region);
}
static LogicalResult verifyReductionDeclareOp(ReductionDeclareOp op) {
if (op.initializerRegion().empty())
return op.emitOpError() << "expects non-empty initializer region";
Block &initializerEntryBlock = op.initializerRegion().front();
LogicalResult ReductionDeclareOp::verify() {
if (initializerRegion().empty())
return emitOpError() << "expects non-empty initializer region";
Block &initializerEntryBlock = initializerRegion().front();
if (initializerEntryBlock.getNumArguments() != 1 ||
initializerEntryBlock.getArgument(0).getType() != op.type()) {
return op.emitOpError() << "expects initializer region with one argument "
"of the reduction type";
initializerEntryBlock.getArgument(0).getType() != type()) {
return emitOpError() << "expects initializer region with one argument "
"of the reduction type";
}
for (YieldOp yieldOp : op.initializerRegion().getOps<YieldOp>()) {
for (YieldOp yieldOp : initializerRegion().getOps<YieldOp>()) {
if (yieldOp.results().size() != 1 ||
yieldOp.results().getTypes()[0] != op.type())
return op.emitOpError() << "expects initializer region to yield a value "
"of the reduction type";
yieldOp.results().getTypes()[0] != type())
return emitOpError() << "expects initializer region to yield a value "
"of the reduction type";
}
if (op.reductionRegion().empty())
return op.emitOpError() << "expects non-empty reduction region";
Block &reductionEntryBlock = op.reductionRegion().front();
if (reductionRegion().empty())
return emitOpError() << "expects non-empty reduction region";
Block &reductionEntryBlock = reductionRegion().front();
if (reductionEntryBlock.getNumArguments() != 2 ||
reductionEntryBlock.getArgumentTypes()[0] !=
reductionEntryBlock.getArgumentTypes()[1] ||
reductionEntryBlock.getArgumentTypes()[0] != op.type())
return op.emitOpError() << "expects reduction region with two arguments of "
"the reduction type";
for (YieldOp yieldOp : op.reductionRegion().getOps<YieldOp>()) {
reductionEntryBlock.getArgumentTypes()[0] != type())
return emitOpError() << "expects reduction region with two arguments of "
"the reduction type";
for (YieldOp yieldOp : reductionRegion().getOps<YieldOp>()) {
if (yieldOp.results().size() != 1 ||
yieldOp.results().getTypes()[0] != op.type())
return op.emitOpError() << "expects reduction region to yield a value "
"of the reduction type";
yieldOp.results().getTypes()[0] != type())
return emitOpError() << "expects reduction region to yield a value "
"of the reduction type";
}
if (op.atomicReductionRegion().empty())
if (atomicReductionRegion().empty())
return success();
Block &atomicReductionEntryBlock = op.atomicReductionRegion().front();
Block &atomicReductionEntryBlock = atomicReductionRegion().front();
if (atomicReductionEntryBlock.getNumArguments() != 2 ||
atomicReductionEntryBlock.getArgumentTypes()[0] !=
atomicReductionEntryBlock.getArgumentTypes()[1])
return op.emitOpError() << "expects atomic reduction region with two "
"arguments of the same type";
return emitOpError() << "expects atomic reduction region with two "
"arguments of the same type";
auto ptrType = atomicReductionEntryBlock.getArgumentTypes()[0]
.dyn_cast<PointerLikeType>();
if (!ptrType || ptrType.getElementType() != op.type())
return op.emitOpError() << "expects atomic reduction region arguments to "
"be accumulators containing the reduction type";
if (!ptrType || ptrType.getElementType() != type())
return emitOpError() << "expects atomic reduction region arguments to "
"be accumulators containing the reduction type";
return success();
}
static LogicalResult verifyReductionOp(ReductionOp op) {
LogicalResult ReductionOp::verify() {
// TODO: generalize this to an op interface when there is more than one op
// that supports reductions.
auto container = op->getParentOfType<WsLoopOp>();
auto container = (*this)->getParentOfType<WsLoopOp>();
for (unsigned i = 0, e = container.getNumReductionVars(); i < e; ++i)
if (container.reduction_vars()[i] == op.accumulator())
if (container.reduction_vars()[i] == accumulator())
return success();
return op.emitOpError() << "the accumulator is not used by the parent";
return emitOpError() << "the accumulator is not used by the parent";
}
//===----------------------------------------------------------------------===//
@ -1368,27 +1368,26 @@ void WsLoopOp::build(OpBuilder &builder, OperationState &result,
}
}
static LogicalResult verifyWsLoopOp(WsLoopOp op) {
return verifyReductionVarList(op, op.reductions(), op.reduction_vars());
LogicalResult WsLoopOp::verify() {
return verifyReductionVarList(*this, reductions(), reduction_vars());
}
//===----------------------------------------------------------------------===//
// Verifier for critical construct (2.17.1)
//===----------------------------------------------------------------------===//
static LogicalResult verifyCriticalDeclareOp(CriticalDeclareOp op) {
return verifySynchronizationHint(op, op.hint());
LogicalResult CriticalDeclareOp::verify() {
return verifySynchronizationHint(*this, hint());
}
static LogicalResult verifyCriticalOp(CriticalOp op) {
if (op.nameAttr()) {
auto symbolRef = op.nameAttr().cast<SymbolRefAttr>();
auto decl =
SymbolTable::lookupNearestSymbolFrom<CriticalDeclareOp>(op, symbolRef);
LogicalResult CriticalOp::verify() {
if (nameAttr()) {
SymbolRefAttr symbolRef = nameAttr();
auto decl = SymbolTable::lookupNearestSymbolFrom<CriticalDeclareOp>(
*this, symbolRef);
if (!decl) {
return op.emitOpError() << "expected symbol reference " << symbolRef
<< " to point to a critical declaration";
return emitOpError() << "expected symbol reference " << symbolRef
<< " to point to a critical declaration";
}
}
@ -1399,34 +1398,34 @@ static LogicalResult verifyCriticalOp(CriticalOp op) {
// Verifier for ordered construct
//===----------------------------------------------------------------------===//
static LogicalResult verifyOrderedOp(OrderedOp op) {
auto container = op->getParentOfType<WsLoopOp>();
LogicalResult OrderedOp::verify() {
auto container = (*this)->getParentOfType<WsLoopOp>();
if (!container || !container.ordered_valAttr() ||
container.ordered_valAttr().getInt() == 0)
return op.emitOpError() << "ordered depend directive must be closely "
<< "nested inside a worksharing-loop with ordered "
<< "clause with parameter present";
return emitOpError() << "ordered depend directive must be closely "
<< "nested inside a worksharing-loop with ordered "
<< "clause with parameter present";
if (container.ordered_valAttr().getInt() !=
(int64_t)op.num_loops_val().getValue())
return op.emitOpError() << "number of variables in depend clause does not "
<< "match number of iteration variables in the "
<< "doacross loop";
(int64_t)num_loops_val().getValue())
return emitOpError() << "number of variables in depend clause does not "
<< "match number of iteration variables in the "
<< "doacross loop";
return success();
}
static LogicalResult verifyOrderedRegionOp(OrderedRegionOp op) {
LogicalResult OrderedRegionOp::verify() {
// TODO: The code generation for ordered simd directive is not supported yet.
if (op.simd())
if (simd())
return failure();
if (auto container = op->getParentOfType<WsLoopOp>()) {
if (auto container = (*this)->getParentOfType<WsLoopOp>()) {
if (!container.ordered_valAttr() ||
container.ordered_valAttr().getInt() != 0)
return op.emitOpError() << "ordered region must be closely nested inside "
<< "a worksharing-loop region with an ordered "
<< "clause without parameter present";
return emitOpError() << "ordered region must be closely nested inside "
<< "a worksharing-loop region with an ordered "
<< "clause without parameter present";
}
return success();
@ -1468,18 +1467,18 @@ static void printAtomicReadOp(OpAsmPrinter &p, AtomicReadOp op) {
}
/// Verifier for AtomicReadOp
static LogicalResult verifyAtomicReadOp(AtomicReadOp op) {
if (auto mo = op.memory_order()) {
LogicalResult AtomicReadOp::verify() {
if (auto mo = memory_order()) {
if (*mo == ClauseMemoryOrderKind::acq_rel ||
*mo == ClauseMemoryOrderKind::release) {
return op.emitError(
return emitError(
"memory-order must not be acq_rel or release for atomic reads");
}
}
if (op.x() == op.v())
return op.emitError(
if (x() == v())
return emitError(
"read and write must not be to the same location for atomic reads");
return verifySynchronizationHint(op, op.hint());
return verifySynchronizationHint(*this, hint());
}
//===----------------------------------------------------------------------===//
@ -1521,15 +1520,15 @@ static void printAtomicWriteOp(OpAsmPrinter &p, AtomicWriteOp op) {
}
/// Verifier for AtomicWriteOp
static LogicalResult verifyAtomicWriteOp(AtomicWriteOp op) {
if (auto mo = op.memory_order()) {
LogicalResult AtomicWriteOp::verify() {
if (auto mo = memory_order()) {
if (*mo == ClauseMemoryOrderKind::acq_rel ||
*mo == ClauseMemoryOrderKind::acquire) {
return op.emitError(
return emitError(
"memory-order must not be acq_rel or acquire for atomic writes");
}
}
return verifySynchronizationHint(op, op.hint());
return verifySynchronizationHint(*this, hint());
}
//===----------------------------------------------------------------------===//
@ -1601,11 +1600,11 @@ static void printAtomicUpdateOp(OpAsmPrinter &p, AtomicUpdateOp op) {
}
/// Verifier for AtomicUpdateOp
static LogicalResult verifyAtomicUpdateOp(AtomicUpdateOp op) {
if (auto mo = op.memory_order()) {
LogicalResult AtomicUpdateOp::verify() {
if (auto mo = memory_order()) {
if (*mo == ClauseMemoryOrderKind::acq_rel ||
*mo == ClauseMemoryOrderKind::acquire) {
return op.emitError(
return emitError(
"memory-order must not be acq_rel or acquire for atomic updates");
}
}
@ -1637,10 +1636,10 @@ static void printAtomicCaptureOp(OpAsmPrinter &p, AtomicCaptureOp op) {
}
/// Verifier for AtomicCaptureOp
static LogicalResult verifyAtomicCaptureOp(AtomicCaptureOp op) {
Block::OpListType &ops = op.region().front().getOperations();
LogicalResult AtomicCaptureOp::verify() {
Block::OpListType &ops = region().front().getOperations();
if (ops.size() != 3)
return emitError(op.getLoc())
return emitError()
<< "expected three operations in omp.atomic.capture region (one "
"terminator, and two atomic ops)";
auto &firstOp = ops.front();
@ -1654,21 +1653,21 @@ static LogicalResult verifyAtomicCaptureOp(AtomicCaptureOp op) {
if (!((firstUpdateStmt && secondReadStmt) ||
(firstReadStmt && secondUpdateStmt) ||
(firstReadStmt && secondWriteStmt)))
return emitError(ops.front().getLoc())
return ops.front().emitError()
<< "invalid sequence of operations in the capture region";
if (firstUpdateStmt && secondReadStmt &&
firstUpdateStmt.x() != secondReadStmt.x())
return emitError(firstUpdateStmt.getLoc())
return firstUpdateStmt.emitError()
<< "updated variable in omp.atomic.update must be captured in "
"second operation";
if (firstReadStmt && secondUpdateStmt &&
firstReadStmt.x() != secondUpdateStmt.x())
return emitError(firstReadStmt.getLoc())
return firstReadStmt.emitError()
<< "captured variable in omp.atomic.read must be updated in second "
"operation";
if (firstReadStmt && secondWriteStmt &&
firstReadStmt.x() != secondWriteStmt.address())
return emitError(firstReadStmt.getLoc())
return firstReadStmt.emitError()
<< "captured variable in omp.atomic.read must be updated in "
"second operation";
return success();

View File

@ -90,7 +90,7 @@ acc.update wait_devnum(%cst: index) host(%value: memref<10xf32>)
%cst = arith.constant 1 : index
%value = memref.alloc() : memref<10xf32>
// expected-error@+1 {{async attribute cannot appear with asyncOperand}}
// expected-error@+1 {{async attribute cannot appear with asyncOperand}}
acc.update async(%cst: index) host(%value: memref<10xf32>) attributes {async}
// -----