--- a/hotspot/src/share/vm/opto/loopnode.hpp Fri Oct 09 15:00:17 2015 +0200
+++ b/hotspot/src/share/vm/opto/loopnode.hpp Fri Oct 09 12:17:58 2015 -0700
@@ -38,6 +38,7 @@
class LoopNode;
class Node;
class PhaseIdealLoop;
+class CountedLoopReserveKit;
class VectorSet;
class Invariance;
struct small_cache;
@@ -529,6 +530,8 @@
class PhaseIdealLoop : public PhaseTransform {
friend class IdealLoopTree;
friend class SuperWord;
+ friend class CountedLoopReserveKit;
+
// Pre-computed def-use info
PhaseIterGVN &_igvn;
@@ -965,6 +968,16 @@
ProjNode* create_slow_version_of_loop(IdealLoopTree *loop,
Node_List &old_new);
+ // Clone a loop and return the clone head (clone_loop_head).
+ // Added nodes include int(1), int(0) - disconnected, If, IfTrue, IfFalse,
+ // This routine was created for usage in CountedLoopReserveKit.
+ //
+ // int(1) -> If -> IfTrue -> original_loop_head
+ // |
+ // V
+ // IfFalse -> clone_loop_head (returned by function pointer)
+ //
+ LoopNode* create_reserve_version_of_loop(IdealLoopTree *loop, CountedLoopReserveKit* lk);
// Clone loop with an invariant test (that does not exit) and
// insert a clone of the test that selects which version to
// execute.
@@ -1117,6 +1130,68 @@
#endif
};
+// This kit may be used for making of a reserved copy of a loop before this loop
+// goes under non-reversible changes.
+//
+// Function create_reserve() creates a reserved copy (clone) of the loop.
+// The reserved copy is created by calling
+// PhaseIdealLoop::create_reserve_version_of_loop - see there how
+// the original and reserved loops are connected in the outer graph.
+// If create_reserve succeeded, it returns 'true' and _has_reserved is set to 'true'.
+//
+// By default the reserved copy (clone) of the loop is created as dead code - it is
+// dominated in the outer loop by this node chain:
+// intcon(1)->If->IfFalse->reserved_copy.
+// The original loop is dominated by the the same node chain but IfTrue projection:
+// intcon(1)->If->IfTrue->original_loop.
+//
+// In this implementation of CountedLoopReserveKit the ctor includes create_reserve()
+// and the dtor, checks _use_new value.
+// If _use_new == false, it "switches" control to reserved copy of the loop
+// by simple replacing of node intcon(1) with node intcon(0).
+//
+// Here is a proposed example of usage (see also SuperWord::output in superword.cpp).
+//
+// void CountedLoopReserveKit_example()
+// {
+// CountedLoopReserveKit lrk((phase, lpt, DoReserveCopy = true); // create local object
+// if (DoReserveCopy && !lrk.has_reserved()) {
+// return; //failed to create reserved loop copy
+// }
+// ...
+// //something is wrong, switch to original loop
+/// if(something_is_wrong) return; // ~CountedLoopReserveKit makes the switch
+// ...
+// //everything worked ok, return with the newly modified loop
+// lrk.use_new();
+// return; // ~CountedLoopReserveKit does nothing once use_new() was called
+// }
+//
+// Keep in mind, that by default if create_reserve() is not followed by use_new()
+// the dtor will "switch to the original" loop.
+// NOTE. You you modify outside of the original loop this class is no help.
+//
+class CountedLoopReserveKit {
+ private:
+ PhaseIdealLoop* _phase;
+ IdealLoopTree* _lpt;
+ LoopNode* _lp;
+ IfNode* _iff;
+ LoopNode* _lp_reserved;
+ bool _has_reserved;
+ bool _use_new;
+ const bool _active; //may be set to false in ctor, then the object is dummy
+
+ public:
+ CountedLoopReserveKit(PhaseIdealLoop* phase, IdealLoopTree *loop, bool active);
+ ~CountedLoopReserveKit();
+ void use_new() {_use_new = true;}
+ void set_iff(IfNode* x) {_iff = x;}
+ bool has_reserved() const { return _active && _has_reserved;}
+ private:
+ bool create_reserve();
+};// class CountedLoopReserveKit
+
inline Node* IdealLoopTree::tail() {
// Handle lazy update of _tail field
Node *n = _tail;