Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/parse2.cpp @ 6131:8f6ce6f1049b
7170463: C2 should recognize "obj.getClass() == A.class" code pattern
Summary: optimize this code pattern obj.getClass() == A.class.
Reviewed-by: jrose, kvn
Contributed-by: Krystal Mok <sajia@taobao.com>
author | kvn |
---|---|
date | Fri, 25 May 2012 07:53:11 -0700 |
parents | c124e2e7463e |
children | 70862d781d01 |
comparison
equal
deleted
inserted
replaced
6088:7089278210e2 | 6131:8f6ce6f1049b |
---|---|
1231 } | 1231 } |
1232 } | 1232 } |
1233 if (!have_con) // remaining adjustments need a con | 1233 if (!have_con) // remaining adjustments need a con |
1234 return; | 1234 return; |
1235 | 1235 |
1236 sharpen_type_after_if(btest, con, tcon, val, tval); | |
1237 } | |
1238 | |
1239 | |
1240 static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) { | |
1241 Node* ldk; | |
1242 if (n->is_DecodeN()) { | |
1243 if (n->in(1)->Opcode() != Op_LoadNKlass) { | |
1244 return NULL; | |
1245 } else { | |
1246 ldk = n->in(1); | |
1247 } | |
1248 } else if (n->Opcode() != Op_LoadKlass) { | |
1249 return NULL; | |
1250 } else { | |
1251 ldk = n; | |
1252 } | |
1253 assert(ldk != NULL && ldk->is_Load(), "should have found a LoadKlass or LoadNKlass node"); | |
1254 | |
1255 Node* adr = ldk->in(MemNode::Address); | |
1256 intptr_t off = 0; | |
1257 Node* obj = AddPNode::Ideal_base_and_offset(adr, gvn, off); | |
1258 if (obj == NULL || off != oopDesc::klass_offset_in_bytes()) // loading oopDesc::_klass? | |
1259 return NULL; | |
1260 const TypePtr* tp = gvn->type(obj)->is_ptr(); | |
1261 if (tp == NULL || !(tp->isa_instptr() || tp->isa_aryptr())) // is obj a Java object ptr? | |
1262 return NULL; | |
1263 | |
1264 return obj; | |
1265 } | |
1266 | |
1267 void Parse::sharpen_type_after_if(BoolTest::mask btest, | |
1268 Node* con, const Type* tcon, | |
1269 Node* val, const Type* tval) { | |
1270 // Look for opportunities to sharpen the type of a node | |
1271 // whose klass is compared with a constant klass. | |
1272 if (btest == BoolTest::eq && tcon->isa_klassptr()) { | |
1273 Node* obj = extract_obj_from_klass_load(&_gvn, val); | |
1274 const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type(); | |
1275 if (obj != NULL && (con_type->isa_instptr() || con_type->isa_aryptr())) { | |
1276 // Found: | |
1277 // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) | |
1278 // or the narrowOop equivalent. | |
1279 const Type* obj_type = _gvn.type(obj); | |
1280 const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr(); | |
1281 if (tboth != NULL && tboth != obj_type && tboth->higher_equal(obj_type)) { | |
1282 // obj has to be of the exact type Foo if the CmpP succeeds. | |
1283 assert(tboth->klass_is_exact(), "klass should be exact"); | |
1284 int obj_in_map = map()->find_edge(obj); | |
1285 JVMState* jvms = this->jvms(); | |
1286 if (obj_in_map >= 0 && | |
1287 (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { | |
1288 TypeNode* ccast = new (C, 2) CheckCastPPNode(control(), obj, tboth); | |
1289 const Type* tcc = ccast->as_Type()->type(); | |
1290 assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); | |
1291 // Delay transform() call to allow recovery of pre-cast value | |
1292 // at the control merge. | |
1293 _gvn.set_type_bottom(ccast); | |
1294 record_for_igvn(ccast); | |
1295 // Here's the payoff. | |
1296 replace_in_map(obj, ccast); | |
1297 } | |
1298 } | |
1299 } | |
1300 } | |
1236 | 1301 |
1237 int val_in_map = map()->find_edge(val); | 1302 int val_in_map = map()->find_edge(val); |
1238 if (val_in_map < 0) return; // replace_in_map would be useless | 1303 if (val_in_map < 0) return; // replace_in_map would be useless |
1239 { | 1304 { |
1240 JVMState* jvms = this->jvms(); | 1305 JVMState* jvms = this->jvms(); |
1263 const TypeF* tf = tcon->isa_float_constant(); | 1328 const TypeF* tf = tcon->isa_float_constant(); |
1264 const TypeD* td = tcon->isa_double_constant(); | 1329 const TypeD* td = tcon->isa_double_constant(); |
1265 // Exclude tests vs float/double 0 as these could be | 1330 // Exclude tests vs float/double 0 as these could be |
1266 // either +0 or -0. Just because you are equal to +0 | 1331 // either +0 or -0. Just because you are equal to +0 |
1267 // doesn't mean you ARE +0! | 1332 // doesn't mean you ARE +0! |
1333 // Note, following code also replaces Long and Oop values. | |
1268 if ((!tf || tf->_f != 0.0) && | 1334 if ((!tf || tf->_f != 0.0) && |
1269 (!td || td->_d != 0.0)) | 1335 (!td || td->_d != 0.0)) |
1270 cast = con; // Replace non-constant val by con. | 1336 cast = con; // Replace non-constant val by con. |
1271 } | 1337 } |
1272 } | 1338 } |