hotspot/src/share/vm/opto/loopnode.hpp
changeset 33166 81352250770f
parent 33067 0cabc639c87b
child 33469 30f4811eded0
--- 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;