Skip to content

Commit 83a91bf

Browse files
author
Vladimir Ivanov
committed
8253734: C2: Optimize Move nodes
Reviewed-by: thartmann, neliasso, kvn
1 parent 6666dcb commit 83a91bf

File tree

5 files changed

+132
-15
lines changed

5 files changed

+132
-15
lines changed

src/hotspot/share/opto/memnode.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,59 @@ Node* LoadNode::convert_to_signed_load(PhaseGVN& gvn) {
12681268
is_unaligned_access(), is_mismatched_access());
12691269
}
12701270

1271+
bool LoadNode::has_reinterpret_variant(const Type* rt) {
1272+
BasicType bt = rt->basic_type();
1273+
switch (Opcode()) {
1274+
case Op_LoadI: return (bt == T_FLOAT);
1275+
case Op_LoadL: return (bt == T_DOUBLE);
1276+
case Op_LoadF: return (bt == T_INT);
1277+
case Op_LoadD: return (bt == T_LONG);
1278+
1279+
default: return false;
1280+
}
1281+
}
1282+
1283+
Node* LoadNode::convert_to_reinterpret_load(PhaseGVN& gvn, const Type* rt) {
1284+
BasicType bt = rt->basic_type();
1285+
assert(has_reinterpret_variant(rt), "no reinterpret variant: %s %s", Name(), type2name(bt));
1286+
bool is_mismatched = is_mismatched_access();
1287+
const TypeRawPtr* raw_type = gvn.type(in(MemNode::Memory))->isa_rawptr();
1288+
if (raw_type == NULL) {
1289+
is_mismatched = true; // conservatively match all non-raw accesses as mismatched
1290+
}
1291+
return LoadNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address),
1292+
raw_adr_type(), rt, bt, _mo, _control_dependency,
1293+
is_unaligned_access(), is_mismatched);
1294+
}
1295+
1296+
bool StoreNode::has_reinterpret_variant(const Type* vt) {
1297+
BasicType bt = vt->basic_type();
1298+
switch (Opcode()) {
1299+
case Op_StoreI: return (bt == T_FLOAT);
1300+
case Op_StoreL: return (bt == T_DOUBLE);
1301+
case Op_StoreF: return (bt == T_INT);
1302+
case Op_StoreD: return (bt == T_LONG);
1303+
1304+
default: return false;
1305+
}
1306+
}
1307+
1308+
Node* StoreNode::convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Type* vt) {
1309+
BasicType bt = vt->basic_type();
1310+
assert(has_reinterpret_variant(vt), "no reinterpret variant: %s %s", Name(), type2name(bt));
1311+
StoreNode* st = StoreNode::make(gvn, in(MemNode::Control), in(MemNode::Memory), in(MemNode::Address), raw_adr_type(), val, bt, _mo);
1312+
1313+
bool is_mismatched = is_mismatched_access();
1314+
const TypeRawPtr* raw_type = gvn.type(in(MemNode::Memory))->isa_rawptr();
1315+
if (raw_type == NULL) {
1316+
is_mismatched = true; // conservatively match all non-raw accesses as mismatched
1317+
}
1318+
if (is_mismatched) {
1319+
st->set_mismatched_access();
1320+
}
1321+
return st;
1322+
}
1323+
12711324
// We're loading from an object which has autobox behaviour.
12721325
// If this object is result of a valueOf call we'll have a phi
12731326
// merging a newly allocated object and a load from the cache.
@@ -2548,6 +2601,7 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
25482601

25492602
Node* mem = in(MemNode::Memory);
25502603
Node* address = in(MemNode::Address);
2604+
Node* value = in(MemNode::ValueIn);
25512605
// Back-to-back stores to same address? Fold em up. Generally
25522606
// unsafe if I have intervening uses... Also disallowed for StoreCM
25532607
// since they must follow each StoreP operation. Redundant StoreCMs
@@ -2611,6 +2665,19 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
26112665
}
26122666
}
26132667

2668+
// Fold reinterpret cast into memory operation:
2669+
// StoreX mem (MoveY2X v) => StoreY mem v
2670+
if (value->is_Move()) {
2671+
const Type* vt = value->in(1)->bottom_type();
2672+
if (has_reinterpret_variant(vt)) {
2673+
if (phase->C->post_loop_opts_phase()) {
2674+
return convert_to_reinterpret_store(*phase, value->in(1), vt);
2675+
} else {
2676+
phase->C->record_for_post_loop_opts_igvn(this); // attempt the transformation once loop opts are over
2677+
}
2678+
}
2679+
}
2680+
26142681
return NULL; // No further progress
26152682
}
26162683

src/hotspot/share/opto/memnode.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,9 @@ class LoadNode : public MemNode {
282282
Node* convert_to_unsigned_load(PhaseGVN& gvn);
283283
Node* convert_to_signed_load(PhaseGVN& gvn);
284284

285+
bool has_reinterpret_variant(const Type* rt);
286+
Node* convert_to_reinterpret_load(PhaseGVN& gvn, const Type* rt);
287+
285288
void pin() { _control_dependency = Pinned; }
286289
bool has_unknown_control_dependency() const { return _control_dependency == UnknownControl; }
287290

@@ -634,6 +637,9 @@ class StoreNode : public MemNode {
634637
// have all possible loads of the value stored been optimized away?
635638
bool value_never_loaded(PhaseTransform *phase) const;
636639

640+
bool has_reinterpret_variant(const Type* vt);
641+
Node* convert_to_reinterpret_store(PhaseGVN& gvn, Node* val, const Type* vt);
642+
637643
MemBarNode* trailing_membar() const;
638644
};
639645

src/hotspot/share/opto/movenode.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,36 @@ Node *CMoveDNode::Ideal(PhaseGVN *phase, bool can_reshape) {
352352
return abs;
353353
}
354354

355+
//------------------------------MoveNode------------------------------------------
356+
357+
Node* MoveNode::Ideal(PhaseGVN* phase, bool can_reshape) {
358+
if (can_reshape) {
359+
// Fold reinterpret cast into memory operation:
360+
// MoveX2Y (LoadX mem) => LoadY mem
361+
LoadNode* ld = in(1)->isa_Load();
362+
if (ld != NULL && (ld->outcnt() == 1)) { // replace only
363+
const Type* rt = bottom_type();
364+
if (ld->has_reinterpret_variant(rt)) {
365+
if (phase->C->post_loop_opts_phase()) {
366+
return ld->convert_to_reinterpret_load(*phase, rt);
367+
} else {
368+
phase->C->record_for_post_loop_opts_igvn(this); // attempt the transformation once loop opts are over
369+
}
370+
}
371+
}
372+
}
373+
return NULL;
374+
}
375+
376+
Node* MoveNode::Identity(PhaseGVN* phase) {
377+
if (in(1)->is_Move()) {
378+
// Back-to-back moves: MoveX2Y (MoveY2X v) => v
379+
assert(bottom_type() == in(1)->in(1)->bottom_type(), "sanity");
380+
return in(1)->in(1);
381+
}
382+
return this;
383+
}
384+
355385
//------------------------------Value------------------------------------------
356386
const Type* MoveL2DNode::Value(PhaseGVN* phase) const {
357387
const Type *t = phase->type( in(1) );

src/hotspot/share/opto/movenode.hpp

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,41 +98,52 @@ class CMoveNNode : public CMoveNode {
9898
};
9999

100100
//
101-
class MoveI2FNode : public Node {
101+
class MoveNode : public Node {
102+
protected:
103+
MoveNode(Node* value) : Node(NULL, value) {
104+
init_class_id(Class_Move);
105+
}
106+
107+
public:
108+
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
109+
virtual Node* Identity(PhaseGVN* phase);
110+
};
111+
112+
class MoveI2FNode : public MoveNode {
102113
public:
103-
MoveI2FNode( Node *value ) : Node(0,value) {}
114+
MoveI2FNode(Node* value) : MoveNode(value) {}
104115
virtual int Opcode() const;
105-
virtual const Type *bottom_type() const { return Type::FLOAT; }
116+
virtual const Type* bottom_type() const { return Type::FLOAT; }
106117
virtual uint ideal_reg() const { return Op_RegF; }
107118
virtual const Type* Value(PhaseGVN* phase) const;
108119
virtual Node* Identity(PhaseGVN* phase);
109120
};
110121

111-
class MoveL2DNode : public Node {
122+
class MoveL2DNode : public MoveNode {
112123
public:
113-
MoveL2DNode( Node *value ) : Node(0,value) {}
124+
MoveL2DNode(Node* value) : MoveNode(value) {}
114125
virtual int Opcode() const;
115-
virtual const Type *bottom_type() const { return Type::DOUBLE; }
126+
virtual const Type* bottom_type() const { return Type::DOUBLE; }
116127
virtual uint ideal_reg() const { return Op_RegD; }
117128
virtual const Type* Value(PhaseGVN* phase) const;
118129
virtual Node* Identity(PhaseGVN* phase);
119130
};
120131

121-
class MoveF2INode : public Node {
132+
class MoveF2INode : public MoveNode {
122133
public:
123-
MoveF2INode( Node *value ) : Node(0,value) {}
134+
MoveF2INode(Node* value) : MoveNode(value) {}
124135
virtual int Opcode() const;
125-
virtual const Type *bottom_type() const { return TypeInt::INT; }
136+
virtual const Type* bottom_type() const { return TypeInt::INT; }
126137
virtual uint ideal_reg() const { return Op_RegI; }
127138
virtual const Type* Value(PhaseGVN* phase) const;
128139
virtual Node* Identity(PhaseGVN* phase);
129140
};
130141

131-
class MoveD2LNode : public Node {
142+
class MoveD2LNode : public MoveNode {
132143
public:
133-
MoveD2LNode( Node *value ) : Node(0,value) {}
144+
MoveD2LNode(Node* value) : MoveNode(value) {}
134145
virtual int Opcode() const;
135-
virtual const Type *bottom_type() const { return TypeLong::LONG; }
146+
virtual const Type* bottom_type() const { return TypeLong::LONG; }
136147
virtual uint ideal_reg() const { return Op_RegL; }
137148
virtual const Type* Value(PhaseGVN* phase) const;
138149
virtual Node* Identity(PhaseGVN* phase);

src/hotspot/share/opto/node.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ class MemBarNode;
112112
class MemBarStoreStoreNode;
113113
class MemNode;
114114
class MergeMemNode;
115+
class MoveNode;
115116
class MulNode;
116117
class MultiNode;
117118
class MultiBranchNode;
@@ -721,10 +722,11 @@ class Node {
721722
DEFINE_CLASS_ID(Vector, Node, 13)
722723
DEFINE_CLASS_ID(VectorMaskCmp, Vector, 0)
723724
DEFINE_CLASS_ID(ClearArray, Node, 14)
724-
DEFINE_CLASS_ID(Halt, Node, 15)
725-
DEFINE_CLASS_ID(Opaque1, Node, 16)
725+
DEFINE_CLASS_ID(Halt, Node, 15)
726+
DEFINE_CLASS_ID(Opaque1, Node, 16)
727+
DEFINE_CLASS_ID(Move, Node, 17)
726728

727-
_max_classes = ClassMask_Opaque1
729+
_max_classes = ClassMask_Move
728730
};
729731
#undef DEFINE_CLASS_ID
730732

@@ -870,6 +872,7 @@ class Node {
870872
DEFINE_CLASS_QUERY(MemBar)
871873
DEFINE_CLASS_QUERY(MemBarStoreStore)
872874
DEFINE_CLASS_QUERY(MergeMem)
875+
DEFINE_CLASS_QUERY(Move)
873876
DEFINE_CLASS_QUERY(Mul)
874877
DEFINE_CLASS_QUERY(Multi)
875878
DEFINE_CLASS_QUERY(MultiBranch)

0 commit comments

Comments
 (0)