Skip to content

Commit

Permalink
[flang][hlfir] Separate -emit-fir and -emit-hlfir for flang-new
Browse files Browse the repository at this point in the history
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
  • Loading branch information
tblah committed Jun 1, 2023
1 parent 01ef213 commit 39ecf9d
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 29 deletions.
9 changes: 6 additions & 3 deletions clang/include/clang/Driver/Options.td
Expand Up @@ -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]

Expand Down
15 changes: 12 additions & 3 deletions flang/include/flang/Frontend/FrontendActions.h
Expand Up @@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions flang/include/flang/Frontend/FrontendOptions.h
Expand Up @@ -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,
Expand Down
10 changes: 7 additions & 3 deletions flang/lib/Frontend/CompilerInvocation.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down
44 changes: 42 additions & 2 deletions flang/lib/Frontend/FrontendActions.cpp
Expand Up @@ -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.");
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 4 additions & 2 deletions flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
Expand Up @@ -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:
Expand Down
3 changes: 2 additions & 1 deletion flang/test/Driver/driver-help.f90
Expand Up @@ -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
Expand Down
45 changes: 32 additions & 13 deletions 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.

0 comments on commit 39ecf9d

Please sign in to comment.