diff --git a/flang/lib/Lower/DirectivesCommon.h b/flang/lib/Lower/DirectivesCommon.h index 656fd36099b51..1b231ee1b891b 100644 --- a/flang/lib/Lower/DirectivesCommon.h +++ b/flang/lib/Lower/DirectivesCommon.h @@ -357,6 +357,11 @@ void genOmpAccAtomicRead(Fortran::lower::AbstractConverter &converter, fir::getBase(converter.genExprAddr(fromExpr, stmtCtx)); mlir::Value toAddress = fir::getBase(converter.genExprAddr( *Fortran::semantics::GetExpr(assignmentStmtVariable), stmtCtx)); + mlir::Location loc = converter.getCurrentLocation(); + fir::FirOpBuilder &builder = converter.getFirOpBuilder(); + if (fromAddress.getType() != toAddress.getType()) + fromAddress = + builder.create(loc, toAddress.getType(), fromAddress); genOmpAccAtomicCaptureStatement(converter, fromAddress, toAddress, leftHandClauseList, rightHandClauseList, elementType); @@ -427,10 +432,12 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter, const Fortran::parser::AssignmentStmt &stmt1 = std::get(atomicCapture.t).v.statement; + const Fortran::evaluate::Assignment &assign1 = *stmt1.typedAssignment->v; const auto &stmt1Var{std::get(stmt1.t)}; const auto &stmt1Expr{std::get(stmt1.t)}; const Fortran::parser::AssignmentStmt &stmt2 = std::get(atomicCapture.t).v.statement; + const Fortran::evaluate::Assignment &assign2 = *stmt2.typedAssignment->v; const auto &stmt2Var{std::get(stmt2.t)}; const auto &stmt2Expr{std::get(stmt2.t)}; @@ -442,36 +449,25 @@ void genOmpAccAtomicCapture(Fortran::lower::AbstractConverter &converter, mlir::Value stmt1LHSArg, stmt1RHSArg, stmt2LHSArg, stmt2RHSArg; mlir::Type elementType; // LHS evaluations are common to all combinations of `atomic.capture` - stmt1LHSArg = fir::getBase( - converter.genExprAddr(*Fortran::semantics::GetExpr(stmt1Var), stmtCtx)); - stmt2LHSArg = fir::getBase( - converter.genExprAddr(*Fortran::semantics::GetExpr(stmt2Var), stmtCtx)); + stmt1LHSArg = fir::getBase(converter.genExprAddr(assign1.lhs, stmtCtx)); + stmt2LHSArg = fir::getBase(converter.genExprAddr(assign2.lhs, stmtCtx)); // Operation specific RHS evaluations if (checkForSingleVariableOnRHS(stmt1)) { // Atomic capture construct is of the form [capture-stmt, update-stmt] or // of the form [capture-stmt, write-stmt] - stmt1RHSArg = fir::getBase(converter.genExprAddr( - *Fortran::semantics::GetExpr(stmt1Expr), stmtCtx)); - stmt2RHSArg = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(stmt2Expr), stmtCtx)); - + stmt1RHSArg = fir::getBase(converter.genExprAddr(assign1.rhs, stmtCtx)); + stmt2RHSArg = fir::getBase(converter.genExprValue(assign2.rhs, stmtCtx)); } else { // Atomic capture construct is of the form [update-stmt, capture-stmt] - stmt1RHSArg = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(stmt1Expr), stmtCtx)); - stmt2RHSArg = fir::getBase(converter.genExprAddr( - *Fortran::semantics::GetExpr(stmt2Expr), stmtCtx)); + stmt1RHSArg = fir::getBase(converter.genExprValue(assign1.rhs, stmtCtx)); + stmt2RHSArg = fir::getBase(converter.genExprAddr(assign2.lhs, stmtCtx)); } // Type information used in generation of `atomic.update` operation mlir::Type stmt1VarType = - fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(stmt1Var), stmtCtx)) - .getType(); + fir::getBase(converter.genExprValue(assign1.lhs, stmtCtx)).getType(); mlir::Type stmt2VarType = - fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(stmt2Var), stmtCtx)) - .getType(); + fir::getBase(converter.genExprValue(assign2.lhs, stmtCtx)).getType(); mlir::Operation *atomicCaptureOp = nullptr; if constexpr (std::is_same : f32 +! CHECK: %[[CONV:.*]] = fir.convert %[[MUL]] : (f32) -> i32 +! CHECK: acc.atomic.capture { +! CHECK: acc.atomic.read %[[V]] = %[[K]] : !fir.ref, i32 +! CHECK: acc.atomic.write %[[K]] = %[[CONV]] : !fir.ref, i32 +! CHECK: } diff --git a/flang/test/Lower/OpenACC/acc-atomic-read.f90 b/flang/test/Lower/OpenACC/acc-atomic-read.f90 index 28f0ce44e6f41..3a718576124c3 100644 --- a/flang/test/Lower/OpenACC/acc-atomic-read.f90 +++ b/flang/test/Lower/OpenACC/acc-atomic-read.f90 @@ -46,3 +46,17 @@ subroutine atomic_read_pointer() x = y end + +subroutine atomic_read_with_convert() + integer(4) :: x + integer(8) :: y + + !$acc atomic read + y = x +end + +! CHECK-LABEL: func.func @_QPatomic_read_with_convert() { +! CHECK: %[[X:.*]] = fir.alloca i32 {bindc_name = "x", uniq_name = "_QFatomic_read_with_convertEx"} +! CHECK: %[[Y:.*]] = fir.alloca i64 {bindc_name = "y", uniq_name = "_QFatomic_read_with_convertEy"} +! CHECK: %[[CONV:.*]] = fir.convert %[[X]] : (!fir.ref) -> !fir.ref +! CHECK: acc.atomic.read %[[Y]] = %[[CONV]] : !fir.ref, i32