Skip to content

Commit 80afe56

Browse files
committed
[flang][OpenMP] Add -f[no]-openmp-simd
Both clang and gfortran support the -fopenmp-simd flag, which enables OpenMP support only for simd constructs, while disabling the rest of OpenMP. Add a new SimdOnly flang OpenMP IR pass which rewrites generated OpenMP FIR to remove all constructs except for omp.simd constructs, and constructs nested under them. With this approach, the logic required to make the flag work can be self-contained within the pass, as opposed to being scattered all over the lowering code. The flag is expected to have no effect if -fopenmp is passed explicitly, and is only expected to remove OpenMP constructs, not things like OpenMP library functions calls. This matches the behaviour of other compilers. Signed-off-by: Kajetan Puchalski <[email protected]>
1 parent 372d86d commit 80afe56

File tree

18 files changed

+1263
-141
lines changed

18 files changed

+1263
-141
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,14 +3731,19 @@ def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">,
37313731
def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">,
37323732
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>,
37333733
Visibility<[ClangOption, CC1Option]>;
3734-
def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>,
3735-
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
3736-
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
3734+
def fopenmp_simd : Flag<["-"], "fopenmp-simd">,
3735+
Group<f_Group>,
3736+
Flags<[NoArgumentUnused]>,
3737+
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
3738+
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
37373739
def fopenmp_enable_irbuilder : Flag<["-"], "fopenmp-enable-irbuilder">, Group<f_Group>,
37383740
Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
37393741
HelpText<"Use the experimental OpenMP-IR-Builder codegen path.">;
3740-
def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>,
3741-
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>;
3742+
def fno_openmp_simd
3743+
: Flag<["-"], "fno-openmp-simd">,
3744+
Group<f_Group>,
3745+
Flags<[NoArgumentUnused]>,
3746+
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>;
37423747
def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>,
37433748
Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>;
37443749
def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>,

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
937937

938938
if (Args.hasArg(options::OPT_fopenmp_force_usm))
939939
CmdArgs.push_back("-fopenmp-force-usm");
940+
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
941+
options::OPT_fno_openmp_simd);
940942

941943
// FIXME: Clang supports a whole bunch more flags here.
942944
break;
@@ -952,6 +954,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
952954
<< A->getSpelling() << A->getValue();
953955
break;
954956
}
957+
} else {
958+
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
959+
options::OPT_fno_openmp_simd);
955960
}
956961

957962
// Pass the path to compiler resource files.

flang/include/flang/Optimizer/OpenMP/Passes.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,9 @@ def GenericLoopConversionPass
112112
];
113113
}
114114

115+
def SimdOnlyPass : Pass<"omp-simd-only", "mlir::func::FuncOp"> {
116+
let summary = "Filters out non-simd OpenMP constructs";
117+
let dependentDialects = ["mlir::omp::OpenMPDialect"];
118+
}
119+
115120
#endif //FORTRAN_OPTIMIZER_OPENMP_PASSES

flang/include/flang/Optimizer/Passes/Pipelines.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,16 @@ void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config);
119119
void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
120120
MLIRToLLVMPassPipelineConfig &pc);
121121

122+
/// Select which mode to enable OpenMP support in.
123+
enum class EnableOpenMP { None, Simd, Full };
124+
122125
/// Create a pass pipeline for lowering from HLFIR to FIR
123126
///
124127
/// \param pm - MLIR pass manager that will hold the pipeline definition
125128
/// \param optLevel - optimization level used for creating FIR optimization
126129
/// passes pipeline
127130
void createHLFIRToFIRPassPipeline(
128-
mlir::PassManager &pm, bool enableOpenMP,
131+
mlir::PassManager &pm, EnableOpenMP enableOpenMP,
129132
llvm::OptimizationLevel optLevel = defaultOptLevel);
130133

131134
struct OpenMPFIRPassPipelineOpts {

flang/include/flang/Optimizer/Transforms/Utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ void genMinMaxlocReductionLoop(fir::FirOpBuilder &builder, mlir::Value array,
3333
mlir::Type maskElemType, mlir::Value resultArr,
3434
bool maskMayBeLogicalScalar);
3535

36+
std::pair<mlir::Block *, mlir::Block *>
37+
convertDoLoopToCFG(DoLoopOp loop, mlir::PatternRewriter &rewriter, bool setNSW,
38+
bool forceLoopToExecuteOnce);
39+
3640
} // namespace fir
3741

3842
#endif // FORTRAN_OPTIMIZER_TRANSFORMS_UTILS_H

flang/include/flang/Support/LangOptions.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ LANGOPT(OpenMPTeamSubscription, 1, 0)
5858
LANGOPT(OpenMPNoThreadState, 1, 0)
5959
/// Assume that no thread in a parallel region will encounter a parallel region
6060
LANGOPT(OpenMPNoNestedParallelism, 1, 0)
61+
/// Use SIMD only OpenMP support.
62+
LANGOPT(OpenMPSimd, 1, false)
6163

6264
LANGOPT(VScaleMin, 32, 0) ///< Minimum vscale range value
6365
LANGOPT(VScaleMax, 32, 0) ///< Maximum vscale range value

flang/include/flang/Tools/CrossToolHelpers.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
134134
///< functions.
135135
bool NSWOnLoopVarInc = true; ///< Add nsw flag to loop variable increments.
136136
bool EnableOpenMP = false; ///< Enable OpenMP lowering.
137+
bool EnableOpenMPSimd = false; ///< Enable OpenMP simd-only mode.
137138
std::string InstrumentFunctionEntry =
138139
""; ///< Name of the instrument-function that is called on each
139140
///< function-entry

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,8 +1162,15 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
11621162
clang::DiagnosticsEngine &diags) {
11631163
llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fopenmp,
11641164
clang::driver::options::OPT_fno_openmp);
1165-
if (!arg || arg->getOption().matches(clang::driver::options::OPT_fno_openmp))
1166-
return true;
1165+
if (!arg ||
1166+
arg->getOption().matches(clang::driver::options::OPT_fno_openmp)) {
1167+
bool isSimdSpecified = args.hasFlag(
1168+
clang::driver::options::OPT_fopenmp_simd,
1169+
clang::driver::options::OPT_fno_openmp_simd, /*Default=*/false);
1170+
if (!isSimdSpecified)
1171+
return true;
1172+
res.getLangOpts().OpenMPSimd = 1;
1173+
}
11671174

11681175
unsigned numErrorsBefore = diags.getNumErrors();
11691176
llvm::Triple t(res.getTargetOpts().triple);

flang/lib/Frontend/FrontendActions.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ bool CodeGenAction::beginSourceFileAction() {
298298
bool isOpenMPEnabled =
299299
ci.getInvocation().getFrontendOpts().features.IsEnabled(
300300
Fortran::common::LanguageFeature::OpenMP);
301+
bool isOpenMPSimd = ci.getInvocation().getLangOpts().OpenMPSimd;
301302

302303
fir::OpenMPFIRPassPipelineOpts opts;
303304

@@ -329,12 +330,13 @@ bool CodeGenAction::beginSourceFileAction() {
329330
if (auto offloadMod = llvm::dyn_cast<mlir::omp::OffloadModuleInterface>(
330331
mlirModule->getOperation()))
331332
opts.isTargetDevice = offloadMod.getIsTargetDevice();
333+
}
332334

333-
// WARNING: This pipeline must be run immediately after the lowering to
334-
// ensure that the FIR is correct with respect to OpenMP operations/
335-
// attributes.
335+
// WARNING: This pipeline must be run immediately after the lowering to
336+
// ensure that the FIR is correct with respect to OpenMP operations/
337+
// attributes.
338+
if (isOpenMPEnabled || isOpenMPSimd)
336339
fir::createOpenMPFIRPassPipeline(pm, opts);
337-
}
338340

339341
pm.enableVerifier(/*verifyPasses=*/true);
340342
pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
@@ -617,12 +619,14 @@ void CodeGenAction::lowerHLFIRToFIR() {
617619
pm.addPass(std::make_unique<Fortran::lower::VerifierPass>());
618620
pm.enableVerifier(/*verifyPasses=*/true);
619621

622+
fir::EnableOpenMP enableOpenMP = fir::EnableOpenMP::None;
623+
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
624+
Fortran::common::LanguageFeature::OpenMP))
625+
enableOpenMP = fir::EnableOpenMP::Full;
626+
if (ci.getInvocation().getLangOpts().OpenMPSimd)
627+
enableOpenMP = fir::EnableOpenMP::Simd;
620628
// Create the pass pipeline
621-
fir::createHLFIRToFIRPassPipeline(
622-
pm,
623-
ci.getInvocation().getFrontendOpts().features.IsEnabled(
624-
Fortran::common::LanguageFeature::OpenMP),
625-
level);
629+
fir::createHLFIRToFIRPassPipeline(pm, enableOpenMP, level);
626630
(void)mlir::applyPassManagerCLOptions(pm);
627631

628632
mlir::TimingScope timingScopeMLIRPasses = timingScopeRoot.nest(
@@ -748,6 +752,9 @@ void CodeGenAction::generateLLVMIR() {
748752
Fortran::common::LanguageFeature::OpenMP))
749753
config.EnableOpenMP = true;
750754

755+
if (ci.getInvocation().getLangOpts().OpenMPSimd)
756+
config.EnableOpenMPSimd = true;
757+
751758
if (ci.getInvocation().getLoweringOpts().getIntegerWrapAround())
752759
config.NSWOnLoopVarInc = false;
753760

flang/lib/Lower/OpenMP/ClauseProcessor.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,12 @@ void ClauseProcessor::processTODO(mlir::Location currentLocation,
208208
if (!x)
209209
return;
210210
unsigned version = semaCtx.langOptions().OpenMPVersion;
211-
TODO(currentLocation,
212-
"Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +
213-
" in " +
214-
llvm::omp::getOpenMPDirectiveName(directive, version).upper() +
215-
" construct");
211+
if (!semaCtx.langOptions().OpenMPSimd)
212+
TODO(currentLocation,
213+
"Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +
214+
" in " +
215+
llvm::omp::getOpenMPDirectiveName(directive, version).upper() +
216+
" construct");
216217
};
217218

218219
for (ClauseIterator it = clauses.begin(); it != clauses.end(); ++it)

0 commit comments

Comments
 (0)