1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "opto/castnode.hpp" 27 #include "opto/graphKit.hpp" 28 #include "opto/phaseX.hpp" 29 #include "opto/rootnode.hpp" 30 #include "opto/vector.hpp" 31 #include "utilities/macros.hpp" 32 33 void PhaseVector::optimize_vector_boxes() { 34 Compile::TracePhase tp("vector_elimination", &timers[_t_vector_elimination]); 35 36 assert(C->inlining_incrementally() == false, "sanity"); 37 38 C->set_inlining_incrementally(true); // FIXME another way to signal GraphKit it's post-parsing phase? 39 40 C->for_igvn()->clear(); 41 C->initial_gvn()->replace_with(&_igvn); 42 43 expand_vunbox_nodes(); 44 scalarize_vbox_nodes(); 45 46 C->inline_vector_reboxing_calls(); 47 48 expand_vbox_nodes(); 49 eliminate_vbox_alloc_nodes(); 50 51 C->set_inlining_incrementally(false); // FIXME another way to signal GraphKit it's post-parsing phase? 52 53 do_cleanup(); 54 } 55 56 void PhaseVector::do_cleanup() { 57 if (C->failing()) return; 58 { 59 Compile::TracePhase tp("vector_pru", &timers[_t_vector_pru]); 60 ResourceMark rm; 61 PhaseRemoveUseless pru(C->initial_gvn(), C->for_igvn()); 62 } 63 64 if (C->failing()) return; 65 66 { 67 Compile::TracePhase tp("incrementalInline_igvn", &timers[_t_vector_igvn]); 68 _igvn = PhaseIterGVN(C->initial_gvn()); 69 _igvn.optimize(); 70 } 71 } 72 73 void PhaseVector::scalarize_vbox_nodes() { 74 if (C->failing()) return; 75 76 if (!EnableVectorReboxing) { 77 return; // don't scalarize vector boxes 78 } 79 80 int macro_idx = C->macro_count() - 1; 81 while (macro_idx >= 0) { 82 Node * n = C->macro_node(macro_idx); 83 assert(n->is_macro(), "only macro nodes expected here"); 84 if (n->Opcode() == Op_VectorBox) { 85 VectorBoxNode* vbox = static_cast<VectorBoxNode*>(n); 86 scalarize_vbox_node(vbox); 87 if (C->failing()) return; 88 C->print_method(PHASE_SCALARIZE_VBOX, vbox, 3); 89 } 90 if (C->failing()) return; 91 macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); 92 } 93 } 94 95 void PhaseVector::expand_vbox_nodes() { 96 if (C->failing()) return; 97 98 int macro_idx = C->macro_count() - 1; 99 while (macro_idx >= 0) { 100 Node * n = C->macro_node(macro_idx); 101 assert(n->is_macro(), "only macro nodes expected here"); 102 if (n->Opcode() == Op_VectorBox) { 103 VectorBoxNode* vbox = static_cast<VectorBoxNode*>(n); 104 expand_vbox_node(vbox); 105 if (C->failing()) return; 106 C->print_method(PHASE_EXPAND_VBOX, vbox, 3); 107 } 108 if (C->failing()) return; 109 macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); 110 } 111 } 112 113 void PhaseVector::expand_vunbox_nodes() { 114 if (C->failing()) return; 115 116 int macro_idx = C->macro_count() - 1; 117 while (macro_idx >= 0) { 118 Node * n = C->macro_node(macro_idx); 119 assert(n->is_macro(), "only macro nodes expected here"); 120 if (n->Opcode() == Op_VectorUnbox) { 121 VectorUnboxNode* vec_unbox = static_cast<VectorUnboxNode*>(n); 122 expand_vunbox_node(vec_unbox); 123 if (C->failing()) return; 124 C->print_method(PHASE_EXPAND_VUNBOX, vec_unbox, 3); 125 } 126 if (C->failing()) return; 127 macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); 128 } 129 } 130 131 void PhaseVector::eliminate_vbox_alloc_nodes() { 132 if (C->failing()) return; 133 134 int macro_idx = C->macro_count() - 1; 135 while (macro_idx >= 0) { 136 Node * n = C->macro_node(macro_idx); 137 assert(n->is_macro(), "only macro nodes expected here"); 138 if (n->Opcode() == Op_VectorBoxAllocate) { 139 VectorBoxAllocateNode* vbox_alloc = static_cast<VectorBoxAllocateNode*>(n); 140 eliminate_vbox_alloc_node(vbox_alloc); 141 if (C->failing()) return; 142 C->print_method(PHASE_ELIMINATE_VBOX_ALLOC, vbox_alloc, 3); 143 } 144 if (C->failing()) return; 145 macro_idx = MIN2(macro_idx - 1, C->macro_count() - 1); 146 } 147 } 148 149 static JVMState* clone_jvms(Compile* C, SafePointNode* sfpt) { 150 JVMState* new_jvms = sfpt->jvms()->clone_shallow(C); 151 uint size = sfpt->req(); 152 SafePointNode* map = new SafePointNode(size, new_jvms); 153 for (uint i = 0; i < size; i++) { 154 map->init_req(i, sfpt->in(i)); 155 } 156 new_jvms->set_map(map); 157 return new_jvms; 158 } 159 160 void PhaseVector::scalarize_vbox_node(VectorBoxNode* vec_box) { 161 Node* vec_value = vec_box->in(VectorBoxNode::Value); 162 PhaseGVN& gvn = *C->initial_gvn(); 163 164 // Process merged VBAs 165 166 if (EnableVectorAggressiveReboxing) { 167 Unique_Node_List calls(C->comp_arena()); 168 for (DUIterator_Fast imax, i = vec_box->fast_outs(imax); i < imax; i++) { 169 Node* use = vec_box->fast_out(i); 170 if (use->is_CallJava()) { 171 CallJavaNode* call = use->as_CallJava(); 172 if (call->has_non_debug_use(vec_box) && vec_box->in(VectorBoxNode::Box)->is_Phi()) { 173 calls.push(call); 174 } 175 } 176 } 177 178 while (calls.size() > 0) { 179 CallJavaNode* call = calls.pop()->as_CallJava(); 180 // Attach new VBA to the call and use it instead of Phi (VBA ... VBA). 181 182 JVMState* jvms = clone_jvms(C, call); 183 GraphKit kit(jvms); 184 PhaseGVN& gvn = kit.gvn(); 185 186 // Adjust JVMS from post-call to pre-call state: put args on stack 187 uint nargs = call->method()->arg_size(); 188 kit.ensure_stack(kit.sp() + nargs); 189 for (uint i = TypeFunc::Parms; i < call->tf()->domain()->cnt(); i++) { 190 kit.push(call->in(i)); 191 } 192 jvms = kit.sync_jvms(); 193 194 Node* new_vbox = NULL; 195 { 196 PreserveReexecuteState prs(&kit); 197 198 kit.jvms()->set_should_reexecute(true); 199 200 const TypeInstPtr* vbox_type = vec_box->box_type(); 201 const TypeVect* vect_type = vec_box->vec_type(); 202 Node* vect = vec_box->in(VectorBoxNode::Value); 203 204 VectorBoxAllocateNode* alloc = new VectorBoxAllocateNode(C, vbox_type); 205 kit.set_edges_for_java_call(alloc, /*must_throw=*/false, /*separate_io_proj=*/true); 206 kit.make_slow_call_ex(alloc, C->env()->Throwable_klass(), /*separate_io_proj=*/true, /*deoptimize=*/true); 207 kit.set_i_o(gvn.transform( new ProjNode(alloc, TypeFunc::I_O) )); 208 kit.set_all_memory(gvn.transform( new ProjNode(alloc, TypeFunc::Memory) )); 209 Node* ret = gvn.transform(new ProjNode(alloc, TypeFunc::Parms)); 210 211 new_vbox = gvn.transform(new VectorBoxNode(C, ret, vect, vbox_type, vect_type)); 212 213 kit.replace_in_map(vec_box, new_vbox); 214 } 215 216 kit.dec_sp(nargs); 217 jvms = kit.sync_jvms(); 218 219 call->set_req(TypeFunc::Control , kit.control()); 220 call->set_req(TypeFunc::I_O , kit.i_o()); 221 call->set_req(TypeFunc::Memory , kit.reset_memory()); 222 call->set_req(TypeFunc::FramePtr, kit.frameptr()); 223 call->replace_edge(vec_box, new_vbox); 224 225 C->record_for_igvn(call); 226 } 227 } 228 229 // Process debug uses at safepoints 230 Unique_Node_List safepoints(C->comp_arena()); 231 232 for (DUIterator_Fast imax, i = vec_box->fast_outs(imax); i < imax; i++) { 233 Node* use = vec_box->fast_out(i); 234 if (use->is_SafePoint()) { 235 SafePointNode* sfpt = use->as_SafePoint(); 236 if (!sfpt->is_Call() || !sfpt->as_Call()->has_non_debug_use(vec_box)) { 237 safepoints.push(sfpt); 238 } 239 } 240 } 241 242 while (safepoints.size() > 0) { 243 SafePointNode* sfpt = safepoints.pop()->as_SafePoint(); 244 245 uint first_ind = (sfpt->req() - sfpt->jvms()->scloff()); 246 Node* sobj = new SafePointScalarObjectNode(vec_box->box_type(), 247 #ifdef ASSERT 248 NULL, 249 #endif // ASSERT 250 first_ind, /*n_fields=*/1); 251 sobj->init_req(0, C->root()); 252 sfpt->add_req(vec_value); 253 254 sobj = gvn.transform(sobj); 255 256 JVMState *jvms = sfpt->jvms(); 257 258 jvms->set_endoff(sfpt->req()); 259 // Now make a pass over the debug information replacing any references 260 // to the allocated object with "sobj" 261 int start = jvms->debug_start(); 262 int end = jvms->debug_end(); 263 sfpt->replace_edges_in_range(vec_box, sobj, start, end); 264 265 C->record_for_igvn(sfpt); 266 } 267 } 268 269 void PhaseVector::expand_vbox_node(VectorBoxNode* vec_box) { 270 if (vec_box->outcnt() > 0) { 271 Node* vbox = vec_box->in(VectorBoxNode::Box); 272 Node* vect = vec_box->in(VectorBoxNode::Value); 273 Node* result = expand_vbox_node_helper(vbox, vect, vec_box->box_type(), vec_box->vec_type()); 274 C->gvn_replace_by(vec_box, result); 275 } 276 C->remove_macro_node(vec_box); 277 } 278 279 Node* PhaseVector::expand_vbox_node_helper(Node* vbox, 280 Node* vect, 281 const TypeInstPtr* box_type, 282 const TypeVect* vect_type) { 283 if (vbox->is_Phi() && vect->is_Phi()) { 284 assert(vbox->as_Phi()->region() == vect->as_Phi()->region(), ""); 285 Node* new_phi = new PhiNode(vbox->as_Phi()->region(), box_type); 286 for (uint i = 1; i < vbox->req(); i++) { 287 Node* new_box = expand_vbox_node_helper(vbox->in(i), vect->in(i), box_type, vect_type); 288 new_phi->set_req(i, new_box); 289 } 290 new_phi = C->initial_gvn()->transform(new_phi); 291 return new_phi; 292 } else if (vbox->is_Proj() && vbox->in(0)->Opcode() == Op_VectorBoxAllocate) { 293 VectorBoxAllocateNode* vbox_alloc = static_cast<VectorBoxAllocateNode*>(vbox->in(0)); 294 return expand_vbox_alloc_node(vbox_alloc, vect, box_type, vect_type); 295 } else { 296 assert(!vbox->is_Phi(), ""); 297 // TODO: ensure that expanded vbox is initialized with the same value (vect). 298 return vbox; // already expanded 299 } 300 } 301 302 static bool is_vector_mask(ciKlass* klass) { 303 return klass->is_subclass_of(ciEnv::current()->vector_VectorMask_klass()); 304 } 305 306 static bool is_vector_shuffle(ciKlass* klass) { 307 return klass->is_subclass_of(ciEnv::current()->vector_VectorShuffle_klass()); 308 } 309 310 Node* PhaseVector::expand_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc, 311 Node* value, 312 const TypeInstPtr* box_type, 313 const TypeVect* vect_type) { 314 JVMState* jvms = clone_jvms(C, vbox_alloc); 315 GraphKit kit(jvms); 316 PhaseGVN& gvn = kit.gvn(); 317 318 ciInstanceKlass* box_klass = box_type->klass()->as_instance_klass(); 319 BasicType bt = vect_type->element_basic_type(); 320 int num_elem = vect_type->length(); 321 322 bool is_mask = is_vector_mask(box_klass); 323 if (is_mask && bt != T_BOOLEAN) { 324 value = gvn.transform(new VectorStoreMaskNode(value, bt, num_elem)); 325 // Although type of mask depends on its definition, in terms of storage everything is stored in boolean array. 326 bt = T_BOOLEAN; 327 assert(value->as_Vector()->bottom_type()->is_vect()->element_basic_type() == bt, 328 "must be consistent with mask representation"); 329 } 330 331 // Generate array allocation for the field which holds the values. 332 const TypeKlassPtr* array_klass = TypeKlassPtr::make(ciTypeArrayKlass::make(bt)); 333 Node* arr = kit.new_array(kit.makecon(array_klass), kit.intcon(num_elem), 1); 334 335 // Store the vector value into the array. 336 // (The store should be captured by InitializeNode and turned into initialized store later.) 337 Node* arr_adr = kit.array_element_address(arr, kit.intcon(0), bt); 338 const TypePtr* arr_adr_type = arr_adr->bottom_type()->is_ptr(); 339 Node* arr_mem = kit.memory(arr_adr); 340 Node* vstore = gvn.transform(StoreVectorNode::make(0, 341 kit.control(), 342 arr_mem, 343 arr_adr, 344 arr_adr_type, 345 value, 346 num_elem)); 347 kit.set_memory(vstore, arr_adr_type); 348 349 C->set_max_vector_size(MAX2(C->max_vector_size(), vect_type->length_in_bytes())); 350 351 // Generate the allocate for the Vector object. 352 const TypeKlassPtr* klass_type = box_type->as_klass_type(); 353 Node* klass_node = kit.makecon(klass_type); 354 Node* vec_obj = kit.new_instance(klass_node); 355 356 // Store the allocated array into object. 357 ciField* field = ciEnv::current()->vector_VectorPayload_klass()->get_field_by_name(ciSymbol::payload_name(), 358 ciSymbol::object_signature(), 359 false); 360 assert(field != NULL, ""); 361 Node* vec_field = kit.basic_plus_adr(vec_obj, field->offset_in_bytes()); 362 const TypePtr* vec_adr_type = vec_field->bottom_type()->is_ptr(); 363 364 // The store should be captured by InitializeNode and turned into initialized store later. 365 Node* field_store = gvn.transform(kit.access_store_at(vec_obj, 366 vec_field, 367 vec_adr_type, 368 arr, 369 TypeOopPtr::make_from_klass(field->type()->as_klass()), 370 T_OBJECT, 371 IN_HEAP)); 372 kit.set_memory(field_store, vec_adr_type); 373 374 kit.replace_call(vbox_alloc, vec_obj, true); 375 C->remove_macro_node(vbox_alloc); 376 return vec_obj; 377 } 378 379 void PhaseVector::expand_vunbox_node(VectorUnboxNode* vec_unbox) { 380 if (vec_unbox->outcnt() > 0) { 381 GraphKit kit; 382 PhaseGVN& gvn = kit.gvn(); 383 384 Node* obj = vec_unbox->obj(); 385 const TypeInstPtr* tinst = gvn.type(obj)->isa_instptr(); 386 ciInstanceKlass* from_kls = tinst->klass()->as_instance_klass(); 387 BasicType bt = vec_unbox->vect_type()->element_basic_type(); 388 BasicType masktype = bt; 389 BasicType elem_bt; 390 391 if (is_vector_mask(from_kls)) { 392 bt = T_BOOLEAN; 393 } else if (is_vector_shuffle(from_kls)) { 394 if (vec_unbox->is_shuffle_to_vector() == true) { 395 elem_bt = bt; 396 } 397 bt = T_BYTE; 398 } 399 400 ciField* field = ciEnv::current()->vector_VectorPayload_klass()->get_field_by_name(ciSymbol::payload_name(), 401 ciSymbol::object_signature(), 402 false); 403 assert(field != NULL, ""); 404 int offset = field->offset_in_bytes(); 405 Node* vec_adr = kit.basic_plus_adr(obj, offset); 406 407 Node* mem = vec_unbox->mem(); 408 Node* ctrl = vec_unbox->in(0); 409 Node* vec_field_ld = LoadNode::make(gvn, 410 ctrl, 411 mem, 412 vec_adr, 413 vec_adr->bottom_type()->is_ptr(), 414 TypeOopPtr::make_from_klass(field->type()->as_klass()), 415 T_OBJECT, 416 MemNode::unordered); 417 vec_field_ld = gvn.transform(vec_field_ld); 418 419 // For proper aliasing, attach concrete payload type. 420 ciKlass* payload_klass = ciTypeArrayKlass::make(bt); 421 const Type* payload_type = TypeAryPtr::make_from_klass(payload_klass)->cast_to_ptr_type(TypePtr::NotNull); 422 vec_field_ld = gvn.transform(new CastPPNode(vec_field_ld, payload_type)); 423 424 Node* adr = kit.array_element_address(vec_field_ld, gvn.intcon(0), bt); 425 const TypePtr* adr_type = adr->bottom_type()->is_ptr(); 426 const TypeVect* vt = vec_unbox->bottom_type()->is_vect(); 427 int num_elem = vt->length(); 428 Node* vec_val_load = LoadVectorNode::make(0, 429 ctrl, 430 mem, 431 adr, 432 adr_type, 433 num_elem, 434 bt); 435 vec_val_load = gvn.transform(vec_val_load); 436 437 C->set_max_vector_size(MAX2(C->max_vector_size(), vt->length_in_bytes())); 438 439 if (is_vector_mask(from_kls) && masktype != T_BOOLEAN) { 440 assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect mask type consistency"); 441 vec_val_load = gvn.transform(new VectorLoadMaskNode(vec_val_load, TypeVect::make(masktype, num_elem))); 442 } else if (is_vector_shuffle(from_kls)) { 443 if (vec_unbox->is_shuffle_to_vector() == false) { 444 assert(vec_unbox->bottom_type()->is_vect()->element_basic_type() == masktype, "expect shuffle type consistency"); 445 vec_val_load = gvn.transform(new VectorLoadShuffleNode(vec_val_load, TypeVect::make(masktype, num_elem))); 446 } else if (elem_bt != T_BYTE) { 447 vec_val_load = gvn.transform(VectorCastNode::make(Op_VectorCastB2X, vec_val_load, elem_bt, num_elem)); 448 } 449 } 450 451 gvn.hash_delete(vec_unbox); 452 vec_unbox->disconnect_inputs(NULL, C); 453 C->gvn_replace_by(vec_unbox, vec_val_load); 454 } 455 C->remove_macro_node(vec_unbox); 456 } 457 458 void PhaseVector::eliminate_vbox_alloc_node(VectorBoxAllocateNode* vbox_alloc) { 459 JVMState* jvms = clone_jvms(C, vbox_alloc); 460 GraphKit kit(jvms); 461 // Remove VBA, but leave a safepoint behind. 462 // Otherwise, it may end up with a loop without any safepoint polls. 463 kit.replace_call(vbox_alloc, kit.map(), true); 464 C->remove_macro_node(vbox_alloc); 465 }