================
@@ -314,15 +314,80 @@ const VarDecl *getLValueDecl(const Expr *e) {
return cast<VarDecl>(dre->getDecl());
}
-mlir::LogicalResult
-CIRGenFunction::emitOpenACCAtomicConstruct(const OpenACCAtomicConstruct &s) {
- // For now, we are only support 'read'/'write'/'update', so diagnose. We can
- // switch on the kind later once we implement the 'capture' form.
- if (s.getAtomicKind() == OpenACCAtomicKind::Capture) {
- cgm.errorNYI(s.getSourceRange(), "OpenACC Atomic Construct");
- return mlir::failure();
+static mlir::acc::AtomicReadOp
+emitAtomicRead(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
+ mlir::Location start,
+ OpenACCAtomicConstruct::SingleStmtInfo inf) {
+ // Atomic 'read' only permits 'v = x', where v and x are both scalar L
+ // values. The getAssociatedStmtInfo strips off implicit casts, which
+ // includes implicit conversions and L-to-R-Value conversions, so we can
+ // just emit it as an L value. The Flang implementation has no problem with
+ // different types, so it appears that the dialect can handle the
+ // conversions.
+ mlir::Value v = cgf.emitLValue(inf.V).getPointer();
+ mlir::Value x = cgf.emitLValue(inf.X).getPointer();
+ mlir::Type resTy = cgf.convertType(inf.V->getType());
+ return mlir::acc::AtomicReadOp::create(builder, start, x, v, resTy,
+ /*ifCond=*/{});
+}
+
+static mlir::acc::AtomicWriteOp
+emitAtomicWrite(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
+ mlir::Location start,
+ OpenACCAtomicConstruct::SingleStmtInfo inf) {
+ mlir::Value x = cgf.emitLValue(inf.X).getPointer();
+ mlir::Value expr = cgf.emitAnyExpr(inf.RefExpr).getValue();
+ return mlir::acc::AtomicWriteOp::create(builder, start, x, expr,
+ /*ifCond=*/{});
+}
+
+static std::pair<mlir::LogicalResult, mlir::acc::AtomicUpdateOp>
+emitAtomicUpdate(CIRGenFunction &cgf, CIRGenBuilderTy &builder,
+ mlir::Location start, mlir::Location end,
+ OpenACCAtomicConstruct::SingleStmtInfo inf) {
+ mlir::Value x = cgf.emitLValue(inf.X).getPointer();
+ auto op = mlir::acc::AtomicUpdateOp::create(builder, start, x,
/*ifCond=*/{});
+
+ mlir::LogicalResult res = mlir::success();
+ {
+ mlir::OpBuilder::InsertionGuard guardCase(builder);
+ mlir::Type argTy = cast<cir::PointerType>(x.getType()).getPointee();
+ std::array<mlir::Type, 1> recipeType{argTy};
+ std::array<mlir::Location, 1> recipeLoc{start};
+ auto *recipeBlock = builder.createBlock(
+ &op.getRegion(), op.getRegion().end(), recipeType, recipeLoc);
+ builder.setInsertionPointToEnd(recipeBlock);
+ // Since we have an initial value that we know is a scalar type, we can
+ // just emit the entire statement here after sneaking-in our 'alloca' in
+ // the right place, then loading out of it. Flang does a lot less work
+ // (probably does its own emitting!), but we have more complicated AST
+ // nodes to worry about, so we can just count on opt to remove the extra
+ // alloca/load/store set.
+ auto alloca = cir::AllocaOp::create(
+ builder, start, x.getType(), argTy, "x_var",
+ cgf.cgm.getSize(
+ cgf.getContext().getTypeAlignInChars(inf.X->getType())));
+
+ alloca.setInitAttr(mlir::UnitAttr::get(&cgf.getMLIRContext()));
----------------
andykaylor wrote:
Unrelated to this PR, but it seems a bit dumb that we always pass
`mlir::UnitAttr::get(context))` to `setInitAttr`. It seems like we could have a
helper function with no parameters that did this.
https://github.com/llvm/llvm-project/pull/168422
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits