multnode.cpp revision 5776:de6a9e811145
1240616Sjimharris/* 2240616Sjimharris * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3240616Sjimharris * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4240616Sjimharris * 5240616Sjimharris * This code is free software; you can redistribute it and/or modify it 6240616Sjimharris * under the terms of the GNU General Public License version 2 only, as 7240616Sjimharris * published by the Free Software Foundation. 8240616Sjimharris * 9240616Sjimharris * This code is distributed in the hope that it will be useful, but WITHOUT 10240616Sjimharris * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11240616Sjimharris * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12240616Sjimharris * version 2 for more details (a copy is included in the LICENSE file that 13240616Sjimharris * accompanied this code). 14240616Sjimharris * 15240616Sjimharris * You should have received a copy of the GNU General Public License version 16240616Sjimharris * 2 along with this work; if not, write to the Free Software Foundation, 17240616Sjimharris * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18240616Sjimharris * 19240616Sjimharris * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20240616Sjimharris * or visit www.oracle.com if you need additional information or have any 21240616Sjimharris * questions. 22240616Sjimharris * 23240616Sjimharris */ 24240616Sjimharris 25240616Sjimharris#include "precompiled.hpp" 26240616Sjimharris#include "opto/callnode.hpp" 27240616Sjimharris#include "opto/cfgnode.hpp" 28240616Sjimharris#include "opto/matcher.hpp" 29240616Sjimharris#include "opto/mathexactnode.hpp" 30240616Sjimharris#include "opto/multnode.hpp" 31240616Sjimharris#include "opto/opcodes.hpp" 32240616Sjimharris#include "opto/phaseX.hpp" 33240616Sjimharris#include "opto/regmask.hpp" 34240616Sjimharris#include "opto/type.hpp" 35240616Sjimharris 36240616Sjimharris//============================================================================= 37240616Sjimharris//------------------------------MultiNode-------------------------------------- 38240616Sjimharrisconst RegMask &MultiNode::out_RegMask() const { 39240616Sjimharris return RegMask::Empty; 40248746Sjimharris} 41249421Sjimharris 42240616SjimharrisNode *MultiNode::match( const ProjNode *proj, const Matcher *m ) { return proj->clone(); } 43240616Sjimharris 44240616Sjimharris//------------------------------proj_out--------------------------------------- 45240616Sjimharris// Get a named projection 46240616SjimharrisProjNode* MultiNode::proj_out(uint which_proj) const { 47240616Sjimharris assert(Opcode() != Op_If || which_proj == (uint)true || which_proj == (uint)false, "must be 1 or 0"); 48240616Sjimharris assert(Opcode() != Op_If || outcnt() == 2, "bad if #1"); 49240616Sjimharris for( DUIterator_Fast imax, i = fast_outs(imax); i < imax; i++ ) { 50240616Sjimharris Node *p = fast_out(i); 51240616Sjimharris if (p->is_Proj()) { 52240616Sjimharris ProjNode *proj = p->as_Proj(); 53240616Sjimharris if (proj->_con == which_proj) { 54240616Sjimharris assert(Opcode() != Op_If || proj->Opcode() == (which_proj?Op_IfTrue:Op_IfFalse), "bad if #2"); 55240616Sjimharris return proj; 56240616Sjimharris } 57240616Sjimharris } else if (p->is_FlagsProj()) { 58240616Sjimharris FlagsProjNode *proj = p->as_FlagsProj(); 59240616Sjimharris if (proj->_con == which_proj) { 60240616Sjimharris return proj; 61240616Sjimharris } 62240616Sjimharris } else { 63240616Sjimharris assert(p == this && this->is_Start(), "else must be proj"); 64240616Sjimharris continue; 65240616Sjimharris } 66240616Sjimharris } 67240616Sjimharris return NULL; 68240616Sjimharris} 69240616Sjimharris 70240616Sjimharris//============================================================================= 71240616Sjimharris//------------------------------ProjNode--------------------------------------- 72240616Sjimharrisuint ProjNode::hash() const { 73240616Sjimharris // only one input 74240616Sjimharris return (uintptr_t)in(TypeFunc::Control) + (_con << 1) + (_is_io_use ? 1 : 0); 75240616Sjimharris} 76240616Sjimharrisuint ProjNode::cmp( const Node &n ) const { return _con == ((ProjNode&)n)._con && ((ProjNode&)n)._is_io_use == _is_io_use; } 77240616Sjimharrisuint ProjNode::size_of() const { return sizeof(ProjNode); } 78240616Sjimharris 79240616Sjimharris// Test if we propagate interesting control along this projection 80240616Sjimharrisbool ProjNode::is_CFG() const { 81240616Sjimharris Node *def = in(0); 82240616Sjimharris return (_con == TypeFunc::Control && def->is_CFG()); 83240616Sjimharris} 84240616Sjimharris 85240616Sjimharrisconst Type* ProjNode::proj_type(const Type* t) const { 86240616Sjimharris if (t == Type::TOP) { 87240616Sjimharris return Type::TOP; 88240616Sjimharris } 89240616Sjimharris if (t == Type::BOTTOM) { 90240616Sjimharris return Type::BOTTOM; 91240616Sjimharris } 92240616Sjimharris t = t->is_tuple()->field_at(_con); 93240616Sjimharris Node* n = in(0); 94240616Sjimharris if ((_con == TypeFunc::Parms) && 95240616Sjimharris n->is_CallStaticJava() && n->as_CallStaticJava()->is_boxing_method()) { 96240616Sjimharris // The result of autoboxing is always non-null on normal path. 97240616Sjimharris t = t->join(TypePtr::NOTNULL); 98240616Sjimharris } 99240616Sjimharris return t; 100240616Sjimharris} 101240616Sjimharris 102240616Sjimharrisconst Type *ProjNode::bottom_type() const { 103240616Sjimharris if (in(0) == NULL) return Type::TOP; 104240616Sjimharris return proj_type(in(0)->bottom_type()); 105240616Sjimharris} 106240616Sjimharris 107240616Sjimharrisconst TypePtr *ProjNode::adr_type() const { 108240616Sjimharris if (bottom_type() == Type::MEMORY) { 109240616Sjimharris // in(0) might be a narrow MemBar; otherwise we will report TypePtr::BOTTOM 110240616Sjimharris const TypePtr* adr_type = in(0)->adr_type(); 111240616Sjimharris #ifdef ASSERT 112240616Sjimharris if (!is_error_reported() && !Node::in_dump()) 113240616Sjimharris assert(adr_type != NULL, "source must have adr_type"); 114240616Sjimharris #endif 115240616Sjimharris return adr_type; 116240616Sjimharris } 117240616Sjimharris assert(bottom_type()->base() != Type::Memory, "no other memories?"); 118240616Sjimharris return NULL; 119240616Sjimharris} 120240616Sjimharris 121240616Sjimharrisbool ProjNode::pinned() const { return in(0)->pinned(); } 122240616Sjimharris#ifndef PRODUCT 123240616Sjimharrisvoid ProjNode::dump_spec(outputStream *st) const { st->print("#%d",_con); if(_is_io_use) st->print(" (i_o_use)");} 124240616Sjimharris#endif 125240616Sjimharris 126240616Sjimharris//----------------------------check_con---------------------------------------- 127240616Sjimharrisvoid ProjNode::check_con() const { 128240616Sjimharris Node* n = in(0); 129240616Sjimharris if (n == NULL) return; // should be assert, but NodeHash makes bogons 130240616Sjimharris if (n->is_Mach()) return; // mach. projs. are not type-safe 131240616Sjimharris if (n->is_Start()) return; // alas, starts can have mach. projs. also 132240616Sjimharris if (_con == SCMemProjNode::SCMEMPROJCON ) return; 133240616Sjimharris const Type* t = n->bottom_type(); 134240616Sjimharris if (t == Type::TOP) return; // multi is dead 135240616Sjimharris assert(_con < t->is_tuple()->cnt(), "ProjNode::_con must be in range"); 136240616Sjimharris} 137240616Sjimharris 138240616Sjimharris//------------------------------Value------------------------------------------ 139240616Sjimharrisconst Type *ProjNode::Value( PhaseTransform *phase ) const { 140240616Sjimharris if (in(0) == NULL) return Type::TOP; 141240616Sjimharris return proj_type(phase->type(in(0))); 142240616Sjimharris} 143240616Sjimharris 144240616Sjimharris//------------------------------out_RegMask------------------------------------ 145240616Sjimharris// Pass the buck uphill 146240616Sjimharrisconst RegMask &ProjNode::out_RegMask() const { 147240616Sjimharris return RegMask::Empty; 148240616Sjimharris} 149240616Sjimharris 150240616Sjimharris//------------------------------ideal_reg-------------------------------------- 151240616Sjimharrisuint ProjNode::ideal_reg() const { 152240616Sjimharris return bottom_type()->ideal_reg(); 153240616Sjimharris} 154240616Sjimharris 155240616Sjimharris//-------------------------------is_uncommon_trap_proj---------------------------- 156240616Sjimharris// Return true if proj is the form of "proj->[region->..]call_uct" 157240616Sjimharrisbool ProjNode::is_uncommon_trap_proj(Deoptimization::DeoptReason reason) { 158240616Sjimharris int path_limit = 10; 159240616Sjimharris Node* out = this; 160240616Sjimharris for (int ct = 0; ct < path_limit; ct++) { 161240616Sjimharris out = out->unique_ctrl_out(); 162240616Sjimharris if (out == NULL) 163240616Sjimharris return false; 164240616Sjimharris if (out->is_CallStaticJava()) { 165240616Sjimharris int req = out->as_CallStaticJava()->uncommon_trap_request(); 166240616Sjimharris if (req != 0) { 167240616Sjimharris Deoptimization::DeoptReason trap_reason = Deoptimization::trap_request_reason(req); 168240616Sjimharris if (trap_reason == reason || reason == Deoptimization::Reason_none) { 169240616Sjimharris return true; 170240616Sjimharris } 171240616Sjimharris } 172240616Sjimharris return false; // don't do further after call 173240616Sjimharris } 174240616Sjimharris if (out->Opcode() != Op_Region) 175240616Sjimharris return false; 176240616Sjimharris } 177240616Sjimharris return false; 178240616Sjimharris} 179240616Sjimharris 180240616Sjimharris//-------------------------------is_uncommon_trap_if_pattern------------------------- 181240616Sjimharris// Return true for "if(test)-> proj -> ... 182240616Sjimharris// | 183240616Sjimharris// V 184240616Sjimharris// other_proj->[region->..]call_uct" 185240616Sjimharris// 186240616Sjimharris// "must_reason_predicate" means the uct reason must be Reason_predicate 187240616Sjimharrisbool ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason) { 188240616Sjimharris Node *in0 = in(0); 189240616Sjimharris if (!in0->is_If()) return false; 190240616Sjimharris // Variation of a dead If node. 191240616Sjimharris if (in0->outcnt() < 2) return false; 192240616Sjimharris IfNode* iff = in0->as_If(); 193240616Sjimharris 194240616Sjimharris // we need "If(Conv2B(Opaque1(...)))" pattern for reason_predicate 195240616Sjimharris if (reason != Deoptimization::Reason_none) { 196240616Sjimharris if (iff->in(1)->Opcode() != Op_Conv2B || 197240616Sjimharris iff->in(1)->in(1)->Opcode() != Op_Opaque1) { 198240616Sjimharris return false; 199240616Sjimharris } 200240616Sjimharris } 201240616Sjimharris 202240616Sjimharris ProjNode* other_proj = iff->proj_out(1-_con)->as_Proj(); 203240616Sjimharris if (other_proj->is_uncommon_trap_proj(reason)) { 204240616Sjimharris assert(reason == Deoptimization::Reason_none || 205240616Sjimharris Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list"); 206240616Sjimharris return true; 207240616Sjimharris } 208240616Sjimharris return false; 209240616Sjimharris} 210240616Sjimharris