Skip to content

[flang][OpenMP] Add -f[no]-openmp-simd #150269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Aug 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -3731,14 +3731,20 @@ def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">,
def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">,
Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>,
Visibility<[ClangOption, CC1Option]>;
def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
def fopenmp_simd : Flag<["-"], "fopenmp-simd">,
Group<f_Group>,
Flags<[NoArgumentUnused]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Emit OpenMP code only for SIMD-based constructs.">;
def fopenmp_enable_irbuilder : Flag<["-"], "fopenmp-enable-irbuilder">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>,
HelpText<"Use the experimental OpenMP-IR-Builder codegen path.">;
def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>,
Flags<[NoArgumentUnused]>, Visibility<[ClangOption, CC1Option]>;
def fno_openmp_simd
: Flag<["-"], "fno-openmp-simd">,
Group<f_Group>,
Flags<[NoArgumentUnused]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Do not emit code for any OpenMP constructs.">;
def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>,
Flags<[NoArgumentUnused, HelpHidden]>, Visibility<[ClangOption, CC1Option]>;
def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>,
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,8 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,

if (Args.hasArg(options::OPT_fopenmp_force_usm))
CmdArgs.push_back("-fopenmp-force-usm");
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);

// FIXME: Clang supports a whole bunch more flags here.
break;
Expand All @@ -952,6 +954,9 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
<< A->getSpelling() << A->getValue();
break;
}
} else {
Args.AddLastArg(CmdArgs, options::OPT_fopenmp_simd,
options::OPT_fno_openmp_simd);
}

// Pass the path to compiler resource files.
Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Optimizer/OpenMP/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,9 @@ def GenericLoopConversionPass
];
}

def SimdOnlyPass : Pass<"omp-simd-only", "mlir::ModuleOp"> {
let summary = "Filters out non-simd OpenMP constructs";
let dependentDialects = ["mlir::omp::OpenMPDialect"];
}

#endif //FORTRAN_OPTIMIZER_OPENMP_PASSES
5 changes: 4 additions & 1 deletion flang/include/flang/Optimizer/Passes/Pipelines.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,16 @@ void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config);
void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm,
MLIRToLLVMPassPipelineConfig &pc);

/// Select which mode to enable OpenMP support in.
enum class EnableOpenMP { None, Simd, Full };

/// Create a pass pipeline for lowering from HLFIR to FIR
///
/// \param pm - MLIR pass manager that will hold the pipeline definition
/// \param optLevel - optimization level used for creating FIR optimization
/// passes pipeline
void createHLFIRToFIRPassPipeline(
mlir::PassManager &pm, bool enableOpenMP,
mlir::PassManager &pm, EnableOpenMP enableOpenMP,
llvm::OptimizationLevel optLevel = defaultOptLevel);

struct OpenMPFIRPassPipelineOpts {
Expand Down
16 changes: 16 additions & 0 deletions flang/include/flang/Semantics/openmp-directive-sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,22 @@ static const OmpDirectiveSet nestedWorkshareErrSet{
Directive::OMPD_taskloop,
} | workShareSet,
};

//===----------------------------------------------------------------------===//
// Misc directive sets
//===----------------------------------------------------------------------===//

// Simple standalone directives than can be erased by -fopenmp-simd.
static const OmpDirectiveSet simpleStandaloneNonSimdOnlySet{
Directive::OMPD_taskyield,
Directive::OMPD_barrier,
Directive::OMPD_ordered,
Directive::OMPD_target_enter_data,
Directive::OMPD_target_exit_data,
Directive::OMPD_target_update,
Directive::OMPD_taskwait,
};

} // namespace llvm::omp

#endif // FORTRAN_SEMANTICS_OPENMP_DIRECTIVE_SETS_H_
2 changes: 2 additions & 0 deletions flang/include/flang/Support/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ LANGOPT(OpenMPTeamSubscription, 1, 0)
LANGOPT(OpenMPNoThreadState, 1, 0)
/// Assume that no thread in a parallel region will encounter a parallel region
LANGOPT(OpenMPNoNestedParallelism, 1, 0)
/// Use SIMD only OpenMP support.
LANGOPT(OpenMPSimd, 1, false)

LANGOPT(VScaleMin, 32, 0) ///< Minimum vscale range value
LANGOPT(VScaleMax, 32, 0) ///< Maximum vscale range value
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
///< functions.
bool NSWOnLoopVarInc = true; ///< Add nsw flag to loop variable increments.
bool EnableOpenMP = false; ///< Enable OpenMP lowering.
bool EnableOpenMPSimd = false; ///< Enable OpenMP simd-only mode.
std::string InstrumentFunctionEntry =
""; ///< Name of the instrument-function that is called on each
///< function-entry
Expand Down
11 changes: 9 additions & 2 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1162,8 +1162,15 @@ static bool parseOpenMPArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
clang::DiagnosticsEngine &diags) {
llvm::opt::Arg *arg = args.getLastArg(clang::driver::options::OPT_fopenmp,
clang::driver::options::OPT_fno_openmp);
if (!arg || arg->getOption().matches(clang::driver::options::OPT_fno_openmp))
return true;
if (!arg ||
arg->getOption().matches(clang::driver::options::OPT_fno_openmp)) {
bool isSimdSpecified = args.hasFlag(
clang::driver::options::OPT_fopenmp_simd,
clang::driver::options::OPT_fno_openmp_simd, /*Default=*/false);
if (!isSimdSpecified)
return true;
res.getLangOpts().OpenMPSimd = 1;
}

unsigned numErrorsBefore = diags.getNumErrors();
llvm::Triple t(res.getTargetOpts().triple);
Expand Down
25 changes: 16 additions & 9 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ bool CodeGenAction::beginSourceFileAction() {
bool isOpenMPEnabled =
ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP);
bool isOpenMPSimd = ci.getInvocation().getLangOpts().OpenMPSimd;

fir::OpenMPFIRPassPipelineOpts opts;

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

// WARNING: This pipeline must be run immediately after the lowering to
// ensure that the FIR is correct with respect to OpenMP operations/
// attributes.
// WARNING: This pipeline must be run immediately after the lowering to
// ensure that the FIR is correct with respect to OpenMP operations/
// attributes.
if (isOpenMPEnabled || isOpenMPSimd)
fir::createOpenMPFIRPassPipeline(pm, opts);
}

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

fir::EnableOpenMP enableOpenMP = fir::EnableOpenMP::None;
if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP))
enableOpenMP = fir::EnableOpenMP::Full;
if (ci.getInvocation().getLangOpts().OpenMPSimd)
enableOpenMP = fir::EnableOpenMP::Simd;
// Create the pass pipeline
fir::createHLFIRToFIRPassPipeline(
pm,
ci.getInvocation().getFrontendOpts().features.IsEnabled(
Fortran::common::LanguageFeature::OpenMP),
level);
fir::createHLFIRToFIRPassPipeline(pm, enableOpenMP, level);
(void)mlir::applyPassManagerCLOptions(pm);

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

if (ci.getInvocation().getLangOpts().OpenMPSimd)
config.EnableOpenMPSimd = true;

if (ci.getInvocation().getLoweringOpts().getIntegerWrapAround())
config.NSWOnLoopVarInc = false;

Expand Down
14 changes: 9 additions & 5 deletions flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,11 +208,15 @@ void ClauseProcessor::processTODO(mlir::Location currentLocation,
if (!x)
return;
unsigned version = semaCtx.langOptions().OpenMPVersion;
TODO(currentLocation,
"Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +
" in " +
llvm::omp::getOpenMPDirectiveName(directive, version).upper() +
" construct");
bool isSimdDirective = llvm::omp::getOpenMPDirectiveName(directive, version)
.upper()
.find("SIMD") != llvm::StringRef::npos;
if (!semaCtx.langOptions().OpenMPSimd || isSimdDirective)
TODO(currentLocation,
"Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +
" in " +
llvm::omp::getOpenMPDirectiveName(directive, version).upper() +
" construct");
};

for (ClauseIterator it = clauses.begin(); it != clauses.end(); ++it)
Expand Down
54 changes: 36 additions & 18 deletions flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2262,7 +2262,8 @@ genOrderedOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
mlir::Location loc, const ConstructQueue &queue,
ConstructQueue::const_iterator item) {
TODO(loc, "OMPD_ordered");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(loc, "OMPD_ordered");
return nullptr;
}

Expand Down Expand Up @@ -2449,7 +2450,8 @@ genScopeOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
mlir::Location loc, const ConstructQueue &queue,
ConstructQueue::const_iterator item) {
TODO(loc, "Scope construct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(loc, "Scope construct");
return nullptr;
}

Expand Down Expand Up @@ -3276,7 +3278,8 @@ static mlir::omp::TaskloopOp genCompositeTaskloopSimd(
lower::pft::Evaluation &eval, mlir::Location loc,
const ConstructQueue &queue, ConstructQueue::const_iterator item) {
assert(std::distance(item, queue.end()) == 2 && "Invalid leaf constructs");
TODO(loc, "Composite TASKLOOP SIMD");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(loc, "Composite TASKLOOP SIMD");
return nullptr;
}

Expand Down Expand Up @@ -3448,8 +3451,10 @@ static void genOMPDispatch(lower::AbstractConverter &converter,
break;
case llvm::omp::Directive::OMPD_tile: {
unsigned version = semaCtx.langOptions().OpenMPVersion;
TODO(loc, "Unhandled loop directive (" +
llvm::omp::getOpenMPDirectiveName(dir, version) + ")");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(loc, "Unhandled loop directive (" +
llvm::omp::getOpenMPDirectiveName(dir, version) + ")");
break;
}
case llvm::omp::Directive::OMPD_unroll:
genUnrollOp(converter, symTable, stmtCtx, semaCtx, eval, loc, queue, item);
Expand Down Expand Up @@ -3484,35 +3489,40 @@ static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
const parser::OpenMPDeclarativeAllocate &declarativeAllocate) {
TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPDeclarativeAssumes &assumesConstruct) {
TODO(converter.getCurrentLocation(), "OpenMP ASSUMES declaration");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMP ASSUMES declaration");
}

static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
const parser::OmpDeclareVariantDirective &declareVariantDirective) {
TODO(converter.getCurrentLocation(), "OmpDeclareVariantDirective");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OmpDeclareVariantDirective");
}

static void genOMP(
lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
const parser::OpenMPDeclareReductionConstruct &declareReductionConstruct) {
TODO(converter.getCurrentLocation(), "OpenMPDeclareReductionConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDeclareReductionConstruct");
}

static void
genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval,
const parser::OpenMPDeclareSimdConstruct &declareSimdConstruct) {
TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDeclareSimdConstruct");
}

static void
Expand Down Expand Up @@ -3706,14 +3716,16 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
(void)objects;
(void)clauses;

TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDepobjConstruct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPInteropConstruct &interopConstruct) {
TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPInteropConstruct");
}

static void
Expand All @@ -3729,7 +3741,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPAllocatorsConstruct &allocsConstruct) {
TODO(converter.getCurrentLocation(), "OpenMPAllocatorsConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPAllocatorsConstruct");
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -3795,7 +3808,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
!std::holds_alternative<clause::Detach>(clause.u)) {
std::string name =
parser::ToUpperCaseLetters(llvm::omp::getOpenMPClauseName(clause.id));
TODO(clauseLocation, name + " clause is not implemented yet");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(clauseLocation, name + " clause is not implemented yet");
}
}

Expand All @@ -3811,7 +3825,8 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
lower::pft::Evaluation &eval,
const parser::OpenMPAssumeConstruct &assumeConstruct) {
mlir::Location clauseLocation = converter.genLocation(assumeConstruct.source);
TODO(clauseLocation, "OpenMP ASSUME construct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(clauseLocation, "OpenMP ASSUME construct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
Expand Down Expand Up @@ -3847,21 +3862,24 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPUtilityConstruct &) {
TODO(converter.getCurrentLocation(), "OpenMPUtilityConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPUtilityConstruct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPDispatchConstruct &) {
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPDispatchConstruct");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
semantics::SemanticsContext &semaCtx,
lower::pft::Evaluation &eval,
const parser::OpenMPExecutableAllocate &execAllocConstruct) {
TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
if (!semaCtx.langOptions().OpenMPSimd)
TODO(converter.getCurrentLocation(), "OpenMPExecutableAllocate");
}

static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable,
Expand Down
1 change: 1 addition & 0 deletions flang/lib/Optimizer/OpenMP/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_flang_library(FlangOpenMPTransforms
MarkDeclareTarget.cpp
LowerWorkshare.cpp
LowerNontemporal.cpp
SimdOnly.cpp

DEPENDS
FIRDialect
Expand Down
Loading