Skip to content

Commit 8e315c6

Browse files
committed
[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
1 parent a84b09f commit 8e315c6

File tree

5 files changed

+119
-41
lines changed

5 files changed

+119
-41
lines changed

flang/include/flang/Frontend/CodeGenOptions.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
7373
// has
7474
// TODO: Share with clang instead of re-implementing here
7575
enum class RemarkKind {
76-
RK_Missing, // Remark argument not present on the command line.
77-
RK_Enabled, // Remark enabled via '-Rgroup', i.e. -Rpass, -Rpass-missed,
78-
// -Rpass-analysis
79-
RK_Disabled, // Remark disabled via '-Rno-group', i.e. -Rno-pass,
80-
// -Rno-pass-missed, -Rno-pass-analysis.
76+
RK_Missing, // Remark argument not present on the command line.
77+
RK_Enabled, // Remark enabled via '-Rgroup', i.e. -Rpass, -Rpass-missed,
78+
// -Rpass-analysis
79+
RK_Disabled, // Remark disabled via '-Rno-group', i.e. -Rno-pass,
80+
// -Rno-pass-missed, -Rno-pass-analysis.
81+
RK_WithPattern, // Remark pattern specified via '-Rgroup=regexp'.
8182
};
8283

8384
/// Optimization remark with an optional regular expression pattern.

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,12 @@ static bool parseDebugArgs(Fortran::frontend::CodeGenOptions &opts,
156156
// Generate an OptRemark object containing info on if the -Rgroup
157157
// specified is enabled or not.
158158
static CodeGenOptions::OptRemark
159-
parseOptimizationRemark(llvm::opt::ArgList &args,
159+
parseOptimizationRemark(clang::DiagnosticsEngine &diags,
160+
llvm::opt::ArgList &args, llvm::opt::OptSpecifier optEq,
160161
llvm::StringRef remarkOptName) {
161162
assert((remarkOptName == "pass" || remarkOptName == "pass-missed" ||
162163
remarkOptName == "pass-analysis") &&
163-
"Unknown group name provided.");
164+
"Unsupported remark option name provided.");
164165
CodeGenOptions::OptRemark result;
165166

166167
for (llvm::opt::Arg *a : args) {
@@ -180,6 +181,17 @@ parseOptimizationRemark(llvm::opt::ArgList &args,
180181
result.Pattern = "";
181182
result.Regex = nullptr;
182183
}
184+
} else if (a->getOption().matches(optEq)) {
185+
result.Kind = CodeGenOptions::RemarkKind::RK_WithPattern;
186+
result.Pattern = a->getValue();
187+
result.Regex = std::make_shared<llvm::Regex>(result.Pattern);
188+
std::string regexError;
189+
190+
if (!result.Regex->isValid(regexError)) {
191+
diags.Report(clang::diag::err_drv_optimization_remark_pattern)
192+
<< regexError << a->getAsString(args);
193+
return CodeGenOptions::OptRemark();
194+
}
183195
}
184196
}
185197
return result;
@@ -240,15 +252,20 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
240252

241253
// Create OptRemark that allows printing of all successful optimization
242254
// passes applied.
243-
opts.OptimizationRemark = parseOptimizationRemark(args, "pass");
255+
opts.OptimizationRemark =
256+
parseOptimizationRemark(diags, args, clang::driver::options::OPT_Rpass_EQ,
257+
/*remarkOptName=*/"pass");
244258

245259
// Create OptRemark that allows all missed optimization passes to be printed.
246-
opts.OptimizationRemarkMissed = parseOptimizationRemark(args, "pass-missed");
260+
opts.OptimizationRemarkMissed = parseOptimizationRemark(
261+
diags, args, clang::driver::options::OPT_Rpass_missed_EQ,
262+
/*remarkOptName=*/"pass-missed");
247263

248264
// Create OptRemark that allows all optimization decisions made by LLVM
249265
// to be printed.
250-
opts.OptimizationRemarkAnalysis =
251-
parseOptimizationRemark(args, "pass-analysis");
266+
opts.OptimizationRemarkAnalysis = parseOptimizationRemark(
267+
diags, args, clang::driver::options::OPT_Rpass_analysis_EQ,
268+
/*remarkOptName=*/"pass-analysis");
252269

253270
if (auto *a = args.getLastArg(clang::driver::options::OPT_save_temps_EQ))
254271
opts.SaveTempsDir = a->getValue();
@@ -746,6 +763,9 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
746763
res.getFrontendOpts().showColors =
747764
parseShowColorsArgs(args, /*defaultDiagColor=*/false);
748765

766+
// Honor color diagnostics.
767+
res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
768+
749769
return diags.getNumErrors() == numErrorsBefore;
750770
}
751771

@@ -1010,8 +1030,18 @@ bool CompilerInvocation::createFromArgs(
10101030
// Preserve all the remark options requested, i.e. -Rpass, -Rpass-missed or
10111031
// -Rpass-analysis. This will be used later when processing and outputting the
10121032
// remarks generated by LLVM in ExecuteCompilerInvocation.cpp.
1013-
for (auto *a : args.filtered(clang::driver::options::OPT_R_Group))
1014-
res.getDiagnosticOpts().Remarks.push_back(a->getValue());
1033+
for (auto *a : args.filtered(clang::driver::options::OPT_R_Group)) {
1034+
if (a->getOption().matches(clang::driver::options::OPT_R_value_Group))
1035+
// This is -Rfoo=, where foo is the name of the diagnostic
1036+
// group. Add only the remark option name to the diagnostics. e.g. for
1037+
// -Rpass= we will add the string "pass".
1038+
res.getDiagnosticOpts().Remarks.push_back(
1039+
std::string(a->getOption().getName().drop_front(1).rtrim("=-")));
1040+
else
1041+
// If no regex was provided, add the provided value, e.g. for -Rpass add
1042+
// the string "pass".
1043+
res.getDiagnosticOpts().Remarks.push_back(a->getValue());
1044+
}
10151045

10161046
success &= parseFrontendArgs(res.getFrontendOpts(), args, diags);
10171047
parseTargetArgs(res.getTargetOpts(), args);

flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,6 @@ bool executeCompilerInvocation(CompilerInstance *flang) {
191191
return false;
192192
}
193193

194-
// Honor color diagnostics.
195-
flang->getDiagnosticOpts().ShowColors = flang->getFrontendOpts().showColors;
196-
197194
updateDiagEngineForOptRemarks(flang->getDiagnostics(),
198195
flang->getDiagnosticOpts());
199196

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
! This file tests invalid usage of the -Rpass family of flags (-Rpass, -Rpass-missed
2+
! and -Rpass-analysis)
3+
! loop-delete isn't enabled at O0 so we use at least O1
4+
5+
! Check error on invalid regex -Rpass message is emitted
6+
! RUN: not %flang %s -O1 -Rpass=[ -c 2>&1 | FileCheck %s --check-prefix=REGEX-INVALID
7+
8+
9+
! REGEX-INVALID: error: in pattern '-Rpass=[': brackets ([ ]) not balanced
10+
11+
program forttest
12+
end program forttest

flang/test/Driver/optimization-remark.f90

Lines changed: 63 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,84 @@
44

55
! DEFINE: %{output} = -emit-llvm -o /dev/null 2>&1
66

7+
! Check fc1 can handle -Rpass
8+
! RUN: %flang_fc1 %s -O1 -Rpass %{output} 2>&1 | FileCheck %s --check-prefix=REMARKS
9+
710
! Check that we can override -Rpass= with -Rno-pass.
8-
! RUN: %flang_fc1 %s -O1 -Rpass %{output} | FileCheck %s --check-prefix=REMARKS
9-
! RUN: %flang_fc1 %s -O1 -Rpass -Rno-pass %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
11+
! RUN: %flang_fc1 %s -O1 -Rpass -Rno-pass %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
1012

1113
! Check -Rno-pass, -Rno-pass-analysis, -Rno-pass-missed nothing emitted
12-
! RUN: %flang %s -O1 -Rno-pass -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
13-
! RUN: %flang %s -O1 -Rno-pass-missed -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
14-
! RUN: %flang %s -O1 -Rno-pass-analysis -S %{output} | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
14+
! RUN: %flang %s -O1 -Rno-pass -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
15+
! RUN: %flang %s -O1 -Rno-pass-missed -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
16+
! RUN: %flang %s -O1 -Rno-pass-analysis -S %{output} 2>&1 | FileCheck %s --allow-empty --check-prefix=NO-REMARKS
17+
18+
! Check valid -Rpass regex
19+
! RUN: %flang %s -O1 -Rpass=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=PASS-REGEX-LOOP-ONLY
20+
21+
! Check valid -Rpass-missed regex
22+
! RUN: %flang %s -O1 -Rpass-missed=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=MISSED-REGEX-LOOP-ONLY
23+
24+
! Check valid -Rpass-analysis regex
25+
! RUN: %flang %s -O1 -Rpass-analysis=loop -S %{output} 2>&1 | FileCheck %s --check-prefix=ANALYSIS-REGEX-LOOP-ONLY
1526

1627
! Check full -Rpass message is emitted
17-
! RUN: %flang %s -O1 -Rpass -S %{output} | FileCheck %s
28+
! RUN: %flang %s -O1 -Rpass -S %{output} 2>&1 | FileCheck %s --check-prefix=PASS
1829

1930
! Check full -Rpass-missed message is emitted
20-
! RUN: %flang %s -O1 -Rpass-missed -S %{output} | FileCheck %s --check-prefix=REMARKS-MISSED
31+
! RUN: %flang %s -O1 -Rpass-missed -S %{output} 2>&1 | FileCheck %s --check-prefix=MISSED
2132

2233
! Check full -Rpass-analysis message is emitted
23-
! RUN: %flang %s -O1 -Rpass-analysis -S %{output} | FileCheck %s --check-prefix=REMARKS-ANALYSIS
24-
25-
! CHECK: remark: Loop deleted because it is invariant
26-
! REMARKS-MISSED: {{.*}} will not be inlined into {{.*}} because its definition is unavailable
27-
! REMARKS-MISSED: remark: loop not vectorized
28-
! REMARKS-MISSED-NOT: loop not vectorized: instruction cannot be vectorized
29-
! REMARKS-ANALYSIS: remark: loop not vectorized: instruction cannot be vectorized
30-
! REMARKS-ANALYSIS-NOT: {{.*}} will not be inlined into {{.*}} because its definition is unavailable
34+
! RUN: %flang %s -O1 -Rpass-analysis -S -o /dev/null 2>&1 | FileCheck %s --check-prefix=ANALYSIS
3135

3236
! REMARKS: remark:
3337
! NO-REMARKS-NOT: remark:
3438

35-
program forttest
36-
implicit none
37-
real, dimension(1:50) :: aR1
38-
integer :: n
3939

40-
do n = 1,50
41-
aR1(n) = n * 1.34
42-
print *, "hello"
43-
end do
40+
! With plain -Rpass, -Rpass-missed or -Rpass-analysis, we expect remarks related to 2 opportunities (loop vectorisation / loop delete and load hoisting).
41+
! Once we start filtering, this is reduced to 1 one of the loop passes.
42+
43+
! PASS-REGEX-LOOP-ONLY-NOT: remark: hoisting load
44+
! PASS-REGEX-LOOP-ONLY: remark: Loop deleted because it is invariant
45+
46+
! MISSED-REGEX-LOOP-ONLY-NOT: remark: failed to hoist load with loop-invariant address because load is conditionally executed
47+
! MISSED-REGEX-LOOP-ONLY: remark: loop not vectorized
48+
49+
50+
! 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
51+
! ANALYSIS-REGEX-LOOP-ONLY: Unknown data dependence.
52+
! ANALYSIS-REGEX-LOOP-ONLY-NOT: remark:{{.*}}: IR instruction count changed from {{[0-9]+}} to {{[0-9]+}}; Delta: {{-?[0-9]+}}
53+
54+
! PASS: remark: hoisting load
55+
! PASS: remark: Loop deleted because it is invariant
56+
57+
! MISSED: remark: failed to hoist load with loop-invariant address because load is conditionally executed
58+
! MISSED: remark: loop not vectorized
59+
! 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
60+
! MISSED-NOT: Unknown data dependence.
61+
62+
! 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
63+
! ANALYSIS: Unknown data dependence.
64+
! ANALYSIS: remark: {{.*}}: IR instruction count changed from {{[0-9]+}} to {{[0-9]+}}; Delta: {{-?[0-9]+}}
65+
! ANALYSIS-NOT: remark: failed to hoist load with loop-invariant address because load is conditionally executed
66+
67+
subroutine swap_real(a1, a2)
68+
implicit none
69+
70+
real, dimension(1:2) :: aR1
71+
integer :: i, n
72+
real, intent(inout) :: a1(:), a2(:)
73+
real :: a
74+
75+
! Swap
76+
do i = 1, min(size(a1), size(a2))
77+
a = a1(i)
78+
a1(i) = a2(i)
79+
a2(i) = a
80+
end do
4481

45-
do n = 1,50
82+
! Do a random loop to generate a successful loop-delete pass
83+
do n = 1,2
4684
aR1(n) = n * 1.34
4785
end do
4886

49-
end program forttest
87+
end subroutine swap_real

0 commit comments

Comments
 (0)