Skip to content

Commit e13ee61

Browse files
authored
[Flang][OpenMP] Separate creation of work-sharing and SIMD loops, NFC (#77757)
These two constructs were both handled in `genOMP` for loop constructs. There is some shared code between the two, but there are also enough differences to separate these two cases into individual functions. The shared code converting loop bounds and steps has been extracted into a separate function. Recursive lowering [1/5]
1 parent 2b23104 commit e13ee61

File tree

1 file changed

+154
-99
lines changed

1 file changed

+154
-99
lines changed

flang/lib/Lower/OpenMP.cpp

Lines changed: 154 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -2968,24 +2968,151 @@ genOMP(Fortran::lower::AbstractConverter &converter,
29682968
standaloneConstruct.u);
29692969
}
29702970

2971-
static void genOMP(Fortran::lower::AbstractConverter &converter,
2972-
Fortran::lower::pft::Evaluation &eval,
2973-
Fortran::semantics::SemanticsContext &semanticsContext,
2974-
const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
2971+
static void convertLoopBounds(Fortran::lower::AbstractConverter &converter,
2972+
mlir::Location loc,
2973+
llvm::SmallVectorImpl<mlir::Value> &lowerBound,
2974+
llvm::SmallVectorImpl<mlir::Value> &upperBound,
2975+
llvm::SmallVectorImpl<mlir::Value> &step,
2976+
std::size_t loopVarTypeSize) {
2977+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
2978+
// The types of lower bound, upper bound, and step are converted into the
2979+
// type of the loop variable if necessary.
2980+
mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
2981+
for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) {
2982+
lowerBound[it] =
2983+
firOpBuilder.createConvert(loc, loopVarType, lowerBound[it]);
2984+
upperBound[it] =
2985+
firOpBuilder.createConvert(loc, loopVarType, upperBound[it]);
2986+
step[it] = firOpBuilder.createConvert(loc, loopVarType, step[it]);
2987+
}
2988+
}
2989+
2990+
static void
2991+
createSimdLoop(Fortran::lower::AbstractConverter &converter,
2992+
Fortran::lower::pft::Evaluation &eval,
2993+
llvm::omp::Directive ompDirective,
2994+
const Fortran::parser::OmpClauseList &loopOpClauseList,
2995+
mlir::Location loc) {
2996+
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
2997+
DataSharingProcessor dsp(converter, loopOpClauseList, eval);
2998+
dsp.processStep1();
2999+
3000+
Fortran::lower::StatementContext stmtCtx;
3001+
mlir::Value scheduleChunkClauseOperand, ifClauseOperand;
3002+
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars;
3003+
llvm::SmallVector<mlir::Value> alignedVars, nontemporalVars;
3004+
llvm::SmallVector<const Fortran::semantics::Symbol *> iv;
3005+
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
3006+
mlir::omp::ClauseOrderKindAttr orderClauseOperand;
3007+
mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand;
3008+
std::size_t loopVarTypeSize;
3009+
3010+
ClauseProcessor cp(converter, loopOpClauseList);
3011+
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv,
3012+
loopVarTypeSize);
3013+
cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
3014+
cp.processReduction(loc, reductionVars, reductionDeclSymbols);
3015+
cp.processTODO<Fortran::parser::OmpClause::Linear,
3016+
Fortran::parser::OmpClause::Order>(loc, ompDirective);
3017+
cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd,
3018+
ifClauseOperand);
3019+
cp.processSimdlen(simdlenClauseOperand);
3020+
cp.processSafelen(safelenClauseOperand);
3021+
cp.processTODO<Fortran::parser::OmpClause::Aligned,
3022+
Fortran::parser::OmpClause::Allocate,
3023+
Fortran::parser::OmpClause::Nontemporal>(loc, ompDirective);
3024+
3025+
convertLoopBounds(converter, loc, lowerBound, upperBound, step,
3026+
loopVarTypeSize);
3027+
3028+
mlir::TypeRange resultType;
3029+
auto simdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
3030+
loc, resultType, lowerBound, upperBound, step, alignedVars,
3031+
/*alignment_values=*/nullptr, ifClauseOperand, nontemporalVars,
3032+
orderClauseOperand, simdlenClauseOperand, safelenClauseOperand,
3033+
/*inclusive=*/firOpBuilder.getUnitAttr());
3034+
createBodyOfOp<mlir::omp::SimdLoopOp>(simdLoopOp, converter, loc, eval,
3035+
&loopOpClauseList, iv,
3036+
/*outer=*/false, &dsp);
3037+
}
3038+
3039+
static void createWsLoop(Fortran::lower::AbstractConverter &converter,
3040+
Fortran::lower::pft::Evaluation &eval,
3041+
llvm::omp::Directive ompDirective,
3042+
const Fortran::parser::OmpClauseList &beginClauseList,
3043+
const Fortran::parser::OmpClauseList *endClauseList,
3044+
mlir::Location loc) {
29753045
fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder();
2976-
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, linearVars,
2977-
linearStepVars, reductionVars;
3046+
DataSharingProcessor dsp(converter, beginClauseList, eval);
3047+
dsp.processStep1();
3048+
3049+
Fortran::lower::StatementContext stmtCtx;
29783050
mlir::Value scheduleChunkClauseOperand;
2979-
mlir::IntegerAttr orderedClauseOperand;
3051+
llvm::SmallVector<mlir::Value> lowerBound, upperBound, step, reductionVars;
3052+
llvm::SmallVector<mlir::Value> linearVars, linearStepVars;
3053+
llvm::SmallVector<const Fortran::semantics::Symbol *> iv;
3054+
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
29803055
mlir::omp::ClauseOrderKindAttr orderClauseOperand;
29813056
mlir::omp::ClauseScheduleKindAttr scheduleValClauseOperand;
2982-
mlir::omp::ScheduleModifierAttr scheduleModClauseOperand;
29833057
mlir::UnitAttr nowaitClauseOperand, scheduleSimdClauseOperand;
2984-
llvm::SmallVector<mlir::Attribute> reductionDeclSymbols;
2985-
Fortran::lower::StatementContext stmtCtx;
3058+
mlir::IntegerAttr orderedClauseOperand;
3059+
mlir::omp::ScheduleModifierAttr scheduleModClauseOperand;
29863060
std::size_t loopVarTypeSize;
2987-
llvm::SmallVector<const Fortran::semantics::Symbol *> iv;
29883061

3062+
ClauseProcessor cp(converter, beginClauseList);
3063+
cp.processCollapse(loc, eval, lowerBound, upperBound, step, iv,
3064+
loopVarTypeSize);
3065+
cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
3066+
cp.processReduction(loc, reductionVars, reductionDeclSymbols);
3067+
cp.processTODO<Fortran::parser::OmpClause::Linear,
3068+
Fortran::parser::OmpClause::Order>(loc, ompDirective);
3069+
3070+
convertLoopBounds(converter, loc, lowerBound, upperBound, step,
3071+
loopVarTypeSize);
3072+
3073+
auto wsLoopOp = firOpBuilder.create<mlir::omp::WsLoopOp>(
3074+
loc, lowerBound, upperBound, step, linearVars, linearStepVars,
3075+
reductionVars,
3076+
reductionDeclSymbols.empty()
3077+
? nullptr
3078+
: mlir::ArrayAttr::get(firOpBuilder.getContext(),
3079+
reductionDeclSymbols),
3080+
scheduleValClauseOperand, scheduleChunkClauseOperand,
3081+
/*schedule_modifiers=*/nullptr,
3082+
/*simd_modifier=*/nullptr, nowaitClauseOperand, orderedClauseOperand,
3083+
orderClauseOperand,
3084+
/*inclusive=*/firOpBuilder.getUnitAttr());
3085+
3086+
// Handle attribute based clauses.
3087+
if (cp.processOrdered(orderedClauseOperand))
3088+
wsLoopOp.setOrderedValAttr(orderedClauseOperand);
3089+
3090+
if (cp.processSchedule(scheduleValClauseOperand, scheduleModClauseOperand,
3091+
scheduleSimdClauseOperand)) {
3092+
wsLoopOp.setScheduleValAttr(scheduleValClauseOperand);
3093+
wsLoopOp.setScheduleModifierAttr(scheduleModClauseOperand);
3094+
wsLoopOp.setSimdModifierAttr(scheduleSimdClauseOperand);
3095+
}
3096+
// In FORTRAN `nowait` clause occur at the end of `omp do` directive.
3097+
// i.e
3098+
// !$omp do
3099+
// <...>
3100+
// !$omp end do nowait
3101+
if (endClauseList) {
3102+
if (ClauseProcessor(converter, *endClauseList)
3103+
.processNowait(nowaitClauseOperand))
3104+
wsLoopOp.setNowaitAttr(nowaitClauseOperand);
3105+
}
3106+
3107+
createBodyOfOp<mlir::omp::WsLoopOp>(wsLoopOp, converter, loc, eval,
3108+
&beginClauseList, iv,
3109+
/*outer=*/false, &dsp);
3110+
}
3111+
3112+
static void genOMP(Fortran::lower::AbstractConverter &converter,
3113+
Fortran::lower::pft::Evaluation &eval,
3114+
Fortran::semantics::SemanticsContext &semanticsContext,
3115+
const Fortran::parser::OpenMPLoopConstruct &loopConstruct) {
29893116
const auto &beginLoopDirective =
29903117
std::get<Fortran::parser::OmpBeginLoopDirective>(loopConstruct.t);
29913118
const auto &loopOpClauseList =
@@ -2995,6 +3122,17 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
29953122
const auto ompDirective =
29963123
std::get<Fortran::parser::OmpLoopDirective>(beginLoopDirective.t).v;
29973124

3125+
const auto *endClauseList = [&]() {
3126+
using RetTy = const Fortran::parser::OmpClauseList *;
3127+
if (auto &endLoopDirective =
3128+
std::get<std::optional<Fortran::parser::OmpEndLoopDirective>>(
3129+
loopConstruct.t)) {
3130+
return RetTy(
3131+
&std::get<Fortran::parser::OmpClauseList>((*endLoopDirective).t));
3132+
}
3133+
return RetTy();
3134+
}();
3135+
29983136
bool validDirective = false;
29993137
if (llvm::omp::topTaskloopSet.test(ompDirective)) {
30003138
validDirective = true;
@@ -3033,97 +3171,14 @@ static void genOMP(Fortran::lower::AbstractConverter &converter,
30333171
")");
30343172
}
30353173

3036-
DataSharingProcessor dsp(converter, loopOpClauseList, eval);
3037-
dsp.processStep1();
3038-
3039-
ClauseProcessor cp(converter, loopOpClauseList);
3040-
cp.processCollapse(currentLocation, eval, lowerBound, upperBound, step, iv,
3041-
loopVarTypeSize);
3042-
cp.processScheduleChunk(stmtCtx, scheduleChunkClauseOperand);
3043-
cp.processReduction(currentLocation, reductionVars, reductionDeclSymbols);
3044-
cp.processTODO<Fortran::parser::OmpClause::Linear,
3045-
Fortran::parser::OmpClause::Order>(currentLocation,
3046-
ompDirective);
3047-
3048-
// The types of lower bound, upper bound, and step are converted into the
3049-
// type of the loop variable if necessary.
3050-
mlir::Type loopVarType = getLoopVarType(converter, loopVarTypeSize);
3051-
for (unsigned it = 0; it < (unsigned)lowerBound.size(); it++) {
3052-
lowerBound[it] = firOpBuilder.createConvert(currentLocation, loopVarType,
3053-
lowerBound[it]);
3054-
upperBound[it] = firOpBuilder.createConvert(currentLocation, loopVarType,
3055-
upperBound[it]);
3056-
step[it] =
3057-
firOpBuilder.createConvert(currentLocation, loopVarType, step[it]);
3058-
}
3059-
30603174
// 2.9.3.1 SIMD construct
30613175
if (llvm::omp::allSimdSet.test(ompDirective)) {
3062-
llvm::SmallVector<mlir::Value> alignedVars, nontemporalVars;
3063-
mlir::Value ifClauseOperand;
3064-
mlir::IntegerAttr simdlenClauseOperand, safelenClauseOperand;
3065-
cp.processIf(Fortran::parser::OmpIfClause::DirectiveNameModifier::Simd,
3066-
ifClauseOperand);
3067-
cp.processSimdlen(simdlenClauseOperand);
3068-
cp.processSafelen(safelenClauseOperand);
3069-
cp.processTODO<Fortran::parser::OmpClause::Aligned,
3070-
Fortran::parser::OmpClause::Allocate,
3071-
Fortran::parser::OmpClause::Nontemporal>(currentLocation,
3072-
ompDirective);
3073-
3074-
mlir::TypeRange resultType;
3075-
auto simdLoopOp = firOpBuilder.create<mlir::omp::SimdLoopOp>(
3076-
currentLocation, resultType, lowerBound, upperBound, step, alignedVars,
3077-
/*alignment_values=*/nullptr, ifClauseOperand, nontemporalVars,
3078-
orderClauseOperand, simdlenClauseOperand, safelenClauseOperand,
3079-
/*inclusive=*/firOpBuilder.getUnitAttr());
3080-
createBodyOfOp<mlir::omp::SimdLoopOp>(
3081-
simdLoopOp, converter, currentLocation, eval, &loopOpClauseList, iv,
3082-
/*outer=*/false, &dsp);
3083-
return;
3084-
}
3085-
3086-
auto wsLoopOp = firOpBuilder.create<mlir::omp::WsLoopOp>(
3087-
currentLocation, lowerBound, upperBound, step, linearVars, linearStepVars,
3088-
reductionVars,
3089-
reductionDeclSymbols.empty()
3090-
? nullptr
3091-
: mlir::ArrayAttr::get(firOpBuilder.getContext(),
3092-
reductionDeclSymbols),
3093-
scheduleValClauseOperand, scheduleChunkClauseOperand,
3094-
/*schedule_modifiers=*/nullptr,
3095-
/*simd_modifier=*/nullptr, nowaitClauseOperand, orderedClauseOperand,
3096-
orderClauseOperand,
3097-
/*inclusive=*/firOpBuilder.getUnitAttr());
3098-
3099-
// Handle attribute based clauses.
3100-
if (cp.processOrdered(orderedClauseOperand))
3101-
wsLoopOp.setOrderedValAttr(orderedClauseOperand);
3102-
3103-
if (cp.processSchedule(scheduleValClauseOperand, scheduleModClauseOperand,
3104-
scheduleSimdClauseOperand)) {
3105-
wsLoopOp.setScheduleValAttr(scheduleValClauseOperand);
3106-
wsLoopOp.setScheduleModifierAttr(scheduleModClauseOperand);
3107-
wsLoopOp.setSimdModifierAttr(scheduleSimdClauseOperand);
3108-
}
3109-
// In FORTRAN `nowait` clause occur at the end of `omp do` directive.
3110-
// i.e
3111-
// !$omp do
3112-
// <...>
3113-
// !$omp end do nowait
3114-
if (const auto &endClauseList =
3115-
std::get<std::optional<Fortran::parser::OmpEndLoopDirective>>(
3116-
loopConstruct.t)) {
3117-
const auto &clauseList =
3118-
std::get<Fortran::parser::OmpClauseList>((*endClauseList).t);
3119-
if (ClauseProcessor(converter, clauseList)
3120-
.processNowait(nowaitClauseOperand))
3121-
wsLoopOp.setNowaitAttr(nowaitClauseOperand);
3176+
createSimdLoop(converter, eval, ompDirective, loopOpClauseList,
3177+
currentLocation);
3178+
} else {
3179+
createWsLoop(converter, eval, ompDirective, loopOpClauseList, endClauseList,
3180+
currentLocation);
31223181
}
3123-
3124-
createBodyOfOp<mlir::omp::WsLoopOp>(wsLoopOp, converter, currentLocation,
3125-
eval, &loopOpClauseList, iv,
3126-
/*outer=*/false, &dsp);
31273182
}
31283183

31293184
static void

0 commit comments

Comments
 (0)