Skip to content

Commit 6df78c4

Browse files
eme64rwestrel
andcommitted
8371065: C2 SuperWord: VTransformLoopPhiNode::apply setting type leads to assert/wrong result
Co-authored-by: Roland Westrelin <roland@openjdk.org> Reviewed-by: qamai, chagedorn
1 parent 15dcbf0 commit 6df78c4

File tree

4 files changed

+283
-33
lines changed

4 files changed

+283
-33
lines changed

src/hotspot/share/opto/superwordVTransformBuilder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes() {
6464
const VPointer& mem_p = _vloop_analyzer.vpointers().vpointer(mem);
6565
vtn = new (_vtransform.arena()) VTransformMemopScalarNode(_vtransform, mem, mem_p);
6666
} else if (n->is_Phi()) {
67-
vtn = new (_vtransform.arena()) VTransformLoopPhiNode(_vtransform, n->as_Phi());
67+
vtn = new (_vtransform.arena()) VTransformPhiScalarNode(_vtransform, n->as_Phi());
6868
} else if (n->is_CountedLoop()) {
6969
vtn = new (_vtransform.arena()) VTransformCountedLoopNode(_vtransform, n->as_CountedLoop());
7070
} else if (n->is_CFG()) {

src/hotspot/share/opto/vtransform.cpp

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ void VTransformGraph::optimize(VTransform& vtransform) {
6262
// 1. Memory phi uses are not modeled, so they appear to have no use here, but must be kept alive.
6363
// 2. Similarly, some stores may not have their memory uses modeled, but need to be kept alive.
6464
// 3. Outer node with strong inputs: is a use after the loop that we must keep alive.
65-
!(vtn->isa_LoopPhi() != nullptr ||
65+
!(vtn->isa_PhiScalar() != nullptr ||
6666
vtn->is_load_or_store_in_loop() ||
6767
(vtn->isa_Outer() != nullptr && vtn->has_strong_in_edge()))) {
6868
vtn->mark_dead();
@@ -123,8 +123,10 @@ bool VTransformGraph::schedule() {
123123
// Skip dead nodes
124124
if (!use->is_alive()) { continue; }
125125

126-
// Skip LoopPhi backedge.
127-
if ((use->isa_LoopPhi() != nullptr || use->isa_CountedLoop() != nullptr) && use->in_req(2) == vtn) { continue; }
126+
// Skip backedges.
127+
if ((use->is_loop_head_phi() || use->isa_CountedLoop() != nullptr) && use->in_req(2) == vtn) {
128+
continue;
129+
}
128130

129131
if (post_visited.test(use->_idx)) { continue; }
130132
if (pre_visited.test(use->_idx)) {
@@ -205,7 +207,7 @@ void VTransformGraph::mark_vtnodes_in_loop(VectorSet& in_loop) const {
205207
for (int i = 0; i < _schedule.length(); i++) {
206208
VTransformNode* vtn = _schedule.at(i);
207209
// Is vtn a loop-phi?
208-
if (vtn->isa_LoopPhi() != nullptr ||
210+
if (vtn->is_loop_head_phi() ||
209211
vtn->is_load_or_store_in_loop()) {
210212
is_not_before_loop.set(vtn->_idx);
211213
continue;
@@ -232,8 +234,7 @@ void VTransformGraph::mark_vtnodes_in_loop(VectorSet& in_loop) const {
232234
for (uint i = 0; i < vtn->out_strong_edges(); i++) {
233235
VTransformNode* use = vtn->out_strong_edge(i);
234236
// Or is vtn a backedge or one of its transitive defs?
235-
if (in_loop.test(use->_idx) ||
236-
use->isa_LoopPhi() != nullptr) {
237+
if (in_loop.test(use->_idx) || use->is_loop_head_phi()) {
237238
in_loop.set(vtn->_idx);
238239
break;
239240
}
@@ -957,27 +958,22 @@ VTransformApplyResult VTransformDataScalarNode::apply(VTransformApplyState& appl
957958
return VTransformApplyResult::make_scalar(_node);
958959
}
959960

960-
VTransformApplyResult VTransformLoopPhiNode::apply(VTransformApplyState& apply_state) const {
961+
VTransformApplyResult VTransformPhiScalarNode::apply(VTransformApplyState& apply_state) const {
961962
PhaseIdealLoop* phase = apply_state.phase();
962963
Node* in0 = apply_state.transformed_node(in_req(0));
963964
Node* in1 = apply_state.transformed_node(in_req(1));
964965
phase->igvn().replace_input_of(_node, 0, in0);
965966
phase->igvn().replace_input_of(_node, 1, in1);
966967
// Note: the backedge is hooked up later.
967968

968-
// The Phi's inputs may have been modified, and the types changes,
969-
// e.g. from scalar to vector.
970-
const Type* t = in1->bottom_type();
971-
_node->as_Type()->set_type(t);
972-
phase->igvn().set_type(_node, t);
973-
974969
return VTransformApplyResult::make_scalar(_node);
975970
}
976971

977972
// Cleanup backedges. In the schedule, the backedges come after their phis. Hence,
978973
// we only have the transformed backedges after the phis are already transformed.
979974
// We hook the backedges into the phis now, during cleanup.
980-
void VTransformLoopPhiNode::apply_backedge(VTransformApplyState& apply_state) const {
975+
void VTransformPhiScalarNode::apply_backedge(VTransformApplyState& apply_state) const {
976+
assert(_node == apply_state.transformed_node(this), "sanity");
981977
PhaseIdealLoop* phase = apply_state.phase();
982978
if (_node->is_memory_phi()) {
983979
// Memory phi/backedge
@@ -1219,7 +1215,7 @@ bool VTransformReductionVectorNode::requires_strict_order() const {
12191215
// are performed inside the loop.
12201216
bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_out_of_loop_preconditions(VTransform& vtransform) {
12211217
// We have a phi with a single use.
1222-
VTransformLoopPhiNode* phi = in_req(1)->isa_LoopPhi();
1218+
VTransformPhiScalarNode* phi = in_req(1)->isa_PhiScalar();
12231219
if (phi == nullptr) {
12241220
return false;
12251221
}
@@ -1284,7 +1280,7 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
12841280
// All uses must be outside loop body, except for the phi.
12851281
for (uint i = 0; i < current_red->out_strong_edges(); i++) {
12861282
VTransformNode* use = current_red->out_strong_edge(i);
1287-
if (use->isa_LoopPhi() == nullptr &&
1283+
if (use->isa_PhiScalar() == nullptr &&
12881284
use->isa_Outer() == nullptr) {
12891285
// Should not be allowed by SuperWord::mark_reductions
12901286
assert(false, "reduction has use inside loop");
@@ -1339,16 +1335,28 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
13391335
VTransformNode* vtn_identity_vector = new (vtransform.arena()) VTransformReplicateNode(vtransform, vlen, bt);
13401336
vtn_identity_vector->init_req(1, vtn_identity);
13411337

1342-
// Turn the scalar phi into a vector phi.
1343-
VTransformLoopPhiNode* phi = in_req(1)->isa_LoopPhi();
1344-
VTransformNode* init = phi->in_req(1);
1345-
phi->set_req(1, vtn_identity_vector);
1338+
// Look at old scalar phi.
1339+
VTransformPhiScalarNode* phi_scalar = in_req(1)->isa_PhiScalar();
1340+
PhiNode* old_phi = phi_scalar->node();
1341+
VTransformNode* init = phi_scalar->in_req(1);
1342+
1343+
TRACE_OPTIMIZE(
1344+
tty->print(" phi_scalar ");
1345+
phi_scalar->print();
1346+
)
1347+
1348+
// Create new vector phi
1349+
const VTransformVectorNodeProperties properties = VTransformVectorNodeProperties::make_for_phi_vector(old_phi, vlen, bt);
1350+
VTransformPhiVectorNode* phi_vector = new (vtransform.arena()) VTransformPhiVectorNode(vtransform, 3, properties);
1351+
phi_vector->init_req(0, phi_scalar->in_req(0));
1352+
phi_vector->init_req(1, vtn_identity_vector);
1353+
// Note: backedge comes later
13461354

13471355
// Traverse down the chain of reductions, and replace them with vector_accumulators.
13481356
VTransformReductionVectorNode* first_red = this;
1349-
VTransformReductionVectorNode* last_red = phi->in_req(2)->isa_ReductionVector();
1357+
VTransformReductionVectorNode* last_red = phi_scalar->in_req(2)->isa_ReductionVector();
13501358
VTransformReductionVectorNode* current_red = first_red;
1351-
VTransformNode* current_vector_accumulator = phi;
1359+
VTransformNode* current_vector_accumulator = phi_vector;
13521360
while (true) {
13531361
VTransformNode* vector_input = current_red->in_req(2);
13541362
VTransformVectorNode* vector_accumulator = new (vtransform.arena()) VTransformElementWiseVectorNode(vtransform, 3, current_red->properties(), vopc);
@@ -1366,15 +1374,15 @@ bool VTransformReductionVectorNode::optimize_move_non_strict_order_reductions_ou
13661374
}
13671375

13681376
// Feed vector accumulator into the backedge.
1369-
phi->set_req(2, current_vector_accumulator);
1377+
phi_vector->set_req(2, current_vector_accumulator);
13701378

13711379
// Create post-loop reduction. last_red keeps all uses outside the loop.
13721380
last_red->set_req(1, init);
13731381
last_red->set_req(2, current_vector_accumulator);
13741382

13751383
TRACE_OPTIMIZE(
1376-
tty->print(" phi ");
1377-
phi->print();
1384+
tty->print(" phi_scalar ");
1385+
phi_scalar->print();
13781386
tty->print(" after loop ");
13791387
last_red->print();
13801388
)
@@ -1398,6 +1406,37 @@ VTransformApplyResult VTransformReductionVectorNode::apply(VTransformApplyState&
13981406
return VTransformApplyResult::make_vector(vn, vn->vect_type());
13991407
}
14001408

1409+
VTransformApplyResult VTransformPhiVectorNode::apply(VTransformApplyState& apply_state) const {
1410+
PhaseIdealLoop* phase = apply_state.phase();
1411+
Node* in0 = apply_state.transformed_node(in_req(0));
1412+
Node* in1 = apply_state.transformed_node(in_req(1));
1413+
1414+
// We create a new phi node, because the type is different to the scalar phi.
1415+
PhiNode* old_phi = approximate_origin()->as_Phi();
1416+
PhiNode* new_phi = old_phi->clone()->as_Phi();
1417+
1418+
phase->igvn().replace_input_of(new_phi, 0, in0);
1419+
phase->igvn().replace_input_of(new_phi, 1, in1);
1420+
// Note: the backedge is hooked up later.
1421+
1422+
// Give the new phi node the correct vector type.
1423+
const TypeVect* vt = TypeVect::make(element_basic_type(), vector_length());
1424+
new_phi->as_Type()->set_type(vt);
1425+
phase->igvn().set_type(new_phi, vt);
1426+
1427+
return VTransformApplyResult::make_vector(new_phi, vt);
1428+
}
1429+
1430+
// Cleanup backedges. In the schedule, the backedges come after their phis. Hence,
1431+
// we only have the transformed backedges after the phis are already transformed.
1432+
// We hook the backedges into the phis now, during cleanup.
1433+
void VTransformPhiVectorNode::apply_backedge(VTransformApplyState& apply_state) const {
1434+
PhaseIdealLoop* phase = apply_state.phase();
1435+
PhiNode* new_phi = apply_state.transformed_node(this)->as_Phi();
1436+
Node* in2 = apply_state.transformed_node(in_req(2));
1437+
phase->igvn().replace_input_of(new_phi, 2, in2);
1438+
}
1439+
14011440
float VTransformLoadVectorNode::cost(const VLoopAnalyzer& vloop_analyzer) const {
14021441
uint vlen = vector_length();
14031442
BasicType bt = element_basic_type();
@@ -1535,7 +1574,7 @@ void VTransformDataScalarNode::print_spec() const {
15351574
tty->print("node[%d %s]", _node->_idx, _node->Name());
15361575
}
15371576

1538-
void VTransformLoopPhiNode::print_spec() const {
1577+
void VTransformPhiScalarNode::print_spec() const {
15391578
tty->print("node[%d %s]", _node->_idx, _node->Name());
15401579
}
15411580

src/hotspot/share/opto/vtransform.hpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ class VTransform;
7979
class VTransformNode;
8080
class VTransformMemopScalarNode;
8181
class VTransformDataScalarNode;
82-
class VTransformLoopPhiNode;
82+
class VTransformPhiScalarNode;
8383
class VTransformCFGNode;
8484
class VTransformCountedLoopNode;
8585
class VTransformOuterNode;
@@ -88,6 +88,7 @@ class VTransformElementWiseVectorNode;
8888
class VTransformCmpVectorNode;
8989
class VTransformBoolVectorNode;
9090
class VTransformReductionVectorNode;
91+
class VTransformPhiVectorNode;
9192
class VTransformMemVectorNode;
9293
class VTransformLoadVectorNode;
9394
class VTransformStoreVectorNode;
@@ -539,21 +540,23 @@ class VTransformNode : public ArenaObj {
539540
}
540541

541542
virtual VTransformMemopScalarNode* isa_MemopScalar() { return nullptr; }
542-
virtual VTransformLoopPhiNode* isa_LoopPhi() { return nullptr; }
543+
virtual VTransformPhiScalarNode* isa_PhiScalar() { return nullptr; }
543544
virtual VTransformCountedLoopNode* isa_CountedLoop() { return nullptr; }
544545
virtual VTransformOuterNode* isa_Outer() { return nullptr; }
545546
virtual VTransformVectorNode* isa_Vector() { return nullptr; }
546547
virtual VTransformElementWiseVectorNode* isa_ElementWiseVector() { return nullptr; }
547548
virtual VTransformCmpVectorNode* isa_CmpVector() { return nullptr; }
548549
virtual VTransformBoolVectorNode* isa_BoolVector() { return nullptr; }
549550
virtual VTransformReductionVectorNode* isa_ReductionVector() { return nullptr; }
551+
virtual VTransformPhiVectorNode* isa_PhiVector() { return nullptr; }
550552
virtual VTransformMemVectorNode* isa_MemVector() { return nullptr; }
551553
virtual VTransformLoadVectorNode* isa_LoadVector() { return nullptr; }
552554
virtual VTransformStoreVectorNode* isa_StoreVector() { return nullptr; }
553555

554556
virtual bool is_load_in_loop() const { return false; }
555557
virtual bool is_load_or_store_in_loop() const { return false; }
556558
virtual const VPointer& vpointer() const { ShouldNotReachHere(); }
559+
virtual bool is_loop_head_phi() const { return false; }
557560

558561
virtual bool optimize(const VLoopAnalyzer& vloop_analyzer, VTransform& vtransform) { return false; }
559562

@@ -613,21 +616,24 @@ class VTransformDataScalarNode : public VTransformNode {
613616
};
614617

615618
// Identity transform for loop head phi nodes.
616-
class VTransformLoopPhiNode : public VTransformNode {
619+
class VTransformPhiScalarNode : public VTransformNode {
617620
private:
618621
PhiNode* _node;
619622
public:
620-
VTransformLoopPhiNode(VTransform& vtransform, PhiNode* n) :
623+
VTransformPhiScalarNode(VTransform& vtransform, PhiNode* n) :
621624
VTransformNode(vtransform, n->req()), _node(n)
622625
{
623626
assert(_node->in(0)->is_Loop(), "phi ctrl must be Loop: %s", _node->in(0)->Name());
624627
}
625628

626-
virtual VTransformLoopPhiNode* isa_LoopPhi() override { return this; }
629+
PhiNode* node() const { return _node; }
630+
631+
virtual VTransformPhiScalarNode* isa_PhiScalar() override { return this; }
632+
virtual bool is_loop_head_phi() const override { return in_req(0)->isa_CountedLoop() != nullptr; }
627633
virtual float cost(const VLoopAnalyzer& vloop_analyzer) const override { return 0; }
628634
virtual VTransformApplyResult apply(VTransformApplyState& apply_state) const override;
629635
virtual void apply_backedge(VTransformApplyState& apply_state) const override;
630-
NOT_PRODUCT(virtual const char* name() const override { return "LoopPhi"; };)
636+
NOT_PRODUCT(virtual const char* name() const override { return "PhiScalar"; };)
631637
NOT_PRODUCT(virtual void print_spec() const override;)
632638
};
633639

@@ -754,6 +760,10 @@ class VTransformVectorNodeProperties : public StackObj {
754760
return VTransformVectorNodeProperties(first, opc, vlen, bt);
755761
}
756762

763+
static VTransformVectorNodeProperties make_for_phi_vector(PhiNode* phi, int vlen, BasicType bt) {
764+
return VTransformVectorNodeProperties(phi, phi->Opcode(), vlen, bt);
765+
}
766+
757767
Node* approximate_origin() const { return _approximate_origin; }
758768
int scalar_opcode() const { return _scalar_opcode; }
759769
uint vector_length() const { return _vector_length; }
@@ -870,6 +880,18 @@ class VTransformReductionVectorNode : public VTransformVectorNode {
870880
bool optimize_move_non_strict_order_reductions_out_of_loop(const VLoopAnalyzer& vloop_analyzer, VTransform& vtransform);
871881
};
872882

883+
class VTransformPhiVectorNode : public VTransformVectorNode {
884+
public:
885+
VTransformPhiVectorNode(VTransform& vtransform, uint req, const VTransformVectorNodeProperties properties) :
886+
VTransformVectorNode(vtransform, req, properties) {}
887+
virtual VTransformPhiVectorNode* isa_PhiVector() override { return this; }
888+
virtual bool is_loop_head_phi() const override { return in_req(0)->isa_CountedLoop() != nullptr; }
889+
virtual float cost(const VLoopAnalyzer& vloop_analyzer) const override { return 0; }
890+
virtual VTransformApplyResult apply(VTransformApplyState& apply_state) const override;
891+
virtual void apply_backedge(VTransformApplyState& apply_state) const override;
892+
NOT_PRODUCT(virtual const char* name() const override { return "PhiVector"; };)
893+
};
894+
873895
class VTransformMemVectorNode : public VTransformVectorNode {
874896
private:
875897
const VPointer _vpointer; // with size of the vector

0 commit comments

Comments
 (0)