This patch to the Go frontend by Cherry Zhang adds a
-fgo-debug-optimization option to emit optimization diagnostics. This
can be used for testing optimizations. Apply this to the range clear
optimizations of maps and arrays. Bootstrapped and ran Go testsuite
on x86_64-pc-linux-gnu. Committed to mainline.
Ian
gcc/go:
2019-05-07 Cherry Zhang <[email protected]>
* lang.opt (-fgo-debug-optimization): New option.
* go-c.h (struct go_create_gogo_args): Add debug_optimization
field.
* go-lang.c (go_langhook_init): Set debug_optimization field.
* gccgo.texi (Invoking gccgo): Document -fgo-debug-optimization.
gcc/testsuite:
2019-05-07 Cherry Zhang <[email protected]>
* go.dg/arrayclear.go: New test.
* go.dg/mapclear.go: New test.
Index: gcc/go/gccgo.texi
===================================================================
--- gcc/go/gccgo.texi (revision 270877)
+++ gcc/go/gccgo.texi (working copy)
@@ -246,6 +246,11 @@ This runs escape analysis only on functi
that match the given suffix @var{n}. This can be used to binary
search across functions to uncover escape analysis bugs.
+@item -fgo-debug-optimization
+@cindex @option{-fgo-debug-optimization}
+@cindex @option{-fno-go-debug-optimization}
+Output optimization diagnostics.
+
@item -fgo-c-header=@var{file}
@cindex @option{-fgo-c-header}
Write top-level named Go struct definitions to @var{file} as C code.
Index: gcc/go/go-c.h
===================================================================
--- gcc/go/go-c.h (revision 270877)
+++ gcc/go/go-c.h (working copy)
@@ -49,6 +49,7 @@ struct go_create_gogo_args
int debug_escape_level;
const char* debug_escape_hash;
int64_t nil_check_size_threshold;
+ bool debug_optimization;
};
extern void go_create_gogo (const struct go_create_gogo_args*);
Index: gcc/go/go-lang.c
===================================================================
--- gcc/go/go-lang.c (revision 270877)
+++ gcc/go/go-lang.c (working copy)
@@ -118,6 +118,7 @@ go_langhook_init (void)
args.debug_escape_level = go_debug_escape_level;
args.debug_escape_hash = go_debug_escape_hash;
args.nil_check_size_threshold = TARGET_AIX ? -1 : 4096;
+ args.debug_optimization = go_debug_optimization;
args.linemap = go_get_linemap();
args.backend = go_get_backend();
go_create_gogo (&args);
Index: gcc/go/gofrontend/MERGE
===================================================================
--- gcc/go/gofrontend/MERGE (revision 270877)
+++ gcc/go/gofrontend/MERGE (working copy)
@@ -1,4 +1,4 @@
-4b3015de639cf22ed11ff96097555700909827c8
+dc9c1b43753f392fdc2045bcb7a4abaa44fe79f1
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
Index: gcc/go/gofrontend/go.cc
===================================================================
--- gcc/go/gofrontend/go.cc (revision 270877)
+++ gcc/go/gofrontend/go.cc (working copy)
@@ -44,6 +44,8 @@ go_create_gogo(const struct go_create_go
if (args->debug_escape_hash != NULL)
::gogo->set_debug_escape_hash(args->debug_escape_hash);
::gogo->set_nil_check_size_threshold(args->nil_check_size_threshold);
+ if (args->debug_optimization)
+ ::gogo->set_debug_optimization(args->debug_optimization);
}
// Parse the input files.
Index: gcc/go/gofrontend/gogo.cc
===================================================================
--- gcc/go/gofrontend/gogo.cc (revision 270877)
+++ gcc/go/gofrontend/gogo.cc (working copy)
@@ -55,6 +55,7 @@ Gogo::Gogo(Backend* backend, Linemap* li
check_divide_overflow_(true),
compiling_runtime_(false),
debug_escape_level_(0),
+ debug_optimization_(false),
nil_check_size_threshold_(4096),
verify_types_(),
interface_types_(),
Index: gcc/go/gofrontend/gogo.h
===================================================================
--- gcc/go/gofrontend/gogo.h (revision 270877)
+++ gcc/go/gofrontend/gogo.h (working copy)
@@ -326,6 +326,16 @@ class Gogo
set_debug_escape_hash(const std::string& s)
{ this->debug_escape_hash_ = s; }
+ // Return whether to output optimization diagnostics.
+ bool
+ debug_optimization() const
+ { return this->debug_optimization_; }
+
+ // Set the option to output optimization diagnostics.
+ void
+ set_debug_optimization(bool b)
+ { this->debug_optimization_ = b; }
+
// Return the size threshold used to determine whether to issue
// a nil-check for a given pointer dereference. A threshold of -1
// implies that all potentially faulting dereference ops should
@@ -1075,6 +1085,9 @@ class Gogo
// -fgo-debug-escape-hash option. The analysis is run only on
// functions with names that hash to the matching value.
std::string debug_escape_hash_;
+ // Whether to output optimization diagnostics, from the
+ // -fgo-debug-optimization option.
+ bool debug_optimization_;
// Nil-check size threshhold.
int64_t nil_check_size_threshold_;
// A list of types to verify.
Index: gcc/go/gofrontend/statements.cc
===================================================================
--- gcc/go/gofrontend/statements.cc (revision 270877)
+++ gcc/go/gofrontend/statements.cc (working copy)
@@ -5512,6 +5512,8 @@ For_range_statement::do_lower(Gogo* gogo
range_temp, loc);
if (clear != NULL)
{
+ if (gogo->debug_optimization())
+ go_inform(loc, "map range clear");
temp_block->add_statement(clear);
return Statement::make_block_statement(temp_block, loc);
}
@@ -5527,6 +5529,8 @@ For_range_statement::do_lower(Gogo* gogo
range_temp, loc);
if (clear != NULL)
{
+ if (gogo->debug_optimization())
+ go_inform(loc, "array range clear");
temp_block->add_statement(clear);
return Statement::make_block_statement(temp_block, loc);
}
Index: gcc/go/lang.opt
===================================================================
--- gcc/go/lang.opt (revision 270877)
+++ gcc/go/lang.opt (working copy)
@@ -85,6 +85,10 @@ fgo-debug-escape-hash=
Go Joined RejectNegative Var(go_debug_escape_hash) Init(0)
-fgo-debug-escape-hash=<string> Hash value to debug escape analysis.
+fgo-debug-optimization
+Go Var(go_debug_optimization) Init(0)
+Emit optimization diagnostics.
+
o
Go Joined Separate
; Documented in common.opt
Index: gcc/testsuite/go.dg/arrayclear.go
===================================================================
--- gcc/testsuite/go.dg/arrayclear.go (nonexistent)
+++ gcc/testsuite/go.dg/arrayclear.go (working copy)
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+var a [10]int
+
+func arrayClear() {
+ for i := range a { // { dg-error "array range clear" }
+ a[i] = 0
+ }
+}
+
+var s []int
+
+func sliceClear() {
+ for i := range s { // { dg-error "array range clear" }
+ s[i] = 0
+ }
+}
Index: gcc/testsuite/go.dg/mapclear.go
===================================================================
--- gcc/testsuite/go.dg/mapclear.go (nonexistent)
+++ gcc/testsuite/go.dg/mapclear.go (working copy)
@@ -0,0 +1,10 @@
+// { dg-do compile }
+// { dg-options "-fgo-debug-optimization" }
+
+package p
+
+func clear(m map[int]int) {
+ for k := range m { // { dg-error "map range clear" }
+ delete(m, k)
+ }
+}