mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-20 19:14:38 +02:00
6892658: C2 should optimize some stringbuilder patterns
Reviewed-by: kvn, twisti
This commit is contained in:
parent
63cc2211ed
commit
9db2092b1b
35 changed files with 2245 additions and 115 deletions
|
@ -224,6 +224,32 @@ bool Compile::valid_bundle_info(const Node *n) {
|
|||
}
|
||||
|
||||
|
||||
void Compile::gvn_replace_by(Node* n, Node* nn) {
|
||||
for (DUIterator_Last imin, i = n->last_outs(imin); i >= imin; ) {
|
||||
Node* use = n->last_out(i);
|
||||
bool is_in_table = initial_gvn()->hash_delete(use);
|
||||
uint uses_found = 0;
|
||||
for (uint j = 0; j < use->len(); j++) {
|
||||
if (use->in(j) == n) {
|
||||
if (j < use->req())
|
||||
use->set_req(j, nn);
|
||||
else
|
||||
use->set_prec(j, nn);
|
||||
uses_found++;
|
||||
}
|
||||
}
|
||||
if (is_in_table) {
|
||||
// reinsert into table
|
||||
initial_gvn()->hash_find_insert(use);
|
||||
}
|
||||
record_for_igvn(use);
|
||||
i -= uses_found; // we deleted 1 or more copies of this edge
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Identify all nodes that are reachable from below, useful.
|
||||
// Use breadth-first pass that records state in a Unique_Node_List,
|
||||
// recursive traversal is slower.
|
||||
|
@ -554,6 +580,28 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
|||
rethrow_exceptions(kit.transfer_exceptions_into_jvms());
|
||||
}
|
||||
|
||||
if (!failing() && has_stringbuilder()) {
|
||||
{
|
||||
// remove useless nodes to make the usage analysis simpler
|
||||
ResourceMark rm;
|
||||
PhaseRemoveUseless pru(initial_gvn(), &for_igvn);
|
||||
}
|
||||
|
||||
{
|
||||
ResourceMark rm;
|
||||
print_method("Before StringOpts", 3);
|
||||
PhaseStringOpts pso(initial_gvn(), &for_igvn);
|
||||
print_method("After StringOpts", 3);
|
||||
}
|
||||
|
||||
// now inline anything that we skipped the first time around
|
||||
while (_late_inlines.length() > 0) {
|
||||
CallGenerator* cg = _late_inlines.pop();
|
||||
cg->do_late_inline();
|
||||
}
|
||||
}
|
||||
assert(_late_inlines.length() == 0, "should have been processed");
|
||||
|
||||
print_method("Before RemoveUseless", 3);
|
||||
|
||||
// Remove clutter produced by parsing.
|
||||
|
@ -820,6 +868,7 @@ void Compile::Init(int aliaslevel) {
|
|||
_fixed_slots = 0;
|
||||
set_has_split_ifs(false);
|
||||
set_has_loops(has_method() && method()->has_loops()); // first approximation
|
||||
set_has_stringbuilder(false);
|
||||
_deopt_happens = true; // start out assuming the worst
|
||||
_trap_can_recompile = false; // no traps emitted yet
|
||||
_major_progress = true; // start out assuming good things will happen
|
||||
|
@ -2240,6 +2289,30 @@ static void final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc ) {
|
|||
break;
|
||||
}
|
||||
|
||||
case Op_Proj: {
|
||||
if (OptimizeStringConcat) {
|
||||
ProjNode* p = n->as_Proj();
|
||||
if (p->_is_io_use) {
|
||||
// Separate projections were used for the exception path which
|
||||
// are normally removed by a late inline. If it wasn't inlined
|
||||
// then they will hang around and should just be replaced with
|
||||
// the original one.
|
||||
Node* proj = NULL;
|
||||
// Replace with just one
|
||||
for (SimpleDUIterator i(p->in(0)); i.has_next(); i.next()) {
|
||||
Node *use = i.get();
|
||||
if (use->is_Proj() && p != use && use->as_Proj()->_con == p->_con) {
|
||||
proj = use;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(p != NULL, "must be found");
|
||||
p->subsume_by(proj);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Op_Phi:
|
||||
if (n->as_Phi()->bottom_type()->isa_narrowoop()) {
|
||||
// The EncodeP optimization may create Phi with the same edges
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue