/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "opto/addnode.hpp"
#include "opto/callnode.hpp"
#include "opto/cfgnode.hpp"
#include "opto/idealKit.hpp"
#include "opto/runtime.hpp"
// Static initialization
// This declares the position where vars are kept in the cvstate
// For some degree of consistency we use the TypeFunc enum to
// soak up spots in the inputs even though we only use early Control
// and Memory slots. (So far.)
//----------------------------IdealKit-----------------------------------------
_var_ct = 0;
// We can go memory state free or else we need the entire memory state
assert(_initial_memory == NULL || _initial_memory->Opcode() == Op_MergeMem, "memory must be pre-split");
if (!has_declarations) {
}
}
//----------------------------sync_kit-----------------------------------------
}
//-------------------------------if_then-------------------------------------
// Create: if(left relop right)
// / \
// iffalse iftrue
// Push the iffalse cvstate onto the stack. The iftrue becomes the current cvstate.
} else {
}
} else {
}
// Delay gvn.tranform on if-nodes until construction is finished
// to prevent a constant bool input from discarding a control output.
}
//-------------------------------else_-------------------------------------
// Pop the else cvstate off the stack, and push the (current) then cvstate.
// The else cvstate becomes the current cvstate.
// save current (then) cvstate for later use at endif
}
//-------------------------------end_if-------------------------------------
// Merge the "then" and "else" cvstates.
//
// The if_then() pushed a copy of the current state for later use
// as the initial state for a future "else" clause. The
// current state then became the initial state for the
// then clause. If an "else" clause was encountered, it will
// pop the top state and use it for it's initial state.
// It will also push the current state (the state at the end of
// the "then" clause) for latter use at the end_if.
//
// At the endif, the states are:
// 1) else exists a) current state is end of "else" clause
// b) top stack state is end of "then" clause
//
// 2) no else: a) current state is end of "then" clause
// b) top stack state is from the "if_then" which
// would have been the initial state of the else.
//
// Merging the states is accomplished by:
// 1) make a label for the merge
// 2) terminate the current state with a goto to the label
// 3) pop the top state from the stack and make it the
// current state
// 4) bind the label at the current state. Binding a label
// terminates the current state with a goto to the
// label and makes the label's state the current state.
//
// Node* join_state = _pending_cvstates->pop();
/* merging, join */
}
//-------------------------------loop-------------------------------------
// Create the loop head portion (*) of:
// * iv = init
// * top: (region node)
// * if (iv relop limit) {
// loop body
// i = i + 1
// goto top
// * } else // exits loop
//
// Pushes the loop top cvstate first, then the else (loop exit) cvstate
// onto the stack.
void IdealKit::loop(GraphKit* gkit, int nargs, IdealVariable& iv, Node* init, BoolTest::mask relop, Node* limit, float prob, float cnt) {
if (UseLoopPredicate) {
// Sync IdealKit and graphKit.
// Add loop predicate.
// Update IdealKit memory.
}
_cvstate = copy_cvstate();
}
//-------------------------------end_loop-------------------------------------
// Creates the goto top label.
// Expects the else (loop exit) cvstate to be on top of the
// stack, and the loop top cvstate to be 2nd.
}
//-------------------------------make_label-------------------------------------
// Creates a label. The number of goto's
// must be specified (which should be 1 less than
// the number of precedessors.)
return lab;
}
//-------------------------------bind-------------------------------------
// Bind a label at the current cvstate by simulating
// a goto to the label.
}
//-------------------------------goto_-------------------------------------
// Make the current cvstate a predecessor of the label,
// creating phi's to merge values. If bind is true and
// this is not the last control edge, then ensure that
// all live values have phis created. Used to create phis
// at loop-top regions.
// find next empty slot in region
// If this is last predecessor, then don't force phi creation
// l is the value of var reaching the label. Could be a single value
// reaching the label, or a phi that merges multiples values reaching
// the label. The latter is true if the label's input: in(..) is
// a phi whose control input is the region node for the label.
// Get the current value of the var
// If the var went unused no need for a phi
if (m == NULL) {
continue;
} else if (l == NULL || m == l) {
// Only one unique value "m" is known to reach this label so a phi
// is not yet necessary unless:
// the label is being bound and all predecessors have not been seen,
// in which case "bind" will be true.
if (bind) {
m = promote_to_phi(m, reg);
}
} else {
// More than one value for the variable reaches this label so
// a create a phi if one does not already exist.
if (!was_promoted_to_phi(l, reg)) {
l = promote_to_phi(l, reg);
}
// Record in the phi, the var's value from the current state
}
}
stop();
}
//-----------------------------promote_to_phi-----------------------------------
// Get a conservative type for the phi
}
//-----------------------------declarations_done-------------------------------
}
//-----------------------------transform-----------------------------------
if (_delay_all_transforms) {
return delay_transform(n);
} else {
C->record_for_igvn(n);
return n;
}
}
//-----------------------------delay_transform-----------------------------------
// Delay transform until IterativeGVN
C->record_for_igvn(n);
return n;
}
//-----------------------------new_cvstate-----------------------------------
}
//-----------------------------copy_cvstate-----------------------------------
// We must clone memory since it will be updated as we do stores.
return ns;
}
//-----------------------------clear-----------------------------------
}
//-----------------------------IdealVariable----------------------------
k.declare(this);
}
return p;
}
}
//----------------------------- make_load ----------------------------
const Type* t,
int adr_idx,
bool require_atomic_access) {
} else {
}
}
int adr_idx,
bool require_atomic_access) {
} else {
}
return st;
}
// Card mark store. Must be ordered so that it will come after the store of
// the oop.
int adr_idx) {
// Add required edge to oop_store, optimizer does not support precedence edges.
// Convert required edge to precedence edge before allocation.
return st;
}
//---------------------------- do_memory_merge --------------------------------
// The memory from one merging cvstate needs to be merged with the memory for another
// join cvstate. If the join cvstate doesn't have a merged memory yet then we
// can just copy the state from the merging cvstate
// Merge one slow path into the rest of memory.
// Get the region for the join state
}
return;
}
// The control flow for merging must have already been attached to the join region
// we need its index for the phis.
}
// join_m should be an ancestor mergemem of merging
// Slow path memory comes from the current map (which is from a slow call)
// Merge the other fast-memory inputs with the new slow-default memory.
// for (MergeMemStream mms(merged_memory(), fast_mem->as_MergeMem()); mms.next_non_empty2(); ) {
if (join_slice != merging_slice) {
// bool new_phi = false;
// Is the phi for this slice one that we created for this join region or simply
// one we copied? If it is ours then add
} else {
// create the phi with join_slice filling supplying memory for all of the
// control edges to the join region
// gvn().set_type(phi, Type::MEMORY);
// new_phi = true;
}
// Now update the phi with the slice for the merging slice
// this updates join_m with the phi
}
}
if (join_io != merging_io) {
} else {
}
}
}
//----------------------------- make_call ----------------------------
// Trivial runtime call
const char *leaf_name,
// We only handle taking in RawMem and modifying RawMem
// Slow-path leaf call
// Set fixed predefined input arguments
// Narrow memory as only memory input
// Node *c = _gvn.transform(call);
// Slow leaf call has no side-effects, sets few values
// Make memory for the call
// Set the RawPtr memory state only.
"call node must be constructed correctly");
}
const char *leaf_name,
// We only handle taking in RawMem and modifying RawMem
// Slow-path leaf call
CallNode *call = (CallNode*)new (C) CallLeafNoFPNode( slow_call_type, slow_call, leaf_name, adr_type);
// Set fixed predefined input arguments
// Narrow memory as only memory input
// Node *c = _gvn.transform(call);
// Slow leaf call has no side-effects, sets few values
// Make memory for the call
// Set the RawPtr memory state only.
"call node must be constructed correctly");
}