Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -760,9 +760,10 @@ mlir::Location currentLocation = converter.getCurrentLocation(); llvm::SmallVector lowerBound, upperBound, step, linearVars, linearStepVars, reductionVars; - mlir::Value scheduleChunkClauseOperand; + mlir::Value scheduleChunkClauseOperand, ifClauseOperand; mlir::Attribute scheduleClauseOperand, noWaitClauseOperand, orderedClauseOperand, orderClauseOperand; + Fortran::lower::StatementContext stmtCtx; const auto &loopOpClauseList = std::get( std::get(loopConstruct.t).t); @@ -823,12 +824,19 @@ std::get>( scheduleClause->v.t)) { if (const auto *expr = Fortran::semantics::GetExpr(*chunkExpr)) { - Fortran::lower::StatementContext stmtCtx; scheduleChunkClauseOperand = fir::getBase(converter.genExprValue(*expr, stmtCtx)); } } } + if (const auto &ifClause = + std::get_if(&clause.u)) { + auto &expr = std::get(ifClause->v.t); + mlir::Value ifVal = fir::getBase( + converter.genExprValue(*Fortran::semantics::GetExpr(expr), stmtCtx)); + ifClauseOperand = firOpBuilder.createConvert( + currentLocation, firOpBuilder.getI1Type(), ifVal); + } } // The types of lower bound, upper bound, and step are converted into the @@ -848,7 +856,8 @@ if (llvm::omp::OMPD_simd == ompDirective) { TypeRange resultType; auto SimdLoopOp = firOpBuilder.create( - currentLocation, resultType, lowerBound, upperBound, step); + currentLocation, resultType, lowerBound, upperBound, step, + ifClauseOperand); createBodyOfOp(SimdLoopOp, converter, currentLocation, eval, &loopOpClauseList, iv); return; Index: flang/test/Lower/OpenMP/simd.f90 =================================================================== --- flang/test/Lower/OpenMP/simd.f90 +++ flang/test/Lower/OpenMP/simd.f90 @@ -18,3 +18,21 @@ end do !$OMP END SIMD end subroutine + +!CHECK-LABEL: func @_QPsimdloop_with_if_clause +subroutine simdloop_with_if_clause +integer :: i + !$OMP SIMD IF( 1 .NE. 0 ) + ! CHECK: %[[LB:.*]] = arith.constant 1 : i32 + ! CHECK-NEXT: %[[UB:.*]] = arith.constant 9 : i32 + ! CHECK-NEXT: %[[STEP:.*]] = arith.constant 1 : i32 + ! CHECK-NEXT: %[[COND:.*]] = arith.constant true + ! CHECK-NEXT: omp.simdloop if(%[[COND:.*]]) (%[[I:.*]]) : i32 = (%[[LB]]) to (%[[UB]]) step (%[[STEP]]) { + do i = 1, 9 + ! 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 Index: mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td =================================================================== --- mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td +++ mlir/include/mlir/Dialect/OpenMP/OpenMPOps.td @@ -424,6 +424,10 @@ The body region can contain any number of blocks. The region is terminated by "omp.yield" instruction without operands. + + When an if clause is present and evaluates to false, + the preferred number of iterations to be executed concurrently is one, + regardless of whether a simdlen clause is speciļ¬ed. ``` omp.simdloop (%i1, %i2) : index = (%c0, %c0) to (%c10, %c10) step (%c1, %c1) { @@ -436,9 +440,16 @@ // TODO: Add other clauses let arguments = (ins Variadic:$lowerBound, Variadic:$upperBound, - Variadic:$step); + Variadic:$step, + Optional:$if_expr + ); let regions = (region AnyRegion:$region); + let assemblyFormat = [{ + oilist(`if` `(` $if_expr `)` + ) custom($region, $lowerBound, $upperBound, $step, + type($step)) attr-dict + }]; let extraClassDeclaration = [{ /// Returns the number of loops in the simd loop nest. Index: mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp =================================================================== --- mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp +++ mlir/lib/Dialect/OpenMP/IR/OpenMPDialect.cpp @@ -581,49 +581,46 @@ /// steps := `step` `(`ssa-id-list`)` /// clause-list ::= clause clause-list | empty /// clause ::= TODO -ParseResult SimdLoopOp::parse(OpAsmParser &parser, OperationState &result) { +ParseResult parseSimdLoopControl( + OpAsmParser &parser, Region ®ion, + SmallVectorImpl &lowerBound, + SmallVectorImpl &upperBound, + SmallVectorImpl &steps, + SmallVectorImpl &loopVarTypes) { // Parse an opening `(` followed by induction variables followed by `)` SmallVector ivs; Type loopVarType; - SmallVector lower, upper, steps; if (parser.parseArgumentList(ivs, OpAsmParser::Delimiter::Paren) || parser.parseColonType(loopVarType) || // Parse loop bounds. parser.parseEqual() || - parser.parseOperandList(lower, ivs.size(), + parser.parseOperandList(lowerBound, ivs.size(), OpAsmParser::Delimiter::Paren) || - parser.resolveOperands(lower, loopVarType, result.operands) || parser.parseKeyword("to") || - parser.parseOperandList(upper, ivs.size(), - OpAsmParser::Delimiter::Paren) || - parser.resolveOperands(upper, loopVarType, result.operands) || - // Parse step values. - parser.parseKeyword("step") || - parser.parseOperandList(steps, ivs.size(), - OpAsmParser::Delimiter::Paren) || - parser.resolveOperands(steps, loopVarType, result.operands)) + parser.parseOperandList(upperBound, ivs.size(), + OpAsmParser::Delimiter::Paren)) return failure(); - int numIVs = static_cast(ivs.size()); - SmallVector segments{numIVs, numIVs, numIVs}; - // TODO: Add parseClauses() when we support clauses - result.addAttribute("operand_segment_sizes", - parser.getBuilder().getI32VectorAttr(segments)); + // Parse step values. + if (parser.parseKeyword("step") || + parser.parseOperandList(steps, ivs.size(), OpAsmParser::Delimiter::Paren)) + return failure(); // Now parse the body. - Region *body = result.addRegion(); + loopVarTypes = SmallVector(ivs.size(), loopVarType); for (auto &iv : ivs) iv.type = loopVarType; - return parser.parseRegion(*body, ivs); + return parser.parseRegion(region, ivs); } -void SimdLoopOp::print(OpAsmPrinter &p) { - auto args = getRegion().front().getArguments(); - p << " (" << args << ") : " << args[0].getType() << " = (" << lowerBound() - << ") to (" << upperBound() << ") "; - p << "step (" << step() << ") "; - - p.printRegion(region(), /*printEntryBlockArgs=*/false); +void printSimdLoopControl(OpAsmPrinter &p, Operation *op, Region ®ion, + ValueRange lowerBound, ValueRange upperBound, + ValueRange steps, TypeRange loopVarTypes) { + auto args = region.front().getArguments(); + p << " (" << args << ") : " << args[0].getType() << " = (" << lowerBound + << ") to (" << upperBound << ") "; + p << "step (" << steps << ") "; + p.printRegion(region, /*printEntryBlockArgs=*/false); } //===----------------------------------------------------------------------===// Index: mlir/test/Dialect/OpenMP/invalid.mlir =================================================================== --- mlir/test/Dialect/OpenMP/invalid.mlir +++ mlir/test/Dialect/OpenMP/invalid.mlir @@ -197,7 +197,7 @@ "omp.simdloop" (%lb, %ub, %step) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} : + }) {operand_segment_sizes = dense<[1,1,1,0]> : vector<4xi32>} : (index, index, i32) -> () return Index: mlir/test/Dialect/OpenMP/ops.mlir =================================================================== --- mlir/test/Dialect/OpenMP/ops.mlir +++ mlir/test/Dialect/OpenMP/ops.mlir @@ -333,13 +333,12 @@ "omp.simdloop" (%lb, %ub, %step) ({ ^bb0(%iv: index): omp.yield - }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} : + }) {operand_segment_sizes = dense<[1,1,1,0]> : vector<4xi32>} : (index, index, index) -> () return } - // CHECK-LABEL: omp_simdloop_pretty func.func @omp_simdloop_pretty(%lb : index, %ub : index, %step : index) -> () { // CHECK: omp.simdloop (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) @@ -349,6 +348,15 @@ return } +// CHECK-LABEL: omp_simdloop_pretty_if +func.func @omp_simdloop_pretty_if(%lb : index, %ub : index, %step : index, %if_cond : i1) -> () { + // CHECK: omp.simdloop if(%{{.*}}) (%{{.*}}) : index = (%{{.*}}) to (%{{.*}}) step (%{{.*}}) + omp.simdloop if(%if_cond) (%iv): index = (%lb) to (%ub) step (%step) { + omp.yield + } + return +} + // CHECK-LABEL: omp_simdloop_pretty_multiple func.func @omp_simdloop_pretty_multiple(%lb1 : index, %ub1 : index, %step1 : index, %lb2 : index, %ub2 : index, %step2 : index) -> () { // CHECK: omp.simdloop (%{{.*}}, %{{.*}}) : index = (%{{.*}}, %{{.*}}) to (%{{.*}}, %{{.*}}) step (%{{.*}}, %{{.*}}) Index: mlir/test/Target/LLVMIR/openmp-llvm.mlir =================================================================== --- mlir/test/Target/LLVMIR/openmp-llvm.mlir +++ mlir/test/Target/LLVMIR/openmp-llvm.mlir @@ -697,7 +697,7 @@ %4 = llvm.getelementptr %arg0[%iv] : (!llvm.ptr, i64) -> !llvm.ptr llvm.store %3, %4 : !llvm.ptr omp.yield - }) {operand_segment_sizes = dense<[1,1,1]> : vector<3xi32>} : + }) {operand_segment_sizes = dense<[1,1,1,0]> : vector<4xi32>} : (i64, i64, i64) -> () llvm.return