@@ -2075,6 +2075,7 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
20752075 firOpBuilder.setInsertionPointToStart (firOpBuilder.getAllocaBlock ());
20762076
20772077 mlir::Type tempTy = converter.genType (*sym);
2078+ llvm::outs () << " Temp type = " << tempTy << " \n " ;
20782079 mlir::Value temp = firOpBuilder.create <fir::AllocaOp>(
20792080 loc, tempTy, /* pinned=*/ true , /* lengthParams=*/ mlir::ValueRange{},
20802081 /* shapeParams*/ mlir::ValueRange{},
@@ -2088,6 +2089,103 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
20882089 return storeOp;
20892090}
20902091
2092+ // / Create the body (block) for an OpenMP Loop Operation.
2093+ // /
2094+ // / \param [in] op - the operation the body belongs to.
2095+ // / \param [inout] converter - converter to use for the clauses.
2096+ // / \param [in] loc - location in source code.
2097+ // / \param [in] eval - current PFT node/evaluation.
2098+ // / \oaran [in] clauses - list of clauses to process.
2099+ // / \param [in] args - block arguments (induction variable[s]) for the
2100+ // // region.
2101+ // / \param [in] outerCombined - is this an outer operation - prevents
2102+ // / privatization.
2103+ template <typename Op>
2104+ static void createBodyOfLoopOp (
2105+ Op &op, Fortran::lower::AbstractConverter &converter, mlir::Location &loc,
2106+ Fortran::lower::pft::Evaluation &eval,
2107+ const Fortran::parser::OmpClauseList *clauses = nullptr ,
2108+ const llvm::SmallVector<const Fortran::semantics::Symbol *> &args = {},
2109+ bool outerCombined = false , DataSharingProcessor *dsp = nullptr ) {
2110+ fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
2111+ // If an argument for the region is provided then create the block with that
2112+ // argument. Also update the symbol's address with the mlir argument value.
2113+ // e.g. For loops the argument is the induction variable. And all further
2114+ // uses of the induction variable should use this mlir value.
2115+ mlir::Operation *storeOp = nullptr ;
2116+ assert (args.size () > 0 );
2117+ std::size_t loopVarTypeSize = 0 ;
2118+ for (const Fortran::semantics::Symbol *arg : args)
2119+ loopVarTypeSize = std::max (loopVarTypeSize, arg->GetUltimate ().size ());
2120+ mlir::Type loopVarType = getLoopVarType (converter, loopVarTypeSize);
2121+ llvm::SmallVector<mlir::Type> tiv;
2122+ llvm::SmallVector<mlir::Location> locs;
2123+ for (int i = 0 ; i < (int )args.size (); i++) {
2124+ tiv.push_back (loopVarType);
2125+ locs.push_back (loc);
2126+ }
2127+ int offset = 0 ;
2128+ // The argument is not currently in memory, so make a temporary for the
2129+ // argument, and store it there, then bind that location to the argument.
2130+ for (const Fortran::semantics::Symbol *arg : args) {
2131+ mlir::Type symType = converter.genType (*arg);
2132+ mlir::Type symRefType = firOpBuilder.getRefType (symType);
2133+ tiv.push_back (symRefType);
2134+ locs.push_back (loc);
2135+ offset++;
2136+ }
2137+ firOpBuilder.createBlock (&op.getRegion (), {}, tiv, locs);
2138+
2139+ int argIndex = 0 ;
2140+ for (const Fortran::semantics::Symbol *arg : args) {
2141+ mlir::Value addrVal =
2142+ fir::getBase (op.getRegion ().front ().getArgument (argIndex+offset));
2143+ converter.bindSymbol (*arg, addrVal);
2144+ mlir::Type symType = converter.genType (*arg);
2145+ mlir::Value indexVal =
2146+ fir::getBase (op.getRegion ().front ().getArgument (argIndex));
2147+ mlir::Value cvtVal = firOpBuilder.createConvert (loc, symType, indexVal);
2148+ addrVal = converter.getSymbolAddress (*arg);
2149+ storeOp = firOpBuilder.create <fir::StoreOp>(loc, cvtVal, addrVal);
2150+ argIndex++;
2151+ }
2152+ // Set the insert for the terminator operation to go at the end of the
2153+ // block - this is either empty or the block with the stores above,
2154+ // the end of the block works for both.
2155+ mlir::Block &block = op.getRegion ().back ();
2156+ firOpBuilder.setInsertionPointToEnd (&block);
2157+
2158+ // If it is an unstructured region and is not the outer region of a combined
2159+ // construct, create empty blocks for all evaluations.
2160+ if (eval.lowerAsUnstructured () && !outerCombined)
2161+ Fortran::lower::createEmptyRegionBlocks<mlir::omp::TerminatorOp,
2162+ mlir::omp::YieldOp>(
2163+ firOpBuilder, eval.getNestedEvaluations ());
2164+
2165+ // Insert the terminator.
2166+ Fortran::lower::genOpenMPTerminator (firOpBuilder, op.getOperation (), loc);
2167+ // Reset the insert point to before the terminator.
2168+ resetBeforeTerminator (firOpBuilder, storeOp, block);
2169+
2170+ // Handle privatization. Do not privatize if this is the outer operation.
2171+ if (clauses && !outerCombined) {
2172+ constexpr bool isLoop = std::is_same_v<Op, mlir::omp::WsLoopOp> ||
2173+ std::is_same_v<Op, mlir::omp::SimdLoopOp>;
2174+ if (!dsp) {
2175+ DataSharingProcessor proc (converter, *clauses, eval);
2176+ proc.processStep1 ();
2177+ proc.processStep2 (op, isLoop);
2178+ } else {
2179+ if (isLoop && args.size () > 0 )
2180+ dsp->setLoopIV (converter.getSymbolAddress (*args[0 ]));
2181+ dsp->processStep2 (op, isLoop);
2182+ }
2183+
2184+ if (storeOp)
2185+ firOpBuilder.setInsertionPointAfter (storeOp);
2186+ }
2187+ }
2188+
20912189// / Create the body (block) for an OpenMP Operation.
20922190// /
20932191// / \param [in] op - the operation the body belongs to.
@@ -2914,7 +3012,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
29143012 const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
29153013 fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
29163014 llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, linearVars,
2917- linearStepVars, reductionVars;
3015+ linearStepVars, privateVars, reductionVars;
29183016 mlir::Value scheduleChunkClauseOperand;
29193017 mlir::IntegerAttr orderedClauseOperand;
29203018 mlir::omp::ClauseOrderKindAttr orderClauseOperand;
@@ -3023,9 +3121,23 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
30233121 return ;
30243122 }
30253123
3124+ // Collect the loops to collapse.
3125+ Fortran::lower::pft::Evaluation *doConstructEval =
3126+ &eval.getFirstNestedEvaluation ();
3127+ Fortran::lower::pft::Evaluation *doLoop =
3128+ &doConstructEval->getFirstNestedEvaluation ();
3129+ auto *doStmt = doLoop->getIf <Fortran::parser::NonLabelDoStmt>();
3130+ assert (doStmt && " Expected do loop to be in the nested evaluation" );
3131+ const auto &loopControl =
3132+ std::get<std::optional<Fortran::parser::LoopControl>>(doStmt->t );
3133+ const Fortran::parser::LoopControl::Bounds *bounds =
3134+ std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u );
3135+ assert (bounds && " Expected bounds for worksharing do loop" );
3136+ privateVars.push_back (converter.getSymbolAddress (*bounds->name .thing .symbol ));
3137+
30263138 auto wsLoopOp = firOpBuilder.create <mlir::omp::WsLoopOp>(
30273139 currentLocation, lowerBound, upperBound, step, linearVars, linearStepVars,
3028- reductionVars,
3140+ privateVars, reductionVars,
30293141 reductionDeclSymbols.empty ()
30303142 ? nullptr
30313143 : mlir::ArrayAttr::get (firOpBuilder.getContext (),
@@ -3061,7 +3173,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
30613173 wsLoopOp.setNowaitAttr (nowaitClauseOperand);
30623174 }
30633175
3064- createBodyOfOp <mlir::omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
3176+ createBodyOfLoopOp <mlir::omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
30653177 eval, &loopOpClauseList, iv,
30663178 /* outer=*/ false , &dsp);
30673179}
0 commit comments