Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -1004,7 +1004,7 @@ mlir::Value scheduleChunkClauseOperand, ifClauseOperand; mlir::Attribute scheduleClauseOperand, noWaitClauseOperand, orderedClauseOperand, orderClauseOperand; - mlir::IntegerAttr simdlenClauseOperand; + mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand; SmallVector reductionDeclSymbols; Fortran::lower::StatementContext stmtCtx; const auto &loopOpClauseList = std::get( @@ -1129,6 +1129,13 @@ const std::optional simdlenVal = Fortran::evaluate::ToInt64(*expr); simdlenClauseOperand = firOpBuilder.getI64IntegerAttr(*simdlenVal); + } else if (const auto &safelenClause = + std::get_if( + &clause.u)) { + const auto *expr = Fortran::semantics::GetExpr(safelenClause->v); + const std::optional safelenVal = + Fortran::evaluate::ToInt64(*expr); + safelenClauseOperand = firOpBuilder.getI64IntegerAttr(*safelenVal); } } @@ -1150,7 +1157,7 @@ TypeRange resultType; auto SimdLoopOp = firOpBuilder.create( currentLocation, resultType, lowerBound, upperBound, step, - ifClauseOperand, simdlenClauseOperand, nullptr, + ifClauseOperand, simdlenClauseOperand, safelenClauseOperand, /*inclusive=*/firOpBuilder.getUnitAttr()); createBodyOfOp(SimdLoopOp, converter, currentLocation, eval, &loopOpClauseList, iv); Index: flang/test/Lower/OpenMP/simd.f90 =================================================================== --- flang/test/Lower/OpenMP/simd.f90 +++ flang/test/Lower/OpenMP/simd.f90 @@ -90,6 +90,58 @@ !$OMP END SIMD end subroutine +!CHECK-LABEL: func @_QPsimdloop_with_safelen_clause +subroutine simdloop_with_safelen_clause(n, threshold) +integer :: i, n, threshold + !$OMP SIMD SAFELEN(2) + ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 + ! CHECK: %[[UB:.*]] = fir.load %arg0 + ! CHECK: %[[STEP:.*]] = arith.constant 1 : i32 + ! CHECK: omp.simdloop safelen(2) for (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) { + do i = 1, n + ! CHECK: fir.store %[[I]] to %[[LOCAL:.*]] : !fir.ref + ! CHECK: %[[LD:.*]] = fir.load %[[LOCAL]] : !fir.ref + ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LD]]) : (!fir.ref, i32) -> i1 + print*, i + end do + !$OMP END SIMD +end subroutine + +!CHECK-LABEL: func @_QPsimdloop_with_safelen_clause_from_expr_from_param +subroutine simdloop_with_safelen_clause_from_expr_from_param(n, threshold) +integer :: i, n, threshold +integer, parameter :: safelen = 2; + !$OMP SIMD SAFELEN(safelen*2 + 2) + ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 + ! CHECK: %[[UB:.*]] = fir.load %arg0 + ! CHECK: %[[STEP:.*]] = arith.constant 1 : i32 + ! CHECK: omp.simdloop safelen(6) for (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) { + do i = 1, n + ! CHECK: fir.store %[[I]] to %[[LOCAL:.*]] : !fir.ref + ! CHECK: %[[LD:.*]] = fir.load %[[LOCAL]] : !fir.ref + ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LD]]) : (!fir.ref, i32) -> i1 + print*, i + end do + !$OMP END SIMD +end subroutine + +!CHECK-LABEL: func @_QPsimdloop_with_simdlen_safelen_clause +subroutine simdloop_with_simdlen_safelen_clause(n, threshold) +integer :: i, n, threshold + !$OMP SIMD SIMDLEN(1) SAFELEN(2) + ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 + ! CHECK: %[[UB:.*]] = fir.load %arg0 + ! CHECK: %[[STEP:.*]] = arith.constant 1 : i32 + ! CHECK: omp.simdloop simdlen(1) safelen(2) for (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) inclusive step (%[[STEP]]) { + do i = 1, n + ! CHECK: fir.store %[[I]] to %[[LOCAL:.*]] : !fir.ref + ! CHECK: %[[LD:.*]] = fir.load %[[LOCAL]] : !fir.ref + ! CHECK: fir.call @_FortranAioOutputInteger32({{.*}}, %[[LD]]) : (!fir.ref, i32) -> i1 + print*, i + end do + !$OMP END SIMD +end subroutine + !CHECK-LABEL: func @_QPsimdloop_with_collapse_clause subroutine simdloop_with_collapse_clause(n) integer :: i, j, n