diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-05-31 21:18:39 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-05-31 21:18:39 +0000 |
commit | 6303331c3330222fef94eff8d8d35c99ca1d3e88 (patch) | |
tree | 99ef20c56f1bba3d53736e534b7e49f270169863 /gcc/go/gofrontend/statements.h | |
parent | 2b5360d7477277e7e0f32a5bd5479afac819b5e1 (diff) | |
download | gcc-6303331c3330222fef94eff8d8d35c99ca1d3e88.zip gcc-6303331c3330222fef94eff8d8d35c99ca1d3e88.tar.gz gcc-6303331c3330222fef94eff8d8d35c99ca1d3e88.tar.bz2 |
compiler: optimize append of make
The gc compiler recognizes append(s, make([]T, n)...), and
generates code to directly zero the tail instead of allocating a
new slice and copying. This CL lets the Go frontend do basically
the same.
The difficulty is that at the point we handle append, there may
already be temporaries introduced (e.g. in order_evaluations),
which makes it hard to find the append-of-make pattern. The
compiler could "see through" the value of a temporary, but it is
only safe to do if the temporary is not assigned multiple times.
For this, we add tracking of assignments and uses for temporaries.
This also helps in optimizing non-escape slice make. We already
optimize non-escape slice make with constant len/cap to stack
allocation. But it failed to handle things like f(make([]T, n))
(where the slice doesn't escape and n is constant), because of
the temporary. With tracking of temporary assignments and uses,
it can handle this now as well.
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/179597
From-SVN: r271822
Diffstat (limited to 'gcc/go/gofrontend/statements.h')
-rw-r--r-- | gcc/go/gofrontend/statements.h | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index 2985daa..d621a9a 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -675,7 +675,7 @@ class Temporary_statement : public Statement Temporary_statement(Type* type, Expression* init, Location location) : Statement(STATEMENT_TEMPORARY, location), type_(type), init_(init), bvariable_(NULL), is_address_taken_(false), - value_escapes_(false) + value_escapes_(false), assigned_(false), uses_(0) { } // Return the type of the temporary variable. @@ -687,6 +687,17 @@ class Temporary_statement : public Statement init() const { return this->init_; } + // Set the initializer. + void + set_init(Expression* expr) + { this->init_ = expr; } + + // Whether something takes the address of this temporary + // variable. + bool + is_address_taken() + { return this->is_address_taken_; } + // Record that something takes the address of this temporary // variable. void @@ -703,6 +714,26 @@ class Temporary_statement : public Statement set_value_escapes() { this->value_escapes_ = true; } + // Whether this temporary variable is assigned (after initialization). + bool + assigned() + { return this->assigned_; } + + // Record that this temporary variable is assigned. + void + set_assigned() + { this->assigned_ = true; } + + // Number of uses of this temporary variable. + int + uses() + { return this->uses_; } + + // Add one use of this temporary variable. + void + add_use() + { this->uses_++; } + // Return the temporary variable. This should not be called until // after the statement itself has been converted. Bvariable* @@ -745,6 +776,10 @@ class Temporary_statement : public Statement // True if the value assigned to this temporary variable escapes. // This is used for select statements. bool value_escapes_; + // True if this temporary variable is assigned (after initialization). + bool assigned_; + // Number of uses of this temporary variable. + int uses_; }; // A variable declaration. This marks the point in the code where a |