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 91 // Clauses. 92 // FIXME: Add support for other clauses. 93 mlir::Value numThreads; 94 95 const auto ¶llelOpClauseList = 96 std::get<Fortran::parser::OmpClauseList>(blockDirective.t); 97 for (const auto &clause : parallelOpClauseList.v) { 98 if (const auto &numThreadsClause = 99 std::get_if<Fortran::parser::OmpClause::NumThreads>(&clause.u)) { 100 // OMPIRBuilder expects `NUM_THREAD` clause as a `Value`. 101 numThreads = converter.genExprValue( 102 *Fortran::semantics::GetExpr(numThreadsClause->v)); 103 } 104 } 105 llvm::ArrayRef<mlir::Type> argTy; 106 Attribute defaultValue, procBindValue; 107 // Create and insert the operation. 108 // Create the Op with empty ranges for clauses that are yet to be lowered. 109 auto parallelOp = firOpBuilder.create<mlir::omp::ParallelOp>( 110 currentLocation, argTy, Value(), numThreads, 111 defaultValue.dyn_cast_or_null<StringAttr>(), ValueRange(), ValueRange(), 112 ValueRange(), ValueRange(), ValueRange(), ValueRange(), 113 procBindValue.dyn_cast_or_null<StringAttr>()); 114 firOpBuilder.createBlock(¶llelOp.getRegion()); 115 auto &block = parallelOp.getRegion().back(); 116 firOpBuilder.setInsertionPointToStart(&block); 117 // Ensure the block is well-formed. 118 firOpBuilder.create<mlir::omp::TerminatorOp>(currentLocation); 119 120 // Place the insertion point to the start of the first block. 121 firOpBuilder.setInsertionPointToStart(&block); 122 } 123 } 124 125 void Fortran::lower::genOpenMPConstruct( 126 Fortran::lower::AbstractConverter &converter, 127 Fortran::lower::pft::Evaluation &eval, 128 const Fortran::parser::OpenMPConstruct &ompConstruct) { 129 130 std::visit( 131 common::visitors{ 132 [&](const Fortran::parser::OpenMPStandaloneConstruct 133 &standaloneConstruct) { 134 genOMP(converter, eval, standaloneConstruct); 135 }, 136 [&](const Fortran::parser::OpenMPSectionsConstruct 137 §ionsConstruct) { TODO(); }, 138 [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { 139 TODO(); 140 }, 141 [&](const Fortran::parser::OpenMPBlockConstruct &blockConstruct) { 142 genOMP(converter, eval, blockConstruct); 143 }, 144 [&](const Fortran::parser::OpenMPAtomicConstruct &atomicConstruct) { 145 TODO(); 146 }, 147 [&](const Fortran::parser::OpenMPCriticalConstruct 148 &criticalConstruct) { TODO(); }, 149 }, 150 ompConstruct.u); 151 } 152 153 void Fortran::lower::genOpenMPEndLoop( 154 Fortran::lower::AbstractConverter &, Fortran::lower::pft::Evaluation &, 155 const Fortran::parser::OmpEndLoopDirective &) { 156 TODO(); 157 } 158