Author: Tom Eccles Date: 2023-06-01T19:29:16Z New Revision: 39ecf9d8a1533a434bb9544a1bc275c4d02e2efb
URL: https://github.com/llvm/llvm-project/commit/39ecf9d8a1533a434bb9544a1bc275c4d02e2efb DIFF: https://github.com/llvm/llvm-project/commit/39ecf9d8a1533a434bb9544a1bc275c4d02e2efb.diff LOG: [flang][hlfir] Separate -emit-fir and -emit-hlfir for flang-new In review for https://reviews.llvm.org/D146278, @vzakhari asked to separate -emit-fir and -emit-hlfir. This will allow FIR to be easily outputted after the HLFIR passes have been run. The new semantics are as follows: | Action | -flang-experimental-hlfir? | Result | | =========== | ========================== | =============================== | | -emit-hlfir | N | Outputs HLFIR | | -emit-hlfir | Y | Outputs HLFIR | | -emit-fir | N | Outputs FIR, using old lowering | | -emit-fir | Y | Outputs FIR, lowering via HLFIR | A patch for bbc will follow. Differential Revision: https://reviews.llvm.org/D151088 Added: Modified: clang/include/clang/Driver/Options.td flang/include/flang/Frontend/FrontendActions.h flang/include/flang/Frontend/FrontendOptions.h flang/lib/Frontend/CompilerInvocation.cpp flang/lib/Frontend/FrontendActions.cpp flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp flang/test/Driver/driver-help.f90 flang/test/HLFIR/flang-experimental-hlfir-flag.f90 Removed: ################################################################################ diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 41bd1c00eb229..b77fec6720792 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -5268,9 +5268,12 @@ def fno_reformat : Flag<["-"], "fno-reformat">, Group<Preprocessor_Group>, HelpText<"Dump the cooked character stream in -E mode">; defm analyzed_objects_for_unparse : OptOutFC1FFlag<"analyzed-objects-for-unparse", "", "Do not use the analyzed objects when unparsing">; -def emit_mlir : Flag<["-"], "emit-mlir">, Group<Action_Group>, - HelpText<"Build the parse tree, then lower it to MLIR">; -def emit_fir : Flag<["-"], "emit-fir">, Alias<emit_mlir>; +def emit_fir : Flag<["-"], "emit-fir">, Group<Action_Group>, + HelpText<"Build the parse tree, then lower it to FIR">; +def emit_mlir : Flag<["-"], "emit-mlir">, Alias<emit_fir>; + +def emit_hlfir : Flag<["-"], "emit-hlfir">, Group<Action_Group>, + HelpText<"Build the parse tree, then lower it to HLFIR">; } // let Flags = [FC1Option, FlangOnlyOption] diff --git a/flang/include/flang/Frontend/FrontendActions.h b/flang/include/flang/Frontend/FrontendActions.h index 2b96125e41639..8272e0729ce3f 100644 --- a/flang/include/flang/Frontend/FrontendActions.h +++ b/flang/include/flang/Frontend/FrontendActions.h @@ -191,7 +191,8 @@ enum class BackendActionTy { Backend_EmitObj, ///< Emit native object files Backend_EmitBC, ///< Emit LLVM bitcode files Backend_EmitLL, ///< Emit human-readable LLVM assembly - Backend_EmitMLIR ///< Emit MLIR files + Backend_EmitFIR, ///< Emit FIR files, possibly lowering via HLFIR + Backend_EmitHLFIR, ///< Emit HLFIR files before any passes run }; /// Abstract base class for actions that generate code (MLIR, LLVM IR, assembly @@ -224,6 +225,9 @@ class CodeGenAction : public FrontendAction { /// Embeds offload objects given with specified with -fembed-offload-object void embedOffloadObjects(); + /// Runs pass pipeline to lower HLFIR into FIR + void lowerHLFIRToFIR(); + /// Generates an LLVM IR module from CodeGenAction::mlirModule and saves it /// in CodeGenAction::llvmModule. void generateLLVMIR(); @@ -236,9 +240,14 @@ class CodeGenAction : public FrontendAction { ~CodeGenAction() override; }; -class EmitMLIRAction : public CodeGenAction { +class EmitFIRAction : public CodeGenAction { +public: + EmitFIRAction() : CodeGenAction(BackendActionTy::Backend_EmitFIR) {} +}; + +class EmitHLFIRAction : public CodeGenAction { public: - EmitMLIRAction() : CodeGenAction(BackendActionTy::Backend_EmitMLIR) {} + EmitHLFIRAction() : CodeGenAction(BackendActionTy::Backend_EmitHLFIR) {} }; class EmitLLVMAction : public CodeGenAction { diff --git a/flang/include/flang/Frontend/FrontendOptions.h b/flang/include/flang/Frontend/FrontendOptions.h index 4691dfe87a731..06b1318f243b0 100644 --- a/flang/include/flang/Frontend/FrontendOptions.h +++ b/flang/include/flang/Frontend/FrontendOptions.h @@ -34,8 +34,11 @@ enum ActionKind { /// -fsyntax-only ParseSyntaxOnly, - /// Emit a .mlir file - EmitMLIR, + /// Emit FIR mlir file + EmitFIR, + + /// Emit HLFIR mlir file + EmitHLFIR, /// Emit an .ll file EmitLLVM, diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index 98a87143f0f6d..02973178d9c28 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -306,8 +306,11 @@ static bool parseFrontendArgs(FrontendOptions &opts, llvm::opt::ArgList &args, case clang::driver::options::OPT_fsyntax_only: opts.programAction = ParseSyntaxOnly; break; - case clang::driver::options::OPT_emit_mlir: - opts.programAction = EmitMLIR; + case clang::driver::options::OPT_emit_fir: + opts.programAction = EmitFIR; + break; + case clang::driver::options::OPT_emit_hlfir: + opts.programAction = EmitHLFIR; break; case clang::driver::options::OPT_emit_llvm: opts.programAction = EmitLLVM; @@ -911,7 +914,8 @@ bool CompilerInvocation::createFromArgs( } // -flang-experimental-hlfir - if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir)) { + if (args.hasArg(clang::driver::options::OPT_flang_experimental_hlfir) || + args.hasArg(clang::driver::options::OPT_emit_hlfir)) { res.loweringOpts.setLowerToHighLevelFIR(true); } diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index efe6c25b826e6..415ce42c20d13 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -647,6 +647,34 @@ mapToLevel(const Fortran::frontend::CodeGenOptions &opts) { } } +// Lower using HLFIR then run the FIR to HLFIR pipeline +void CodeGenAction::lowerHLFIRToFIR() { + assert(mlirModule && "The MLIR module has not been generated yet."); + + CompilerInstance &ci = this->getInstance(); + auto opts = ci.getInvocation().getCodeGenOpts(); + llvm::OptimizationLevel level = mapToLevel(opts); + + fir::support::loadDialects(*mlirCtx); + + // Set-up the MLIR pass manager + mlir::PassManager pm((*mlirModule)->getName(), + mlir::OpPassManager::Nesting::Implicit); + + pm.addPass(std::make_unique<Fortran::lower::VerifierPass>()); + pm.enableVerifier(/*verifyPasses=*/true); + + // Create the pass pipeline + fir::createHLFIRToFIRPassPipeline(pm, level); + (void)mlir::applyPassManagerCLOptions(pm); + + if (!mlir::succeeded(pm.run(*mlirModule))) { + unsigned diagID = ci.getDiagnostics().getCustomDiagID( + clang::DiagnosticsEngine::Error, "Lowering to FIR failed"); + ci.getDiagnostics().Report(diagID); + } +} + // Lower the previously generated MLIR module into an LLVM IR module void CodeGenAction::generateLLVMIR() { assert(mlirModule && "The MLIR module has not been generated yet."); @@ -751,7 +779,9 @@ getOutputStream(CompilerInstance &ci, llvm::StringRef inFile, case BackendActionTy::Backend_EmitLL: return ci.createDefaultOutputFile( /*Binary=*/false, inFile, /*extension=*/"ll"); - case BackendActionTy::Backend_EmitMLIR: + case BackendActionTy::Backend_EmitFIR: + LLVM_FALLTHROUGH; + case BackendActionTy::Backend_EmitHLFIR: return ci.createDefaultOutputFile( /*Binary=*/false, inFile, /*extension=*/"mlir"); case BackendActionTy::Backend_EmitBC: @@ -914,7 +944,17 @@ void CodeGenAction::executeAction() { } } - if (action == BackendActionTy::Backend_EmitMLIR) { + if (action == BackendActionTy::Backend_EmitFIR) { + if (ci.getInvocation().getLoweringOpts().getLowerToHighLevelFIR()) { + lowerHLFIRToFIR(); + } + mlirModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream()); + return; + } + + if (action == BackendActionTy::Backend_EmitHLFIR) { + assert(ci.getInvocation().getLoweringOpts().getLowerToHighLevelFIR() && + "Lowering must have been configured to emit HLFIR"); mlirModule->print(ci.isOutputStreamNull() ? *os : ci.getOutputStream()); return; } diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp index b99d2b7196da3..df7876fdcb251 100644 --- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -40,8 +40,10 @@ createFrontendAction(CompilerInstance &ci) { return std::make_unique<PrintPreprocessedAction>(); case ParseSyntaxOnly: return std::make_unique<ParseSyntaxOnlyAction>(); - case EmitMLIR: - return std::make_unique<EmitMLIRAction>(); + case EmitFIR: + return std::make_unique<EmitFIRAction>(); + case EmitHLFIR: + return std::make_unique<EmitHLFIRAction>(); case EmitLLVM: return std::make_unique<EmitLLVMAction>(); case EmitLLVMBitcode: diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90 index a467a1684fc35..eb342bf5d200a 100644 --- a/flang/test/Driver/driver-help.f90 +++ b/flang/test/Driver/driver-help.f90 @@ -94,9 +94,10 @@ ! HELP-FC1-NEXT:OPTIONS: ! HELP-FC1-NEXT: -cpp Enable predefined and command line preprocessor macros ! HELP-FC1-NEXT: -D <macro>=<value> Define <macro> to <value> (or 1 if <value> omitted) +! HELP-FC1-NEXT: -emit-fir Build the parse tree, then lower it to FIR +! HELP-FC1-NEXT: -emit-hlfir Build the parse tree, then lower it to HLFIR ! HELP-FC1-NEXT: -emit-llvm-bc Build ASTs then convert to LLVM, emit .bc file ! HELP-FC1-NEXT: -emit-llvm Use the LLVM representation for assembler and object files -! HELP-FC1-NEXT: -emit-mlir Build the parse tree, then lower it to MLIR ! HELP-FC1-NEXT: -emit-obj Emit native object files ! HELP-FC1-NEXT: -E Only run the preprocessor ! HELP-FC1-NEXT: -falternative-parameter-statement diff --git a/flang/test/HLFIR/flang-experimental-hlfir-flag.f90 b/flang/test/HLFIR/flang-experimental-hlfir-flag.f90 index 4d9191c6d486a..76f40c8d8fc57 100644 --- a/flang/test/HLFIR/flang-experimental-hlfir-flag.f90 +++ b/flang/test/HLFIR/flang-experimental-hlfir-flag.f90 @@ -1,19 +1,38 @@ -! Test -flang-experimental-hlfir flag -! RUN: %flang_fc1 -flang-experimental-hlfir -emit-fir -o - %s | FileCheck %s -! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s --check-prefix NO-HLFIR +! Test -flang-experimental-hlfir, -emit-hlfir, -emit-fir flags +! RUN: %flang_fc1 -emit-hlfir -o - %s | FileCheck --check-prefix HLFIR --check-prefix ALL %s +! RUN: %flang_fc1 -emit-hlfir -flang-experimental-hlfir -o - %s | FileCheck --check-prefix HLFIR --check-prefix ALL %s +! RUN: %flang_fc1 -emit-fir -o - %s | FileCheck %s --check-prefix NO-HLFIR --check-prefix ALL +! RUN: %flang_fc1 -emit-fir -flang-experimental-hlfir -o - %s | FileCheck --check-prefix FIR --check-prefix ALL %s + +! | Action | -flang-experimental-hlfir? | Result | +! | =========== | ========================== | =============================== | +! | -emit-hlfir | N | Outputs HLFIR | +! | -emit-hlfir | Y | Outputs HLFIR | +! | -emit-fir | N | Outputs FIR, using old lowering | +! | -emit-fir | Y | Outputs FIR, lowering via HLFIR | subroutine test(a, res) real :: a(:), res res = SUM(a) end subroutine -! CHECK-LABEL: func.func @_QPtest -! CHECK: %[[A:.*]]: !fir.box<!fir.array<?xf32>> -! CHECK: %[[RES:.*]]: !fir.ref<f32> -! CHECK-DAG: %[[A_VAR:.*]]:2 = hlfir.declare %[[A]] -! CHECK-DAG: %[[RES_VAR:.*]]:2 = hlfir.declare %[[RES]] -! CHECK-NEXT: %[[SUM_RES:.*]] = hlfir.sum %[[A_VAR]]#0 -! CHECK-NEXT: hlfir.assign %[[SUM_RES]] to %[[RES_VAR]]#0 -! CHECK-NEXT: return -! CHECK-NEXT: } +! ALL-LABEL: func.func @_QPtest +! ALL: %[[A:.*]]: !fir.box<!fir.array<?xf32>> +! ALL: %[[RES:.*]]: !fir.ref<f32> + +! HLFIR: %[[A_VAR:.*]]:2 = hlfir.declare %[[A]] +! fir.declare is only generated via the hlfir -> fir lowering +! FIR: %[[A_VAR:.*]] = fir.declare %[[A]] +! NO-HLFIR-NOT: fir.declare + +! HLFIR-DAG: %[[RES_VAR:.*]]:2 = hlfir.declare %[[RES]] +! FIR: %[[RES_VAR:.*]] = fir.declare %[[RES]] +! NO-HLFIR-NOT: fir.declare + +! HLFIR-NEXT: %[[SUM_RES:.*]] = hlfir.sum %[[A_VAR]]#0 +! HLFIR-NEXT: hlfir.assign %[[SUM_RES]] to %[[RES_VAR]]#0 +! FIR-NOT: hlfir. +! NO-HLFIR-NOT: hlfir. + +! ALL: return +! ALL-NEXT: } -! NO-HLFIR-NOT: hlfir. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits