@@ -2075,6 +2075,7 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
2075
2075
firOpBuilder.setInsertionPointToStart (firOpBuilder.getAllocaBlock ());
2076
2076
2077
2077
mlir::Type tempTy = converter.genType (*sym);
2078
+ llvm::outs () << " Temp type = " << tempTy << " \n " ;
2078
2079
mlir::Value temp = firOpBuilder.create <fir::AllocaOp>(
2079
2080
loc, tempTy, /* pinned=*/ true , /* lengthParams=*/ mlir::ValueRange{},
2080
2081
/* shapeParams*/ mlir::ValueRange{},
@@ -2088,6 +2089,103 @@ createAndSetPrivatizedLoopVar(Fortran::lower::AbstractConverter &converter,
2088
2089
return storeOp;
2089
2090
}
2090
2091
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
+
2091
2189
// / Create the body (block) for an OpenMP Operation.
2092
2190
// /
2093
2191
// / \param [in] op - the operation the body belongs to.
@@ -2914,7 +3012,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
2914
3012
const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
2915
3013
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder ();
2916
3014
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, linearVars,
2917
- linearStepVars, reductionVars;
3015
+ linearStepVars, privateVars, reductionVars;
2918
3016
mlir::Value scheduleChunkClauseOperand;
2919
3017
mlir::IntegerAttr orderedClauseOperand;
2920
3018
mlir::omp::ClauseOrderKindAttr orderClauseOperand;
@@ -3023,9 +3121,23 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
3023
3121
return ;
3024
3122
}
3025
3123
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
+
3026
3138
auto wsLoopOp = firOpBuilder.create <mlir::omp::WsLoopOp>(
3027
3139
currentLocation, lowerBound, upperBound, step, linearVars, linearStepVars,
3028
- reductionVars,
3140
+ privateVars, reductionVars,
3029
3141
reductionDeclSymbols.empty ()
3030
3142
? nullptr
3031
3143
: mlir::ArrayAttr::get (firOpBuilder.getContext (),
@@ -3061,7 +3173,7 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
3061
3173
wsLoopOp.setNowaitAttr (nowaitClauseOperand);
3062
3174
}
3063
3175
3064
- createBodyOfOp <mlir::omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
3176
+ createBodyOfLoopOp <mlir::omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
3065
3177
eval, &loopOpClauseList, iv,
3066
3178
/* outer=*/ false , &dsp);
3067
3179
}
0 commit comments