@@ -357,19 +357,38 @@ Node* PhaseMacroExpand::make_arraycopy_load(ArrayCopyNode* ac, intptr_t offset,
357
357
if (ac->modifies (offset, offset, &_igvn, true )) {
358
358
assert (ac->in (ArrayCopyNode::Dest) == alloc->result_cast (), " arraycopy destination should be allocation's result" );
359
359
uint shift = exact_log2 (type2aelembytes (bt));
360
- Node* diff = _igvn.transform (new SubINode (ac->in (ArrayCopyNode::SrcPos), ac->in (ArrayCopyNode::DestPos)));
360
+ Node* src_pos = ac->in (ArrayCopyNode::SrcPos);
361
+ Node* dest_pos = ac->in (ArrayCopyNode::DestPos);
362
+ const TypeInt* src_pos_t = _igvn.type (src_pos)->is_int ();
363
+ const TypeInt* dest_pos_t = _igvn.type (dest_pos)->is_int ();
364
+
365
+ Node* adr = NULL ;
366
+ const TypePtr* adr_type = NULL ;
367
+ if (src_pos_t ->is_con () && dest_pos_t ->is_con ()) {
368
+ intptr_t off = ((src_pos_t ->get_con () - dest_pos_t ->get_con ()) << shift) + offset;
369
+ Node* base = ac->in (ArrayCopyNode::Src);
370
+ adr = _igvn.transform (new AddPNode (base, base, MakeConX (off)));
371
+ adr_type = _igvn.type (base)->is_ptr ()->add_offset (off);
372
+ if (ac->in (ArrayCopyNode::Src) == ac->in (ArrayCopyNode::Dest)) {
373
+ // Don't emit a new load from src if src == dst but try to get the value from memory instead
374
+ return value_from_mem (ac->in (TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr (), alloc);
375
+ }
376
+ } else {
377
+ Node* diff = _igvn.transform (new SubINode (ac->in (ArrayCopyNode::SrcPos), ac->in (ArrayCopyNode::DestPos)));
361
378
#ifdef _LP64
362
- diff = _igvn.transform (new ConvI2LNode (diff));
379
+ diff = _igvn.transform (new ConvI2LNode (diff));
363
380
#endif
364
- diff = _igvn.transform (new LShiftXNode (diff, intcon (shift)));
365
-
366
- Node* off = _igvn.transform (new AddXNode (MakeConX (offset), diff));
367
- Node* base = ac->in (ArrayCopyNode::Src);
368
- Node* adr = _igvn.transform (new AddPNode (base, base, off));
369
- const TypePtr* adr_type = _igvn.type (base)->is_ptr ()->add_offset (offset);
370
- if (ac->in (ArrayCopyNode::Src) == ac->in (ArrayCopyNode::Dest)) {
371
- // Don't emit a new load from src if src == dst but try to get the value from memory instead
372
- return value_from_mem (ac->in (TypeFunc::Memory), ctl, ft, ftype, adr_type->isa_oopptr (), alloc);
381
+ diff = _igvn.transform (new LShiftXNode (diff, intcon (shift)));
382
+
383
+ Node* off = _igvn.transform (new AddXNode (MakeConX (offset), diff));
384
+ Node* base = ac->in (ArrayCopyNode::Src);
385
+ adr = _igvn.transform (new AddPNode (base, base, off));
386
+ adr_type = _igvn.type (base)->is_ptr ()->add_offset (Type::OffsetBot);
387
+ if (ac->in (ArrayCopyNode::Src) == ac->in (ArrayCopyNode::Dest)) {
388
+ // Non constant offset in the array: we can't statically
389
+ // determine the value
390
+ return NULL ;
391
+ }
373
392
}
374
393
res = LoadNode::make (_igvn, ctl, mem, adr, adr_type, type, bt, MemNode::unordered, LoadNode::UnknownControl);
375
394
}
0 commit comments