multnode.cpp revision 7438:269dae261504
1306196Sjkim/* 2160819Ssimon * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3160819Ssimon * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4160819Ssimon * 5160819Ssimon * This code is free software; you can redistribute it and/or modify it 6160819Ssimon * under the terms of the GNU General Public License version 2 only, as 7160819Ssimon * published by the Free Software Foundation. 8160819Ssimon * 9160819Ssimon * This code is distributed in the hope that it will be useful, but WITHOUT 10160819Ssimon * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11160819Ssimon * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12160819Ssimon * version 2 for more details (a copy is included in the LICENSE file that 13160819Ssimon * accompanied this code). 14160819Ssimon * 15160819Ssimon * You should have received a copy of the GNU General Public License version 16160819Ssimon * 2 along with this work; if not, write to the Free Software Foundation, 17160819Ssimon * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18160819Ssimon * 19160819Ssimon * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20215698Ssimon * or visit www.oracle.com if you need additional information or have any 21215698Ssimon * questions. 22215698Ssimon * 23215698Ssimon */ 24215698Ssimon 25160819Ssimon#include "precompiled.hpp" 26160819Ssimon#include "opto/callnode.hpp" 27160819Ssimon#include "opto/cfgnode.hpp" 28160819Ssimon#include "opto/matcher.hpp" 29160819Ssimon#include "opto/mathexactnode.hpp" 30160819Ssimon#include "opto/multnode.hpp" 31160819Ssimon#include "opto/opcodes.hpp" 32160819Ssimon#include "opto/phaseX.hpp" 33160819Ssimon#include "opto/regmask.hpp" 34160819Ssimon#include "opto/type.hpp" 35160819Ssimon 36160819Ssimon//============================================================================= 37160819Ssimon//------------------------------MultiNode-------------------------------------- 38160819Ssimonconst RegMask &MultiNode::out_RegMask() const { 39160819Ssimon return RegMask::Empty; 40160819Ssimon} 41276864Sjkim 42276864SjkimNode *MultiNode::match( const ProjNode *proj, const Matcher *m ) { return proj->clone(); } 43160819Ssimon 44160819Ssimon//------------------------------proj_out--------------------------------------- 45215698Ssimon// Get a named projection 46215698SsimonProjNode* MultiNode::proj_out(uint which_proj) const { 47215698Ssimon assert(Opcode() != Op_If || which_proj == (uint)true || which_proj == (uint)false, "must be 1 or 0"); 48215698Ssimon assert(Opcode() != Op_If || outcnt() == 2, "bad if #1"); 49160819Ssimon for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { 50215698Ssimon Node *p = fast_out(i); 51160819Ssimon if (p->is_Proj()) { 52160819Ssimon ProjNode *proj = p->as_Proj(); 53276864Sjkim if (proj->_con == which_proj) { 54276864Sjkim assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); 55276864Sjkim return proj; 56160819Ssimon } 57276864Sjkim } else { 58276864Sjkim assert(p == this && this->is_Start(), "else must be proj"); 59276864Sjkim continue; 60276864Sjkim } 61276864Sjkim } 62276864Sjkim return NULL; 63215698Ssimon} 64276864Sjkim 65276864Sjkim//============================================================================= 66276864Sjkim//------------------------------ProjNode--------------------------------------- 67276864Sjkimuint ProjNode::hash() const { 68276864Sjkim // only one input 69215698Ssimon return (uintptr_t)in(TypeFunc::Control) + (_con << 1) + (_is_io_use ? 1 : 0); 70276864Sjkim} 71160819Ssimonuint ProjNode::cmp( const Node &n ) const { return _con == ((ProjNode&)n)._con && ((ProjNode&)n)._is_io_use == _is_io_use; } 72160819Ssimonuint ProjNode::size_of() const { return sizeof(ProjNode); } 73160819Ssimon 74160819Ssimon// Test if we propagate interesting control along this projection 75160819Ssimonbool ProjNode::is_CFG() const { 76160819Ssimon Node *def = in(0); 77160819Ssimon return (_con == TypeFunc::Control && def->is_CFG()); 78160819Ssimon} 79160819Ssimon 80160819Ssimonconst Type* ProjNode::proj_type(const Type* t) const { 81160819Ssimon if (t == Type::TOP) { 82160819Ssimon return Type::TOP; 83160819Ssimon } 84160819Ssimon if (t == Type::BOTTOM) { 85160819Ssimon return Type::BOTTOM; 86160819Ssimon } 87160819Ssimon t = t->is_tuple()->field_at(_con); 88160819Ssimon Node* n = in(0); 89160819Ssimon if ((_con == TypeFunc::Parms) && 90160819Ssimon n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method()) { 91160819Ssimon // The result of autoboxing is always non-null on normal path. 92160819Ssimon t = t->join_speculative(TypePtr::NOTNULL); 93160819Ssimon } 94160819Ssimon return t; 95160819Ssimon} 96160819Ssimon 97160819Ssimonconst Type *ProjNode::bottom_type() const { 98160819Ssimon if (in(0) == NULL) return Type::TOP; 99160819Ssimon return proj_type(in(0)->bottom_type()); 100160819Ssimon} 101160819Ssimon 102160819Ssimonconst TypePtr *ProjNode::adr_type() const { 103160819Ssimon if (bottom_type() == Type::MEMORY) { 104160819Ssimon // in(0) might be a narrow MemBar; otherwise we will report TypePtr::BOTTOM 105160819Ssimon Node* ctrl = in(0); 106160819Ssimon if (ctrl == NULL) return NULL; // node is dead 107160819Ssimon const TypePtr* adr_type = ctrl->adr_type(); 108160819Ssimon #ifdef ASSERT 109160819Ssimon if (!is_error_reported() && !Node::in_dump()) 110160819Ssimon assert(adr_type != NULL, "source must have adr_type"); 111160819Ssimon #endif 112160819Ssimon return adr_type; 113160819Ssimon } 114160819Ssimon assert(bottom_type()->base() != Type::Memory, "no other memories?"); 115160819Ssimon return NULL; 116160819Ssimon} 117160819Ssimon 118160819Ssimonbool ProjNode::pinned() const { return in(0)->pinned(); } 119160819Ssimon#ifndef PRODUCT 120160819Ssimonvoid ProjNode::dump_spec(outputStream *st) const { st->print("#%d",_con); if(_is_io_use) st->print(" (i_o_use)");} 121160819Ssimon#endif 122160819Ssimon 123160819Ssimon//----------------------------check_con---------------------------------------- 124160819Ssimonvoid ProjNode::check_con() const { 125160819Ssimon Node* n = in(0); 126160819Ssimon if (n == NULL) return; // should be assert, but NodeHash makes bogons 127160819Ssimon if (n->is_Mach()) return; // mach. projs. are not type-safe 128160819Ssimon if (n->is_Start()) return; // alas, starts can have mach. projs. also 129160819Ssimon if (_con == SCMemProjNode::SCMEMPROJCON ) return; 130160819Ssimon const Type* t = n->bottom_type(); 131160819Ssimon if (t == Type::TOP) return; // multi is dead 132160819Ssimon assert(_con < t->is_tuple()->cnt(), "ProjNode::_con must be in range"); 133160819Ssimon} 134160819Ssimon 135160819Ssimon//------------------------------Value------------------------------------------ 136306196Sjkimconst Type *ProjNode::Value( PhaseTransform *phase ) const { 137215698Ssimon if (in(0) == NULL) return Type::TOP; 138215698Ssimon return proj_type(phase->type(in(0))); 139215698Ssimon} 140215698Ssimon 141160819Ssimon//------------------------------out_RegMask------------------------------------ 142160819Ssimon// Pass the buck uphill 143160819Ssimonconst RegMask &ProjNode::out_RegMask() const { 144160819Ssimon return RegMask::Empty; 145160819Ssimon} 146160819Ssimon 147160819Ssimon//------------------------------ideal_reg-------------------------------------- 148160819Ssimonuint ProjNode::ideal_reg() const { 149160819Ssimon return bottom_type()->ideal_reg(); 150160819Ssimon} 151160819Ssimon 152160819Ssimon//-------------------------------is_uncommon_trap_proj---------------------------- 153160819Ssimon// Return true if proj is the form of "proj->[region->..]call_uct" 154160819Ssimonbool ProjNode::is_uncommon_trap_proj(Deoptimization::DeoptReason reason) { 155269686Sjkim int path_limit = 10; 156160819Ssimon Node* out = this; 157160819Ssimon for (int ct = 0; ct < path_limit; ct++) { 158160819Ssimon out = out->unique_ctrl_out(); 159160819Ssimon if (out == NULL) 160160819Ssimon return false; 161160819Ssimon if (out->is_CallStaticJava()) { 162160819Ssimon int req = out->as_CallStaticJava()->uncommon_trap_request(); 163160819Ssimon if (req != 0) { 164160819Ssimon Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); 165160819Ssimon if (trap_reason == reason || reason == Deoptimization::Reason_none) { 166160819Ssimon return true; 167160819Ssimon } 168160819Ssimon } 169276864Sjkim return false; // don't do further after call 170276864Sjkim } 171160819Ssimon if (out->Opcode() != Op_Region) 172160819Ssimon return false; 173160819Ssimon } 174160819Ssimon return false; 175160819Ssimon} 176160819Ssimon 177160819Ssimon//-------------------------------is_uncommon_trap_if_pattern------------------------- 178160819Ssimon// Return true for "if(test)-> proj -> ... 179160819Ssimon// | 180160819Ssimon// V 181160819Ssimon// other_proj->[region->..]call_uct" 182160819Ssimon// 183160819Ssimon// "must_reason_predicate" means the uct reason must be Reason_predicate 184160819Ssimonbool ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason) { 185160819Ssimon Node *in0 = in(0); 186160819Ssimon if (!in0->is_If()) return false; 187160819Ssimon // Variation of a dead If node. 188160819Ssimon if (in0->outcnt() < 2) return false; 189160819Ssimon IfNode* iff = in0->as_If(); 190160819Ssimon 191160819Ssimon // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate 192160819Ssimon if (reason != Deoptimization::Reason_none) { 193160819Ssimon if (iff->in(1)->Opcode() != Op_Conv2B || 194160819Ssimon iff->in(1)->in(1)->Opcode() != Op_Opaque1) { 195160819Ssimon return false; 196160819Ssimon } 197160819Ssimon } 198160819Ssimon 199160819Ssimon ProjNode* other_proj = iff->proj_out(1-_con); 200160819Ssimon if (other_proj == NULL) // Should never happen, but make Parfait happy. 201160819Ssimon return false; 202160819Ssimon if (other_proj->is_uncommon_trap_proj(reason)) { 203160819Ssimon assert(reason == Deoptimization::Reason_none || 204160819Ssimon Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list"); 205160819Ssimon return true; 206160819Ssimon } 207160819Ssimon return false; 208160819Ssimon} 209160819Ssimon