diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def index dc3da7ba5c7f3..5892d3ef24e5a 100644 --- a/flang/include/flang/Frontend/CodeGenOptions.def +++ b/flang/include/flang/Frontend/CodeGenOptions.def @@ -20,6 +20,8 @@ CODEGENOPT(Name, Bits, Default) #endif CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified. +/// The -Os (==1) or -Oz (==2) option is specified. +CODEGENOPT(OptimizeSize, 2, 0) CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new ///< pass manager. diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp index f05c4cfccf7fc..382fe7c7fa022 100644 --- a/flang/lib/Frontend/CompilerInvocation.cpp +++ b/flang/lib/Frontend/CompilerInvocation.cpp @@ -114,6 +114,10 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args, assert(a->getOption().matches(clang::driver::options::OPT_O)); + llvm::StringRef s(a->getValue()); + if (s == "s" || s == "z") + return 2; + return getLastArgIntValue(args, clang::driver::options::OPT_O, defaultOpt, diags); } @@ -121,6 +125,24 @@ static unsigned getOptimizationLevel(llvm::opt::ArgList &args, return defaultOpt; } +/// Extracts the size-optimization level from \a args +static unsigned getOptimizationLevelSize(llvm::opt::ArgList &args) { + if (llvm::opt::Arg *a = + args.getLastArg(clang::driver::options::OPT_O_Group)) { + if (a->getOption().matches(clang::driver::options::OPT_O)) { + switch (a->getValue()[0]) { + default: + return 0; + case 's': + return 1; + case 'z': + return 2; + } + } + } + return 0; +} + bool Fortran::frontend::parseDiagnosticArgs(clang::DiagnosticOptions &opts, llvm::opt::ArgList &args) { opts.ShowColors = parseShowColorsArgs(args); @@ -273,6 +295,7 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts, llvm::opt::ArgList &args, clang::DiagnosticsEngine &diags) { opts.OptimizationLevel = getOptimizationLevel(args, diags); + opts.OptimizeSize = getOptimizationLevelSize(args); if (args.hasFlag(clang::driver::options::OPT_fdebug_pass_manager, clang::driver::options::OPT_fno_debug_pass_manager, false)) diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp index 159d08a2797b3..d8fb466797671 100644 --- a/flang/lib/Frontend/FrontendActions.cpp +++ b/flang/lib/Frontend/FrontendActions.cpp @@ -602,7 +602,16 @@ mapToLevel(const Fortran::frontend::CodeGenOptions &opts) { case 1: return llvm::OptimizationLevel::O1; case 2: - return llvm::OptimizationLevel::O2; + switch (opts.OptimizeSize) { + default: + llvm_unreachable("Invalid optimization level for size!"); + case 0: + return llvm::OptimizationLevel::O2; + case 1: + return llvm::OptimizationLevel::Os; + case 2: + return llvm::OptimizationLevel::Oz; + } case 3: return llvm::OptimizationLevel::O3; } diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp b/flang/lib/Optimizer/Passes/Pipelines.cpp index 103e736accca0..7da3e0c0a888a 100644 --- a/flang/lib/Optimizer/Passes/Pipelines.cpp +++ b/flang/lib/Optimizer/Passes/Pipelines.cpp @@ -56,7 +56,7 @@ void addCfgConversionPass(mlir::PassManager &pm, void addAVC(mlir::PassManager &pm, const llvm::OptimizationLevel &optLevel) { ArrayValueCopyOptions options; - options.optimizeConflicts = optLevel.isOptimizingForSpeed(); + options.optimizeConflicts = optLevel != llvm::OptimizationLevel::O0; addNestedPassConditionally( pm, disableFirAvc, [&]() { return createArrayValueCopyPass(options); }); } @@ -169,20 +169,24 @@ void registerDefaultInlinerPass(MLIRToLLVMPassPipelineConfig &config) { /// \param pm - MLIR pass manager that will hold the pipeline definition void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig &pc) { + llvm::OptimizationLevel optLevel = pc.OptLevel; + unsigned speedupLevel = optLevel.getSpeedupLevel(); + unsigned sizeLevel = optLevel.getSizeLevel(); + // Early Optimizer EP Callback - pc.invokeFIROptEarlyEPCallbacks(pm, pc.OptLevel); + pc.invokeFIROptEarlyEPCallbacks(pm, optLevel); // simplify the IR mlir::GreedyRewriteConfig config; config.setRegionSimplificationLevel( mlir::GreedySimplifyRegionLevel::Disabled); pm.addPass(mlir::createCSEPass()); - fir::addAVC(pm, pc.OptLevel); + fir::addAVC(pm, optLevel); addNestedPassToAllTopLevelOperations( pm, fir::createCharacterConversion); pm.addPass(mlir::createCanonicalizerPass(config)); pm.addPass(fir::createSimplifyRegionLite()); - if (pc.OptLevel.isOptimizingForSpeed()) { + if (speedupLevel && !sizeLevel) { // These passes may increase code size. pm.addPass(fir::createSimplifyIntrinsics()); pm.addPass(fir::createAlgebraicSimplificationPass(config)); @@ -190,7 +194,7 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, pm.addPass(fir::createConstantArgumentGlobalisationOpt()); } - if (pc.LoopVersioning) + if (pc.LoopVersioning && !sizeLevel) pm.addPass(fir::createLoopVersioning()); pm.addPass(mlir::createCSEPass()); @@ -201,7 +205,7 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, fir::addMemoryAllocationOpt(pm); // FIR Inliner Callback - pc.invokeFIRInlinerCallback(pm, pc.OptLevel); + pc.invokeFIRInlinerCallback(pm, optLevel); pm.addPass(fir::createSimplifyRegionLite()); pm.addPass(mlir::createCSEPass()); @@ -212,13 +216,13 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, // Optimize redundant array repacking operations, // if the source is known to be contiguous. - if (pc.OptLevel.isOptimizingForSpeed()) + if (speedupLevel) pm.addPass(fir::createOptimizeArrayRepacking()); pm.addPass(fir::createLowerRepackArraysPass()); // Expand FIR operations that may use SCF dialect for their // implementation. This is a mandatory pass. - pm.addPass(fir::createSimplifyFIROperations( - {/*preferInlineImplementation=*/pc.OptLevel.isOptimizingForSpeed()})); + bool preferInlineImplementation = speedupLevel && !sizeLevel; + pm.addPass(fir::createSimplifyFIROperations({preferInlineImplementation})); addNestedPassToAllTopLevelOperations( pm, fir::createStackReclaim); @@ -232,11 +236,11 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, pm.addPass(fir::createConvertComplexPow()); pm.addPass(mlir::createCSEPass()); - if (pc.OptLevel.isOptimizingForSpeed()) + if (speedupLevel) pm.addPass(fir::createSetRuntimeCallAttributes()); // Last Optimizer EP Callback - pc.invokeFIROptLastEPCallbacks(pm, pc.OptLevel); + pc.invokeFIROptLastEPCallbacks(pm, optLevel); } /// Create a pass pipeline for lowering from HLFIR to FIR @@ -247,18 +251,24 @@ void createDefaultFIROptimizerPassPipeline(mlir::PassManager &pm, void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, EnableOpenMP enableOpenMP, llvm::OptimizationLevel optLevel) { - if (optLevel.getSizeLevel() > 0 || optLevel.getSpeedupLevel() > 0) { + // if sizeLevel > 0 (this is the case when either -Os or -Oz is provided on + // the command line), the speedupLevel is guaranteed to be 2. + unsigned speedupLevel = optLevel.getSpeedupLevel(); + unsigned sizeLevel = optLevel.getSizeLevel(); + + if (speedupLevel) { addNestedPassToAllTopLevelOperations( pm, hlfir::createExpressionSimplification); } - if (optLevel.isOptimizingForSpeed()) { + if (speedupLevel) { addCanonicalizerPassWithoutRegionSimplification(pm); addNestedPassToAllTopLevelOperations( pm, hlfir::createSimplifyHLFIRIntrinsics); } - addNestedPassToAllTopLevelOperations( - pm, hlfir::createInlineElementals); - if (optLevel.isOptimizingForSpeed()) { + if (!sizeLevel) + addNestedPassToAllTopLevelOperations( + pm, hlfir::createInlineElementals); + if (speedupLevel) { addCanonicalizerPassWithoutRegionSimplification(pm); pm.addPass(mlir::createCSEPass()); // Run SimplifyHLFIRIntrinsics pass late after CSE, @@ -271,8 +281,9 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, pm, hlfir::createPropagateFortranVariableAttributes); addNestedPassToAllTopLevelOperations( pm, hlfir::createOptimizedBufferization); - addNestedPassToAllTopLevelOperations( - pm, hlfir::createInlineHLFIRAssign); + if (!sizeLevel) + addNestedPassToAllTopLevelOperations( + pm, hlfir::createInlineHLFIRAssign); if (optLevel == llvm::OptimizationLevel::O3) { addNestedPassToAllTopLevelOperations( @@ -287,7 +298,7 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, // from hlfir.elemental lowering, if the result is an empty array. // This helps to avoid long running loops for elementals with // shapes like (0, HUGE). - if (optLevel.isOptimizingForSpeed()) + if (speedupLevel) bufferizeOptions.optimizeEmptyElementals = true; pm.addPass(hlfir::createBufferizeHLFIR(bufferizeOptions)); // Run hlfir.assign inlining again after BufferizeHLFIR, @@ -297,7 +308,7 @@ void createHLFIRToFIRPassPipeline(mlir::PassManager &pm, // TODO: we can remove the previous InlineHLFIRAssign, when // FIR AliasAnalysis is good enough to say that a temporary // array does not alias with any user object. - if (optLevel.isOptimizingForSpeed()) + if (speedupLevel && !sizeLevel) addNestedPassToAllTopLevelOperations( pm, hlfir::createInlineHLFIRAssign); pm.addPass(hlfir::createConvertHLFIRtoFIR()); @@ -354,10 +365,12 @@ void createDebugPasses(mlir::PassManager &pm, void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, MLIRToLLVMPassPipelineConfig config, llvm::StringRef inputFilename) { + unsigned speedupLevel = config.OptLevel.getSpeedupLevel(); + pm.addPass(fir::createMIFOpConversion()); fir::addBoxedProcedurePass(pm); - if (config.OptLevel.isOptimizingForSpeed() && config.AliasAnalysis && - !disableFirAliasTags && !useOldAliasTags) + if (speedupLevel && config.AliasAnalysis && !disableFirAliasTags && + !useOldAliasTags) pm.addPass(fir::createAddAliasTags()); addNestedPassToAllTopLevelOperations( pm, fir::createAbstractResultOpt); @@ -389,7 +402,7 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm, // TODO: re-enable setNoAlias by default (when optimizing for speed) once // function specialization is fixed. bool setNoAlias = forceNoAlias; - bool setNoCapture = config.OptLevel.isOptimizingForSpeed(); + bool setNoCapture = speedupLevel; pm.addPass(fir::createFunctionAttr( {framePointerKind, config.InstrumentFunctionEntry, diff --git a/flang/test/Driver/default-optimization-pipelines.f90 b/flang/test/Driver/default-optimization-pipelines.f90 index 08e407f73da5c..18108cd632220 100644 --- a/flang/test/Driver/default-optimization-pipelines.f90 +++ b/flang/test/Driver/default-optimization-pipelines.f90 @@ -14,10 +14,16 @@ ! RUN: %flang_fc1 -S -O2 %s -flto=full -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-LTO ! RUN: %flang_fc1 -S -O2 %s -flto=thin -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O2-THINLTO -! Verify that only the left-most `-O{n}` is used +! Verify that only the right-most `-O{n}` is used ! RUN: %flang -S -O2 -O0 %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0 ! RUN: %flang_fc1 -S -O2 -O0 %s -fdebug-pass-manager -o /dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-O0 +! Verify that passing -Os/-Oz have the desired effect on the pass pipelines. +! RUN: %flang -S -Os %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 \ +! RUN: | FileCheck %s --check-prefix=CHECK-OSIZE +! RUN: %flang -S -Oz %s -Xflang -fdebug-pass-manager -o /dev/null 2>&1 \ +! RUN: | FileCheck %s --check-prefix=CHECK-OSIZE + ! CHECK-O0-NOT: Running pass: SimplifyCFGPass on simple_loop_ ! CHECK-O0: Running analysis: TargetLibraryAnalysis on simple_loop_ ! CHECK-O0-ANYLTO: Running pass: CanonicalizeAliasesPass on [module] @@ -33,6 +39,12 @@ ! CHECK-O2-THINLTO: Running pass: CanonicalizeAliasesPass on [module] ! CHECK-O2-THINLTO: Running pass: NameAnonGlobalPass on [module] +! -Os/-Oz imply -O2, so check that a pass that runs on O2 is run. Then check +! that passes like LibShrinkWrap, that should not be run when optimizing for +! size, are not run (see llvm/lib/Passes/PassBuilderPipelines.cpp). +! CHECK-OSIZE: Running pass: SimplifyCFGPass on simple_loop_ +! CHECK-OSIZE-NOT: Running pass: LibCallsShrinkWrapPass on simple_loop_ + subroutine simple_loop integer :: i do i=1,5 diff --git a/flang/test/Driver/mlir-pass-pipeline.f90 b/flang/test/Driver/mlir-pass-pipeline.f90 index 3b6a9d7cda7ed..24462642e983d 100644 --- a/flang/test/Driver/mlir-pass-pipeline.f90 +++ b/flang/test/Driver/mlir-pass-pipeline.f90 @@ -1,173 +1,206 @@ -! Test the MLIR pass pipeline - -! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline -o /dev/null %s 2>&1 | FileCheck --check-prefixes=ALL %s -! -O0 is the default: -! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O0 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL %s -! RUN: %flang_fc1 -S -mmlir --mlir-pass-statistics -mmlir --mlir-pass-statistics-display=pipeline %s -O2 -o /dev/null 2>&1 | FileCheck --check-prefixes=ALL,O2 %s - ! REQUIRES: asserts - -end program - -! ALL: Pass statistics report -! ALL: Fortran::lower::VerifierPass - -! ALL: Pass statistics report - -! ALL: Fortran::lower::VerifierPass -! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! O2-NEXT: 'fir.global' Pipeline -! O2-NEXT: ExpressionSimplification -! O2-NEXT: 'func.func' Pipeline -! O2-NEXT: ExpressionSimplification -! O2-NEXT: 'omp.declare_reduction' Pipeline -! O2-NEXT: ExpressionSimplification -! O2-NEXT: 'omp.private' Pipeline -! O2-NEXT: ExpressionSimplification -! O2-NEXT: Canonicalizer -! ALL: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! ALL-NEXT:'fir.global' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! ALL: InlineElementals -! ALL-NEXT:'func.func' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! ALL: InlineElementals -! ALL-NEXT:'omp.declare_reduction' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! ALL: InlineElementals -! ALL-NEXT:'omp.private' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! ALL: InlineElementals -! O2-NEXT: Canonicalizer -! O2-NEXT: CSE -! O2-NEXT: (S) {{.*}} num-cse'd -! O2-NEXT: (S) {{.*}} num-dce'd -! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! O2-NEXT: 'fir.global' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! O2-NEXT: PropagateFortranVariableAttributes -! O2-NEXT: OptimizedBufferization -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'func.func' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! O2-NEXT: PropagateFortranVariableAttributes -! O2-NEXT: OptimizedBufferization -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'omp.declare_reduction' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! O2-NEXT: PropagateFortranVariableAttributes -! O2-NEXT: OptimizedBufferization -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'omp.private' Pipeline -! O2-NEXT: SimplifyHLFIRIntrinsics -! O2-NEXT: PropagateFortranVariableAttributes -! O2-NEXT: OptimizedBufferization -! O2-NEXT: InlineHLFIRAssign -! ALL: LowerHLFIROrderedAssignments -! ALL-NEXT: LowerHLFIRIntrinsics -! ALL-NEXT: BufferizeHLFIR -! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! O2-NEXT: 'fir.global' Pipeline -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'func.func' Pipeline -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'omp.declare_reduction' Pipeline -! O2-NEXT: InlineHLFIRAssign -! O2-NEXT: 'omp.private' Pipeline -! O2-NEXT: InlineHLFIRAssign -! ALL-NEXT: ConvertHLFIRtoFIR -! ALL-NEXT: CSE -! Ideally, we need an output with only the pass names, but -! there is currently no way to get that, so in order to -! guarantee that the passes are in the expected order -! (i.e. use -NEXT) we have to check the statistics output as well. -! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd -! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd - -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: CharacterConversion -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: ArrayValueCopy -! ALL-NEXT: CharacterConversion -! ALL-NEXT: 'omp.declare_reduction' Pipeline -! ALL-NEXT: CharacterConversion -! ALL-NEXT: 'omp.private' Pipeline -! ALL-NEXT: CharacterConversion - -! ALL-NEXT: Canonicalizer -! ALL-NEXT: SimplifyRegionLite -! O2-NEXT: SimplifyIntrinsics -! O2-NEXT: AlgebraicSimplification -! ALL-NEXT: CSE -! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd -! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd - -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: MemoryAllocationOpt - -! ALL-NEXT: Inliner -! ALL-NEXT: SimplifyRegionLite -! ALL-NEXT: CSE -! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd -! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd - -! ALL-NEXT: PolymorphicOpConversion -! ALL-NEXT: AssumedRankOpConversion -! O2-NEXT: 'func.func' Pipeline -! O2-NEXT: OptimizeArrayRepacking -! ALL-NEXT: LowerRepackArraysPass -! ALL-NEXT: SimplifyFIROperations - -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] -! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: StackReclaim -! ALL-NEXT: CFGConversion +! +! Test the MLIR pass pipeline +! +! The table below summarizes the relationship between the optimization levels +! -O and the integer speedup and size levels. +! +! .------------------------------. +! | Level | Speedup | Size | +! |------------------------------| +! | -O0 | 0 | 0 | +! | -O1 | 1 | 0 | +! | -O2 | 2 | 0 | +! | -O3 | 3 | 0 | +! | -Os | 2 | 1 | +! | -Oz | 2 | 2 | +! '------------------------------' +! +! Since the speedup level for -Os and -Oz is the same as that of -O2, most of +! the passes that are run at -O2 are run at -Os and -Oz as well, except for any +! passes that might increase the size of the code. The names of the FileCheck +! prefixes in the RUN below lines indicate at which optimization levels the +! corresponding output is expected. For instance: +! +! ALL O0, O1, O2, O3, Os, Oz (note that -O1 and -O3 are not explicitly +! tested here) +! O2 O2 only, but not Os or Oz +! O02 O0 and O2, but not Os or Oz +! O2SZ O2, Os, and Oz +! +! NOTE: At the time of writing, the same set of MLIR passes is run for both +! optimization level -Os and -Oz. +! +! RUN: %flang_fc1 -S -o /dev/null %s -mmlir --mlir-pass-statistics \ +! RUN: -mmlir --mlir-pass-statistics-display=pipeline 2>&1 \ +! RUN: | FileCheck --check-prefixes=ALL,O02 %s +! +! RUN: %flang_fc1 -O0 -S -o /dev/null %s -mmlir --mlir-pass-statistics \ +! RUN: -mmlir --mlir-pass-statistics-display=pipeline 2>&1 \ +! RUN: | FileCheck --check-prefixes=ALL,O02 %s +! +! RUN: %flang_fc1 -O2 -S -o /dev/null %s -mmlir --mlir-pass-statistics \ +! RUN: -mmlir --mlir-pass-statistics-display=pipeline 2>&1 \ +! RUN: | FileCheck --check-prefixes=ALL,O02,O2,O2SZ %s +! +! RUN: %flang_fc1 -Os -S -o /dev/null %s -mmlir --mlir-pass-statistics \ +! RUN: -mmlir --mlir-pass-statistics-display=pipeline 2>&1 \ +! RUN: | FileCheck --check-prefixes=ALL,O2 %s +! +! RUN: %flang_fc1 -Oz -S -o /dev/null %s -mmlir --mlir-pass-statistics \ +! RUN: -mmlir --mlir-pass-statistics-display=pipeline 2>&1 \ +! RUN: | FileCheck --check-prefixes=ALL,O2 %s +! +! Ideally, we need an output with only the pass names, but there is currently no +! way to get that, so in order to guarantee that the passes are in the expected +! order (i.e. use -NEXT) we have to check the statistics output as well. +! +! ALL: Pass statistics report +! ALL: Fortran::lower::VerifierPass +! ALL: Pass statistics report +! ALL: Fortran::lower::VerifierPass +! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! O2-NEXT: 'fir.global' Pipeline +! O2-NEXT: ExpressionSimplification +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: ExpressionSimplification +! O2-NEXT: 'omp.declare_reduction' Pipeline +! O2-NEXT: ExpressionSimplification +! O2-NEXT: 'omp.private' Pipeline +! O2-NEXT: ExpressionSimplification +! O2-NEXT: Canonicalizer +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! ALL-NEXT: 'fir.global' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O02-NEXT: InlineElementals +! ALL-NEXT: 'func.func' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O02-NEXT: InlineElementals +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O02-NEXT: InlineElementals +! ALL-NEXT: 'omp.private' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O02-NEXT: InlineElementals +! O2-NEXT: Canonicalizer +! O2-NEXT: CSE +! O2-NEXT: (S) {{.*}} num-cse'd +! O2-NEXT: (S) {{.*}} num-dce'd +! O2-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! O2-NEXT: 'fir.global' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O2-NEXT: PropagateFortranVariableAttributes +! O2-NEXT: OptimizedBufferization +! O2SZ-NEXT: InlineHLFIRAssign +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O2-NEXT: PropagateFortranVariableAttributes +! O2-NEXT: OptimizedBufferization +! O2SZ-NEXT: InlineHLFIRAssign +! O2-NEXT: 'omp.declare_reduction' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O2-NEXT: PropagateFortranVariableAttributes +! O2-NEXT: OptimizedBufferization +! O2SZ-NEXT: InlineHLFIRAssign +! O2-NEXT: 'omp.private' Pipeline +! O2-NEXT: SimplifyHLFIRIntrinsics +! O2-NEXT: PropagateFortranVariableAttributes +! O2-NEXT: OptimizedBufferization +! O2SZ-NEXT: InlineHLFIRAssign +! ALL: LowerHLFIROrderedAssignments +! ALL-NEXT: LowerHLFIRIntrinsics +! ALL-NEXT: BufferizeHLFIR +! O2SZ-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! O2SZ-NEXT: 'fir.global' Pipeline +! O2SZ-NEXT: InlineHLFIRAssign +! O2SZ-NEXT: 'func.func' Pipeline +! O2SZ-NEXT: InlineHLFIRAssign +! O2SZ-NEXT: 'omp.declare_reduction' Pipeline +! O2SZ-NEXT: InlineHLFIRAssign +! O2SZ-NEXT: 'omp.private' Pipeline +! O2SZ-NEXT: InlineHLFIRAssign +! ALL-NEXT: ConvertHLFIRtoFIR +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! ALL-NEXT: 'fir.global' Pipeline +! ALL-NEXT: CharacterConversion +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: ArrayValueCopy +! ALL-NEXT: CharacterConversion +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: CharacterConversion +! ALL-NEXT: 'omp.private' Pipeline +! ALL-NEXT: CharacterConversion +! ALL-NEXT: Canonicalizer +! ALL-NEXT: SimplifyRegionLite +! O2SZ-NEXT: SimplifyIntrinsics +! O2SZ-NEXT: AlgebraicSimplification +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd ! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: StackReclaim -! ALL-NEXT: CFGConversion -! ALL-NEXT: 'omp.declare_reduction' Pipeline -! ALL-NEXT: StackReclaim -! ALL-NEXT: CFGConversion -! ALL-NEXT: 'omp.private' Pipeline -! ALL-NEXT: StackReclaim -! ALL-NEXT: CFGConversion - -! ALL-NEXT: SCFToControlFlow -! ALL-NEXT: Canonicalizer -! ALL-NEXT: SimplifyRegionLite -! ALL-NEXT: ConvertComplexPow -! ALL-NEXT: CSE -! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd -! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd -! O2-NEXT: 'func.func' Pipeline -! O2-NEXT: SetRuntimeCallAttributes -! ALL-NEXT: MIFOpConversion -! ALL-NEXT: BoxedProcedurePass -! O2-NEXT: AddAliasTags - -! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'gpu.module', 'omp.declare_reduction', 'omp.private'] -! ALL-NEXT: 'fir.global' Pipeline -! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'gpu.module' Pipeline -! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'gpu.func' Pipeline -! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'omp.declare_reduction' Pipeline -! ALL-NEXT: AbstractResultOpt -! ALL-NEXT: 'omp.private' Pipeline -! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: MemoryAllocationOpt +! ALL-NEXT: Inliner +! ALL-NEXT: SimplifyRegionLite +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd +! ALL-NEXT: PolymorphicOpConversion +! ALL-NEXT: AssumedRankOpConversion +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: OptimizeArrayRepacking +! ALL-NEXT: LowerRepackArraysPass +! ALL-NEXT: SimplifyFIROperations +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'omp.declare_reduction', 'omp.private'] +! ALL-NEXT: 'fir.global' Pipeline +! ALL-NEXT: StackReclaim +! ALL-NEXT: CFGConversion +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: StackReclaim +! ALL-NEXT: CFGConversion +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: StackReclaim +! ALL-NEXT: CFGConversion +! ALL-NEXT: 'omp.private' Pipeline +! ALL-NEXT: StackReclaim +! ALL-NEXT: CFGConversion +! ALL-NEXT: SCFToControlFlow +! ALL-NEXT: Canonicalizer +! ALL-NEXT: SimplifyRegionLite +! ALL-NEXT: ConvertComplexPow +! ALL-NEXT: CSE +! ALL-NEXT: (S) 0 num-cse'd - Number of operations CSE'd +! ALL-NEXT: (S) 0 num-dce'd - Number of operations DCE'd +! O2-NEXT: 'func.func' Pipeline +! O2-NEXT: SetRuntimeCallAttributes +! ALL-NEXT: MIFOpConversion +! ALL-NEXT: BoxedProcedurePass +! O2-NEXT: AddAliasTags +! ALL-NEXT: Pipeline Collection : ['fir.global', 'func.func', 'gpu.module', 'omp.declare_reduction', 'omp.private'] +! ALL-NEXT: 'fir.global' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'gpu.module' Pipeline +! ALL-NEXT: Pipeline Collection : ['func.func', 'gpu.func'] +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'gpu.func' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.declare_reduction' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: 'omp.private' Pipeline +! ALL-NEXT: AbstractResultOpt +! ALL-NEXT: CodeGenRewrite +! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated +! ALL-NEXT: ExternalNameConversion +! ALL-NEXT: TargetRewrite +! ALL-NEXT: CompilerGeneratedNamesConversion +! ALL-NEXT: 'func.func' Pipeline +! ALL-NEXT: FunctionAttr +! ALL-NEXT: FIRToLLVMLowering +! ALL-NOT: LLVMIRLoweringPass -! ALL-NEXT: CodeGenRewrite -! ALL-NEXT: (S) 0 num-dce'd - Number of operations eliminated -! ALL-NEXT: ExternalNameConversion -! ALL-NEXT: TargetRewrite -! ALL-NEXT: CompilerGeneratedNamesConversion -! ALL-NEXT: 'func.func' Pipeline -! ALL-NEXT: FunctionAttr -! ALL-NEXT: FIRToLLVMLowering -! ALL-NOT: LLVMIRLoweringPass +end program