Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/opto/idealKit.hpp
32285 views
/*1* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_OPTO_IDEALKIT_HPP25#define SHARE_VM_OPTO_IDEALKIT_HPP2627#include "opto/addnode.hpp"28#include "opto/cfgnode.hpp"29#include "opto/connode.hpp"30#include "opto/divnode.hpp"31#include "opto/graphKit.hpp"32#include "opto/mulnode.hpp"33#include "opto/phaseX.hpp"34#include "opto/subnode.hpp"35#include "opto/type.hpp"3637//-----------------------------------------------------------------------------38//----------------------------IdealKit-----------------------------------------39// Set of utilities for creating control flow and scalar SSA data flow.40// Control:41// if_then(left, relop, right)42// else_ (optional)43// end_if44// loop(iv variable, initial, relop, limit)45// - sets iv to initial for first trip46// - exits when relation on limit is true47// - the values of initial and limit should be loop invariant48// - no increment, must be explicitly coded49// - final value of iv is available after end_loop (until dead())50// end_loop51// make_label(number of gotos)52// goto_(label)53// bind(label)54// Data:55// ConI(integer constant) - create an integer constant56// set(variable, value) - assignment57// value(variable) - reference value58// dead(variable) - variable's value is no longer live59// increment(variable, value) - increment variable by value60// simple operations: AddI, SubI, AndI, LShiftI, etc.61// Example:62// Node* limit = ??63// IdealVariable i(kit), j(kit);64// declarations_done();65// Node* exit = make_label(1); // 1 goto66// set(j, ConI(0));67// loop(i, ConI(0), BoolTest::lt, limit); {68// if_then(value(i), BoolTest::gt, ConI(5)) {69// set(j, ConI(1));70// goto_(exit); dead(i);71// } end_if();72// increment(i, ConI(1));73// } end_loop(); dead(i);74// bind(exit);75//76// See string_indexOf for a more complete example.7778class IdealKit;7980// Variable definition for IdealKit81class IdealVariable: public StackObj {82friend class IdealKit;83private:84int _id;85void set_id(int id) { _id = id; }86public:87IdealVariable(IdealKit &k);88int id() { assert(has_id(),"uninitialized id"); return _id; }89bool has_id() { return _id >= 0; }90};9192class IdealKit: public StackObj {93friend class IdealVariable;94// The main state (called a cvstate for Control and Variables)95// contains both the current values of the variables and the96// current set of predecessor control edges. The variable values97// are managed via a Node [in(1)..in(_var_ct)], and the predecessor98// control edges managed via a RegionNode. The in(0) of the Node99// for variables points to the RegionNode for the control edges.100protected:101Compile * const C;102PhaseGVN &_gvn;103GrowableArray<Node*>* _pending_cvstates; // stack of cvstates104Node* _cvstate; // current cvstate (control, memory and variables)105uint _var_ct; // number of variables106bool _delay_all_transforms; // flag forcing all transforms to be delayed107Node* _initial_ctrl; // saves initial control until variables declared108Node* _initial_memory; // saves initial memory until variables declared109Node* _initial_i_o; // saves initial i_o until variables declared110111PhaseGVN& gvn() const { return _gvn; }112// Create a new cvstate filled with nulls113Node* new_cvstate(); // Create a new cvstate114Node* cvstate() { return _cvstate; } // current cvstate115Node* copy_cvstate(); // copy current cvstate116117void set_memory(Node* mem, uint alias_idx );118void do_memory_merge(Node* merging, Node* join);119void clear(Node* m); // clear a cvstate120void stop() { clear(_cvstate); } // clear current cvstate121Node* delay_transform(Node* n);122Node* transform(Node* n); // gvn.transform or skip it123Node* promote_to_phi(Node* n, Node* reg);// Promote "n" to a phi on region "reg"124bool was_promoted_to_phi(Node* n, Node* reg) {125return (n->is_Phi() && n->in(0) == reg);126}127void declare(IdealVariable* v) { v->set_id(_var_ct++); }128// This declares the position where vars are kept in the cvstate129// For some degree of consistency we use the TypeFunc enum to130// soak up spots in the inputs even though we only use early Control131// and Memory slots. (So far.)132static const uint first_var; // = TypeFunc::Parms + 1;133134#ifdef ASSERT135enum State { NullS=0, BlockS=1, LoopS=2, IfThenS=4, ElseS=8, EndifS= 16 };136GrowableArray<int>* _state;137State state() { return (State)(_state->top()); }138#endif139140// Users should not care about slices only MergedMem so no access for them.141Node* memory(uint alias_idx);142143public:144IdealKit(GraphKit* gkit, bool delay_all_transforms = false, bool has_declarations = false);145~IdealKit() {146stop();147}148void sync_kit(GraphKit* gkit);149150// Control151Node* ctrl() { return _cvstate->in(TypeFunc::Control); }152void set_ctrl(Node* ctrl) { _cvstate->set_req(TypeFunc::Control, ctrl); }153Node* top() { return C->top(); }154MergeMemNode* merged_memory() { return _cvstate->in(TypeFunc::Memory)->as_MergeMem(); }155void set_all_memory(Node* mem) { _cvstate->set_req(TypeFunc::Memory, mem); }156Node* i_o() { return _cvstate->in(TypeFunc::I_O); }157void set_i_o(Node* c) { _cvstate->set_req(TypeFunc::I_O, c); }158void set(IdealVariable& v, Node* rhs) { _cvstate->set_req(first_var + v.id(), rhs); }159Node* value(IdealVariable& v) { return _cvstate->in(first_var + v.id()); }160void dead(IdealVariable& v) { set(v, (Node*)NULL); }161void if_then(Node* left, BoolTest::mask relop, Node* right,162float prob = PROB_FAIR, float cnt = COUNT_UNKNOWN,163bool push_new_state = true);164void else_();165void end_if();166void loop(GraphKit* gkit, int nargs, IdealVariable& iv, Node* init, BoolTest::mask cmp, Node* limit,167float prob = PROB_LIKELY(0.9), float cnt = COUNT_UNKNOWN);168void end_loop();169Node* make_label(int goto_ct);170void bind(Node* lab);171void goto_(Node* lab, bool bind = false);172void declarations_done();173174Node* IfTrue(IfNode* iff) { return transform(new (C) IfTrueNode(iff)); }175Node* IfFalse(IfNode* iff) { return transform(new (C) IfFalseNode(iff)); }176177// Data178Node* ConI(jint k) { return (Node*)gvn().intcon(k); }179Node* makecon(const Type *t) const { return _gvn.makecon(t); }180181Node* AddI(Node* l, Node* r) { return transform(new (C) AddINode(l, r)); }182Node* SubI(Node* l, Node* r) { return transform(new (C) SubINode(l, r)); }183Node* AndI(Node* l, Node* r) { return transform(new (C) AndINode(l, r)); }184Node* MaxI(Node* l, Node* r) { return transform(new (C) MaxINode(l, r)); }185Node* LShiftI(Node* l, Node* r) { return transform(new (C) LShiftINode(l, r)); }186Node* CmpI(Node* l, Node* r) { return transform(new (C) CmpINode(l, r)); }187Node* Bool(Node* cmp, BoolTest::mask relop) { return transform(new (C) BoolNode(cmp, relop)); }188void increment(IdealVariable& v, Node* j) { set(v, AddI(value(v), j)); }189void decrement(IdealVariable& v, Node* j) { set(v, SubI(value(v), j)); }190191Node* CmpL(Node* l, Node* r) { return transform(new (C) CmpLNode(l, r)); }192193// TLS194Node* thread() { return gvn().transform(new (C) ThreadLocalNode()); }195196// Pointers197198// Raw address should be transformed regardless 'delay_transform' flag199// to produce canonical form CastX2P(offset).200Node* AddP(Node *base, Node *ptr, Node *off) { return _gvn.transform(new (C) AddPNode(base, ptr, off)); }201202Node* CmpP(Node* l, Node* r) { return transform(new (C) CmpPNode(l, r)); }203#ifdef _LP64204Node* XorX(Node* l, Node* r) { return transform(new (C) XorLNode(l, r)); }205#else // _LP64206Node* XorX(Node* l, Node* r) { return transform(new (C) XorINode(l, r)); }207#endif // _LP64208Node* URShiftX(Node* l, Node* r) { return transform(new (C) URShiftXNode(l, r)); }209Node* ConX(jint k) { return (Node*)gvn().MakeConX(k); }210Node* CastPX(Node* ctl, Node* p) { return transform(new (C) CastP2XNode(ctl, p)); }211212// Memory operations213214// This is the base version which is given an alias index.215Node* load(Node* ctl,216Node* adr,217const Type* t,218BasicType bt,219int adr_idx,220bool require_atomic_access = false);221222// Return the new StoreXNode223Node* store(Node* ctl,224Node* adr,225Node* val,226BasicType bt,227int adr_idx,228MemNode::MemOrd mo,229bool require_atomic_access = false,230bool mismatched = false231);232233// Store a card mark ordered after store_oop234Node* storeCM(Node* ctl,235Node* adr,236Node* val,237Node* oop_store,238int oop_adr_idx,239BasicType bt,240int adr_idx);241242// Trivial call243void make_leaf_call(const TypeFunc *slow_call_type,244address slow_call,245const char *leaf_name,246Node* parm0,247Node* parm1 = NULL,248Node* parm2 = NULL,249Node* parm3 = NULL);250251void make_leaf_call_no_fp(const TypeFunc *slow_call_type,252address slow_call,253const char *leaf_name,254const TypePtr* adr_type,255Node* parm0,256Node* parm1,257Node* parm2,258Node* parm3);259260};261262#endif // SHARE_VM_OPTO_IDEALKIT_HPP263264265