1 //===-- OpenMP.cpp -- Open MP directive lowering --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "flang/Lower/OpenMP.h" 14 #include "flang/Lower/Bridge.h" 15 #include "flang/Lower/FIRBuilder.h" 16 #include "flang/Lower/PFTBuilder.h" 17 #include "flang/Parser/parse-tree.h" 18 #include "flang/Semantics/tools.h" 19 #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 20 #include "llvm/Frontend/OpenMP/OMPConstants.h" 21 22 #define TODO() llvm_unreachable("not yet implemented") 23 24 static void genOMP(Fortran::lower::AbstractConverter &converter, 25 Fortran::lower::pft::Evaluation &eval, 26 const Fortran::parser::OpenMPSimpleStandaloneConstruct 27 &simpleStandaloneConstruct) { 28 const auto &directive = 29 std::get<Fortran::parser::OmpSimpleStandaloneDirective>( 30 simpleStandaloneConstruct.t); 31 switch (directive.v) { 32 default: 33 break; 34 case llvm::omp::Directive::OMPD_barrier: 35 converter.getFirOpBuilder().create<mlir::omp::BarrierOp>( 36 converter.getCurrentLocation()); 37 break; 38 case llvm::omp::Directive::OMPD_taskwait: 39 converter.getFirOpBuilder().create<mlir::omp::TaskwaitOp>( 40 converter.getCurrentLocation()); 41 break; 42 case llvm::omp::Directive::OMPD_taskyield: 43 converter.getFirOpBuilder().create<mlir::omp::TaskyieldOp>( 44 converter.getCurrentLocation()); 45 break; 46 case llvm::omp::Directive::OMPD_target_enter_data: 47 TODO(); 48 case llvm::omp::Directive::OMPD_target_exit_data: 49 TODO(); 50 case llvm::omp::Directive::OMPD_target_update: 51 TODO(); 52 case llvm::omp::Directive::OMPD_ordered: 53 TODO(); 54 } 55 } 56 57 static void 58 genOMP(Fortran::lower::AbstractConverter &converter, 59 Fortran::lower::pft::Evaluation &eval, 60 const Fortran::parser::OpenMPStandaloneConstruct &standaloneConstruct) { 61 std::visit( 62 Fortran::common::visitors{ 63 [&](const Fortran::parser::OpenMPSimpleStandaloneConstruct 64 &simpleStandaloneConstruct) { 65 genOMP(converter, eval, simpleStandaloneConstruct); 66 }, 67 [&](const Fortran::parser::OpenMPFlushConstruct &flushConstruct) { 68 TODO(); 69 }, 70 [&](const Fortran::parser::OpenMPCancelConstruct &cancelConstruct) { 71 TODO(); 72 }, 73 [&](const Fortran::parser::OpenMPCancellationPointConstruct 74 &cancellationPointConstruct) { TODO(); }, 75 }, 76 standaloneConstruct.u); 77 } 78 79 static void 80 genOMP(Fortran::lower::AbstractConverter &converter, 81 Fortran::lower::pft::Evaluation &eval, 82 const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { 83 const auto &blockDirective = 84 std::get<Fortran::parser::OmpBeginBlockDirective>(blockConstruct.t); 85 const auto ¶llelDirective = 86 std::get<Fortran::parser::OmpBlockDirective>(blockDirective.t); 87 if (parallelDirective.v == llvm::omp::OMPD_parallel) { 88 auto &firOpBuilder = converter.getFirOpBuilder(); 89 auto currentLocation = converter.getCurrentLocation(); 90 auto insertPt = firOpBuilder.saveInsertionPoint(); 91 92 // Clauses. 93 // FIXME: Add support for other clauses. 94 mlir::Value numThreads; 95 96 const auto ¶llelOpClauseList = 97 std::get<Fortran::parser::OmpClauseList>(blockDirective.t); 98 for (const auto &clause : parallelOpClauseList.v) { 99 if (const auto &numThreadsClause = 100 std::get_if<Fortran::parser::OmpClause::NumThreads>(&clause.u)) { 101 // OMPIRBuilder expects `NUM_THREAD` clause as a `Value`. 102 numThreads = converter.genExprValue( 103 *Fortran::semantics::GetExpr(numThreadsClause->v)); 104 } 105 } 106 llvm::ArrayRef<mlir::Type> argTy; 107 Attribute defaultValue, procBindValue; 108 // Create and insert the operation. 109 // Create the Op with empty ranges for clauses that are yet to be lowered. 110 auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>( 111 currentLocation, argTy, Value(), numThreads, 112 defaultValue.dyn_cast_or_null<StringAttr>(), ValueRange(), ValueRange(), 113 ValueRange(), ValueRange(), 114 procBindValue.dyn_cast_or_null<StringAttr>()); 115 firOpBuilder.createBlock(¶llelOp.getRegion()); 116 auto &block = parallelOp.getRegion().back(); 117 firOpBuilder.setInsertionPointToStart(&block); 118 // Ensure the block is well-formed. 119 firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation); 120 firOpBuilder.restoreInsertionPoint(insertPt); 121 } 122 } 123 124 void Fortran::lower::genOpenMPConstruct( 125 Fortran::lower::AbstractConverter &converter, 126 Fortran::lower::pft::Evaluation &eval, 127 const Fortran::parser::OpenMPConstruct &ompConstruct) { 128 129 std::visit( 130 common::visitors{ 131 [&](const Fortran::parser::OpenMPStandaloneConstruct 132 &standaloneConstruct) { 133 genOMP(converter, eval, standaloneConstruct); 134 }, 135 [&](const Fortran::parser::OpenMPSectionsConstruct 136 §ionsConstruct) { TODO(); }, 137 [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { 138 TODO(); 139 }, 140 [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { 141 genOMP(converter, eval, blockConstruct); 142 }, 143 [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { 144 TODO(); 145 }, 146 [&](const Fortran::parser::OpenMPCriticalConstruct 147 &criticalConstruct) { TODO(); }, 148 }, 149 ompConstruct.u); 150 } 151 152 void Fortran::lower::genOpenMPEndLoop( 153 Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &, 154 const Fortran::parser::OmpEndLoopDirective &) { 155 TODO(); 156 } 157