[flang-commits] [flang] 8e315c6 - [Flang][Driver] Add regex support for R_Group options
Victor Kingi via flang-commits
flang-commits at lists.llvm.org
Thu Aug 31 04:16:03 PDT 2023
Author: Victor Kingi
Date: 2023-08-31T11:15:58Z
New Revision: 8e315c6ce558a25f7cadab57bd8a14ff958ae517
URL: https://github.com/llvm/llvm-project/commit/8e315c6ce558a25f7cadab57bd8a14ff958ae517
DIFF: https://github.com/llvm/llvm-project/commit/8e315c6ce558a25f7cadab57bd8a14ff958ae517.diff
LOG: [Flang][Driver] Add regex support for R_Group options
Add regex handling for all variations of OPT_R_Joined, i.e.
`-Rpass`, `-Rpass-analysis`, `-Rpass-missed`.
Depends on D158174. That patch implements backend support for
R_Group options.
Reviewed By: awarzynski
Differential Revision: https://reviews.llvm.org/D158436
Added:
flang/test/Driver/optimization-remark-invalid.f90
Modified:
flang/include/flang/Frontend/CodeGenOptions.h
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
flang/test/Driver/optimization-remark.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h b/flang/include/flang/Frontend/CodeGenOptions.h
index 0bc7758a678016..b0e0c91e09ab38 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -73,11 +73,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
// has
// TODO: Share with clang instead of re-implementing here
enum class RemarkKind {
- RK_Missing, // Remark argument not present on the command line.
- RK_Enabled, // Remark enabled via '-Rgroup', i.e. -Rpass, -Rpass-missed,
- // -Rpass-analysis
- RK_Disabled, // Remark disabled via '-Rno-group', i.e. -Rno-pass,
- // -Rno-pass-missed, -Rno-pass-analysis.
+ RK_Missing, // Remark argument not present on the command line.
+ RK_Enabled, // Remark enabled via '-Rgroup', i.e. -Rpass, -Rpass-missed,
+ // -Rpass-analysis
+ RK_Disabled, // Remark disabled via '-Rno-group', i.e. -Rno-pass,
+ // -Rno-pass-missed, -Rno-pass-analysis.
+ RK_WithPattern, // Remark pattern specified via '-Rgroup=regexp'.
};
/// Optimization remark with an optional regular expression pattern.
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index f2a7ffdd135edb..56218cbadd444d 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -156,11 +156,12 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
// Generate an OptRemark object containing info on if the -Rgroup
// specified is enabled or not.
static CodeGenOptions::OptRemark
-parseOptimizationRemark(llvm::opt::ArgList &args,
+parseOptimizationRemark(clang::DiagnosticsEngine &diags,
+ llvm::opt::ArgList &args, llvm::opt::OptSpecifier optEq,
llvm::StringRef remarkOptName) {
assert((remarkOptName == "pass" || remarkOptName == "pass-missed" ||
remarkOptName == "pass-analysis") &&
- "Unknown group name provided.");
+ "Unsupported remark option name provided.");
CodeGenOptions::OptRemark result;
for (llvm::opt::Arg *a : args) {
@@ -180,6 +181,17 @@ parseOptimizationRemark(llvm::opt::ArgList &args,
result.Pattern = "";
result.Regex = nullptr;
}
+ } else if (a->getOption().matches(optEq)) {
+ result.Kind = CodeGenOptions::RemarkKind::RK_WithPattern;
+ result.Pattern = a->getValue();
+ result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
+ std::string regexError;
+
+ if (!result.Regex->isValid(regexError)) {
+ diags.Report(clang::diag::err_drv_optimization_remark_pattern)
+ << regexError << a->getAsString(args);
+ return CodeGenOptions::OptRemark();
+ }
}
}
return result;
@@ -240,15 +252,20 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
// Create OptRemark that allows printing of all successful optimization
// passes applied.
- opts.OptimizationRemark = parseOptimizationRemark(args, "pass");
+ opts.OptimizationRemark =
+ parseOptimizationRemark(diags, args, clang::driver::options::OPT_Rpass_EQ,
+ /*remarkOptName=*/"pass");
// Create OptRemark that allows all missed optimization passes to be printed.
- opts.OptimizationRemarkMissed = parseOptimizationRemark(args, "pass-missed");
+ opts.OptimizationRemarkMissed = parseOptimizationRemark(
+ diags, args, clang::driver::options::OPT_Rpass_missed_EQ,
+ /*remarkOptName=*/"pass-missed");
// Create OptRemark that allows all optimization decisions made by LLVM
// to be printed.
- opts.OptimizationRemarkAnalysis =
- parseOptimizationRemark(args, "pass-analysis");
+ opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
+ diags, args, clang::driver::options::OPT_Rpass_analysis_EQ,
+ /*remarkOptName=*/"pass-analysis");
if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
opts.SaveTempsDir = a->getValue();
@@ -746,6 +763,9 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
res.getFrontendOpts().showColors =
parseShowColorsArgs(args, /*defaultDiagColor=*/false);
+ // Honor color diagnostics.
+ res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
+
return diags.getNumErrors() == numErrorsBefore;
}
@@ -1010,8 +1030,18 @@ bool CompilerInvocation::createFromArgs(
// Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
// -Rpass-analysis. This will be used later when processing and outputting the
// remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
- for (auto *a : args.filtered(clang::driver::options::OPT_R_Group))
- res.getDiagnosticOpts().Remarks.push_back(a->getValue());
+ for (auto *a : args.filtered(clang::driver::options::OPT_R_Group)) {
+ if (a->getOption().matches(clang::driver::options::OPT_R_value_Group))
+ // This is -Rfoo=, where foo is the name of the diagnostic
+ // group. Add only the remark option name to the diagnostics. e.g. for
+ // -Rpass= we will add the string "pass".
+ res.getDiagnosticOpts().Remarks.push_back(
+ std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
+ else
+ // If no regex was provided, add the provided value, e.g. for -Rpass add
+ // the string "pass".
+ res.getDiagnosticOpts().Remarks.push_back(a->getValue());
+ }
success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
parseTargetArgs(res.getTargetOpts(), args);
diff --git a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index e1de344825f88a..d16aff84f445fb 100644
--- a/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -191,9 +191,6 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
return false;
}
- // Honor color diagnostics.
- flang->getDiagnosticOpts().ShowColors = flang->getFrontendOpts().showColors;
-
updateDiagEngineForOptRemarks(flang->getDiagnostics(),
flang->getDiagnosticOpts());
diff --git a/flang/test/Driver/optimization-remark-invalid.f90 b/flang/test/Driver/optimization-remark-invalid.f90
new file mode 100644
index 00000000000000..829ccba8951997
--- /dev/null
+++ b/flang/test/Driver/optimization-remark-invalid.f90
@@ -0,0 +1,12 @@
+! This file tests invalid usage of the -Rpass family of flags (-Rpass, -Rpass-missed
+! and -Rpass-analysis)
+! loop-delete isn't enabled at O0 so we use at least O1
+
+! Check error on invalid regex -Rpass message is emitted
+! RUN: not %flang %s -O1 -Rpass=[ -c 2>&1 | FileCheck %s --check-prefix=REGEX-INVALID
+
+
+! REGEX-INVALID: error: in pattern '-Rpass=[': brackets ([ ]) not balanced
+
+program forttest
+end program forttest
diff --git a/flang/test/Driver/optimization-remark.f90 b/flang/test/Driver/optimization-remark.f90
index 06cc133e8e42bf..eb24a91d8db51b 100644
--- a/flang/test/Driver/optimization-remark.f90
+++ b/flang/test/Driver/optimization-remark.f90
@@ -4,46 +4,84 @@
! DEFINE: %{output} = -emit-llvm -o /dev/null 2>&1
+! Check fc1 can handle -Rpass
+! RUN: %flang_fc1 %s -O1 -Rpass %{output} 2>&1 | FileCheck %s --check-prefix=REMARKS
+
! Check that we can override -Rpass= with -Rno-pass.
-! RUN: %flang_fc1 %s -O1 -Rpass %{output} | FileCheck %s --check-prefix=REMARKS
-! RUN: %flang_fc1 %s -O1 -Rpass -Rno-pass %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
+! RUN: %flang_fc1 %s -O1 -Rpass -Rno-pass %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
! Check -Rno-pass, -Rno-pass-analysis, -Rno-pass-missed nothing emitted
-! RUN: %flang %s -O1 -Rno-pass -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
-! RUN: %flang %s -O1 -Rno-pass-missed -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
-! RUN: %flang %s -O1 -Rno-pass-analysis -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
+! RUN: %flang %s -O1 -Rno-pass -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
+! RUN: %flang %s -O1 -Rno-pass-missed -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
+! RUN: %flang %s -O1 -Rno-pass-analysis -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
+
+! Check valid -Rpass regex
+! RUN: %flang %s -O1 -Rpass=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=PASS-REGEX-LOOP-ONLY
+
+! Check valid -Rpass-missed regex
+! RUN: %flang %s -O1 -Rpass-missed=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=MISSED-REGEX-LOOP-ONLY
+
+! Check valid -Rpass-analysis regex
+! RUN: %flang %s -O1 -Rpass-analysis=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=ANALYSIS-REGEX-LOOP-ONLY
! Check full -Rpass message is emitted
-! RUN: %flang %s -O1 -Rpass -S %{output} | FileCheck %s
+! RUN: %flang %s -O1 -Rpass -S %{output} 2>&1 | FileCheck %s --check-prefix=PASS
! Check full -Rpass-missed message is emitted
-! RUN: %flang %s -O1 -Rpass-missed -S %{output} | FileCheck %s --check-prefix=REMARKS-MISSED
+! RUN: %flang %s -O1 -Rpass-missed -S %{output} 2>&1 | FileCheck %s --check-prefix=MISSED
! Check full -Rpass-analysis message is emitted
-! RUN: %flang %s -O1 -Rpass-analysis -S %{output} | FileCheck %s --check-prefix=REMARKS-ANALYSIS
-
-! CHECK: remark: Loop deleted because it is invariant
-! REMARKS-MISSED: {{.*}} will not be inlined into {{.*}} because its definition is unavailable
-! REMARKS-MISSED: remark: loop not vectorized
-! REMARKS-MISSED-NOT: loop not vectorized: instruction cannot be vectorized
-! REMARKS-ANALYSIS: remark: loop not vectorized: instruction cannot be vectorized
-! REMARKS-ANALYSIS-NOT: {{.*}} will not be inlined into {{.*}} because its definition is unavailable
+! RUN: %flang %s -O1 -Rpass-analysis -S -o /dev/null 2>&1 | FileCheck %s --check-prefix=ANALYSIS
! REMARKS: remark:
! NO-REMARKS-NOT: remark:
-program forttest
- implicit none
- real, dimension(1:50) :: aR1
- integer :: n
- do n = 1,50
- aR1(n) = n * 1.34
- print *, "hello"
- end do
+! With plain -Rpass, -Rpass-missed or -Rpass-analysis, we expect remarks related to 2 opportunities (loop vectorisation / loop delete and load hoisting).
+! Once we start filtering, this is reduced to 1 one of the loop passes.
+
+! PASS-REGEX-LOOP-ONLY-NOT: remark: hoisting load
+! PASS-REGEX-LOOP-ONLY: remark: Loop deleted because it is invariant
+
+! MISSED-REGEX-LOOP-ONLY-NOT: remark: failed to hoist load with loop-invariant address because load is conditionally executed
+! MISSED-REGEX-LOOP-ONLY: remark: loop not vectorized
+
+
+! ANALYSIS-REGEX-LOOP-ONLY: remark: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
+! ANALYSIS-REGEX-LOOP-ONLY: Unknown data dependence.
+! ANALYSIS-REGEX-LOOP-ONLY-NOT: remark:{{.*}}: IR instruction count changed from {{[0-9]+}} to {{[0-9]+}}; Delta: {{-?[0-9]+}}
+
+! PASS: remark: hoisting load
+! PASS: remark: Loop deleted because it is invariant
+
+! MISSED: remark: failed to hoist load with loop-invariant address because load is conditionally executed
+! MISSED: remark: loop not vectorized
+! MISSED-NOT: remark: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
+! MISSED-NOT: Unknown data dependence.
+
+! ANALYSIS: remark: loop not vectorized: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
+! ANALYSIS: Unknown data dependence.
+! ANALYSIS: remark: {{.*}}: IR instruction count changed from {{[0-9]+}} to {{[0-9]+}}; Delta: {{-?[0-9]+}}
+! ANALYSIS-NOT: remark: failed to hoist load with loop-invariant address because load is conditionally executed
+
+subroutine swap_real(a1, a2)
+ implicit none
+
+ real, dimension(1:2) :: aR1
+ integer :: i, n
+ real, intent(inout) :: a1(:), a2(:)
+ real :: a
+
+! Swap
+ do i = 1, min(size(a1), size(a2))
+ a = a1(i)
+ a1(i) = a2(i)
+ a2(i) = a
+ end do
- do n = 1,50
+! Do a random loop to generate a successful loop-delete pass
+ do n = 1,2
aR1(n) = n * 1.34
end do
-end program forttest
+end subroutine swap_real
More information about the flang-commits
mailing list