@@ -1227,32 +1227,28 @@ static LogicalResult verifyOrderedRegionOp(OrderedRegionOp op) {
1227
1227
// / address ::= operand `:` type
1228
1228
static ParseResult parseAtomicReadOp (OpAsmParser &parser,
1229
1229
OperationState &result) {
1230
- OpAsmParser::OperandType address ;
1230
+ OpAsmParser::OperandType x, v ;
1231
1231
Type addressType;
1232
1232
SmallVector<ClauseType> clauses = {memoryOrderClause, hintClause};
1233
1233
SmallVector<int > segments;
1234
1234
1235
- if (parser.parseOperand (address ) ||
1235
+ if (parser.parseOperand (v) || parser. parseEqual () || parser. parseOperand (x ) ||
1236
1236
parseClauses (parser, result, clauses, segments) ||
1237
1237
parser.parseColonType (addressType) ||
1238
- parser.resolveOperand (address, addressType, result.operands ))
1238
+ parser.resolveOperand (x, addressType, result.operands ) ||
1239
+ parser.resolveOperand (v, addressType, result.operands ))
1239
1240
return failure ();
1240
-
1241
- SmallVector<Type> resultType;
1242
- if (parser.parseArrowTypeList (resultType))
1243
- return failure ();
1244
- result.addTypes (resultType);
1245
1241
return success ();
1246
1242
}
1247
1243
1248
1244
// / Printer for AtomicReadOp
1249
1245
static void printAtomicReadOp (OpAsmPrinter &p, AtomicReadOp op) {
1250
- p << " " << op.address () << " " ;
1246
+ p << " " << op.v () << " = " << op. x () << " " ;
1251
1247
if (op.memory_order ())
1252
1248
p << " memory_order(" << op.memory_order ().getValue () << " ) " ;
1253
1249
if (op.hintAttr ())
1254
1250
printSynchronizationHint (p << " " , op, op.hintAttr ());
1255
- p << " : " << op.address (). getType () << " -> " << op .getType ();
1251
+ p << " : " << op.x () .getType ();
1256
1252
return ;
1257
1253
}
1258
1254
@@ -1264,6 +1260,9 @@ static LogicalResult verifyAtomicReadOp(AtomicReadOp op) {
1264
1260
return op.emitError (
1265
1261
" memory-order must not be acq_rel or release for atomic reads" );
1266
1262
}
1263
+ if (op.x () == op.v ())
1264
+ return op.emitError (
1265
+ " read and write must not be to the same location for atomic reads" );
1267
1266
return verifySynchronizationHint (op, op.hint ());
1268
1267
}
1269
1268
@@ -1284,7 +1283,7 @@ static ParseResult parseAtomicWriteOp(OpAsmParser &parser,
1284
1283
SmallVector<ClauseType> clauses = {memoryOrderClause, hintClause};
1285
1284
SmallVector<int > segments;
1286
1285
1287
- if (parser.parseOperand (address) || parser.parseComma () ||
1286
+ if (parser.parseOperand (address) || parser.parseEqual () ||
1288
1287
parser.parseOperand (value) ||
1289
1288
parseClauses (parser, result, clauses, segments) ||
1290
1289
parser.parseColonType (addrType) || parser.parseComma () ||
@@ -1297,7 +1296,7 @@ static ParseResult parseAtomicWriteOp(OpAsmParser &parser,
1297
1296
1298
1297
// / Printer for AtomicWriteOp
1299
1298
static void printAtomicWriteOp (OpAsmPrinter &p, AtomicWriteOp op) {
1300
- p << " " << op.address () << " , " << op.value () << " " ;
1299
+ p << " " << op.address () << " = " << op.value () << " " ;
1301
1300
if (op.memory_order ())
1302
1301
p << " memory_order(" << op.memory_order () << " ) " ;
1303
1302
if (op.hintAttr ())
@@ -1328,61 +1327,28 @@ static ParseResult parseAtomicUpdateOp(OpAsmParser &parser,
1328
1327
OperationState &result) {
1329
1328
SmallVector<ClauseType> clauses = {memoryOrderClause, hintClause};
1330
1329
SmallVector<int > segments;
1331
- OpAsmParser::OperandType x, y, z;
1332
- Type xType, exprType;
1333
- StringRef binOp;
1334
-
1335
- // x = y `op` z : xtype, exprtype
1336
- if (parser.parseOperand (x) || parser.parseEqual () || parser.parseOperand (y) ||
1337
- parser.parseKeyword (&binOp) || parser.parseOperand (z) ||
1338
- parseClauses (parser, result, clauses, segments) || parser.parseColon () ||
1339
- parser.parseType (xType) || parser.parseComma () ||
1340
- parser.parseType (exprType) ||
1341
- parser.resolveOperand (x, xType, result.operands )) {
1330
+ OpAsmParser::OperandType x, expr;
1331
+ Type xType;
1332
+
1333
+ if (parseClauses (parser, result, clauses, segments) ||
1334
+ parser.parseOperand (x) || parser.parseColon () ||
1335
+ parser.parseType (xType) ||
1336
+ parser.resolveOperand (x, xType, result.operands ) ||
1337
+ parser.parseRegion (*result.addRegion ())) {
1342
1338
return failure ();
1343
1339
}
1344
-
1345
- auto binOpEnum = AtomicBinOpKindToEnum (binOp.upper ());
1346
- if (!binOpEnum)
1347
- return parser.emitError (parser.getNameLoc ())
1348
- << " invalid atomic bin op in atomic update\n " ;
1349
- auto attr =
1350
- parser.getBuilder ().getI64IntegerAttr ((int64_t )binOpEnum.getValue ());
1351
- result.addAttribute (" binop" , attr);
1352
-
1353
- OpAsmParser::OperandType expr;
1354
- if (x.name == y.name && x.number == y.number ) {
1355
- expr = z;
1356
- result.addAttribute (" isXBinopExpr" , parser.getBuilder ().getUnitAttr ());
1357
- } else if (x.name == z.name && x.number == z.number ) {
1358
- expr = y;
1359
- } else {
1360
- return parser.emitError (parser.getNameLoc ())
1361
- << " atomic update variable " << x.name
1362
- << " not found in the RHS of the assignment statement in an"
1363
- " atomic.update operation" ;
1364
- }
1365
- return parser.resolveOperand (expr, exprType, result.operands );
1340
+ return success ();
1366
1341
}
1367
1342
1368
1343
// / Printer for AtomicUpdateOp
1369
1344
static void printAtomicUpdateOp (OpAsmPrinter &p, AtomicUpdateOp op) {
1370
- p << " " << op.x () << " = " ;
1371
- Value y, z;
1372
- if (op.isXBinopExpr ()) {
1373
- y = op.x ();
1374
- z = op.expr ();
1375
- } else {
1376
- y = op.expr ();
1377
- z = op.x ();
1378
- }
1379
- p << y << " " << AtomicBinOpKindToString (op.binop ()).lower () << " " << z
1380
- << " " ;
1345
+ p << " " ;
1381
1346
if (op.memory_order ())
1382
1347
p << " memory_order(" << op.memory_order () << " ) " ;
1383
1348
if (op.hintAttr ())
1384
1349
printSynchronizationHint (p, op, op.hintAttr ());
1385
- p << " : " << op.x ().getType () << " , " << op.expr ().getType ();
1350
+ p << op.x () << " : " << op.x ().getType ();
1351
+ p.printRegion (op.region ());
1386
1352
}
1387
1353
1388
1354
// / Verifier for AtomicUpdateOp
@@ -1393,6 +1359,84 @@ static LogicalResult verifyAtomicUpdateOp(AtomicUpdateOp op) {
1393
1359
return op.emitError (
1394
1360
" memory-order must not be acq_rel or acquire for atomic updates" );
1395
1361
}
1362
+ if (op.region ().getNumArguments () != 1 )
1363
+ return op.emitError (" the region must accept exactly one argument" );
1364
+
1365
+ if (op.x ().getType ().cast <PointerLikeType>().getElementType () !=
1366
+ op.region ().getArgument (0 ).getType ()) {
1367
+ return op.emitError (
1368
+ " the type of the operand must be a pointer type whose "
1369
+ " element type is the same as that of the region argument" );
1370
+ }
1371
+
1372
+ YieldOp yieldOp = *op.region ().getOps <YieldOp>().begin ();
1373
+ if (yieldOp.results ().size () != 1 )
1374
+ return op.emitError (" only updated value must be returned" );
1375
+ if (yieldOp.results ().front ().getType () !=
1376
+ op.region ().getArgument (0 ).getType ())
1377
+ return op.emitError (" input and yielded value must have the same type" );
1378
+ return success ();
1379
+ }
1380
+
1381
+ // ===----------------------------------------------------------------------===//
1382
+ // AtomicCaptureOp
1383
+ // ===----------------------------------------------------------------------===//
1384
+
1385
+ // / Parser for AtomicCaptureOp
1386
+ static LogicalResult parseAtomicCaptureOp (OpAsmParser &parser,
1387
+ OperationState &result) {
1388
+ SmallVector<ClauseType> clauses = {memoryOrderClause, hintClause};
1389
+ SmallVector<int > segments;
1390
+ if (parseClauses (parser, result, clauses, segments) ||
1391
+ parser.parseRegion (*result.addRegion ()))
1392
+ return failure ();
1393
+ return success ();
1394
+ }
1395
+
1396
+ // / Printer for AtomicCaptureOp
1397
+ static void printAtomicCaptureOp (OpAsmPrinter &p, AtomicCaptureOp op) {
1398
+ if (op.memory_order ())
1399
+ p << " memory_order(" << op.memory_order () << " ) " ;
1400
+ if (op.hintAttr ())
1401
+ printSynchronizationHint (p, op, op.hintAttr ());
1402
+ p.printRegion (op.region ());
1403
+ }
1404
+
1405
+ // / Verifier for AtomicCaptureOp
1406
+ static LogicalResult verifyAtomicCaptureOp (AtomicCaptureOp op) {
1407
+ Block::OpListType &ops = op.region ().front ().getOperations ();
1408
+ if (ops.size () != 3 )
1409
+ return emitError (op.getLoc ())
1410
+ << " expected three operations in omp.atomic.capture region (one"
1411
+ " terminator, and two atomic ops" ;
1412
+ auto &firstOp = ops.front ();
1413
+ auto &secondOp = *ops.getNextNode (firstOp);
1414
+ auto firstReadStmt = dyn_cast<AtomicReadOp>(firstOp);
1415
+ auto firstUpdateStmt = dyn_cast<AtomicUpdateOp>(firstOp);
1416
+ auto secondReadStmt = dyn_cast<AtomicReadOp>(secondOp);
1417
+ auto secondUpdateStmt = dyn_cast<AtomicUpdateOp>(secondOp);
1418
+ auto secondWriteStmt = dyn_cast<AtomicWriteOp>(secondOp);
1419
+
1420
+ if (!((firstUpdateStmt && secondReadStmt) ||
1421
+ (firstReadStmt && secondUpdateStmt) ||
1422
+ (firstReadStmt && secondWriteStmt)))
1423
+ return emitError (ops.front ().getLoc ())
1424
+ << " invalid sequence of operations in the capture region" ;
1425
+ if (firstUpdateStmt && secondReadStmt &&
1426
+ firstUpdateStmt.x () != secondReadStmt.x ())
1427
+ return emitError (firstUpdateStmt.getLoc ())
1428
+ << " updated variable in omp.atomic.update must be captured in "
1429
+ " second operation" ;
1430
+ if (firstReadStmt && secondUpdateStmt &&
1431
+ firstReadStmt.x () != secondUpdateStmt.x ())
1432
+ return emitError (firstReadStmt.getLoc ())
1433
+ << " captured variable in omp.atomic.read must be updated in "
1434
+ " second operation" ;
1435
+ if (firstReadStmt && secondWriteStmt &&
1436
+ firstReadStmt.x () != secondWriteStmt.address ())
1437
+ return emitError (firstReadStmt.getLoc ())
1438
+ << " captured variable in omp.atomic.read must be updated in "
1439
+ " second operation" ;
1396
1440
return success ();
1397
1441
}
1398
1442
0 commit comments