While I converted other iterators requiring special BREAK_FROM_XYZ
a few years ago FOR_EACH_IMM_USE_STMT is remaining.  I've pondered
a bit but cannot arrive at a "nice" solution here with just one
iterator as the macros happen to use.  For reference, the macro use is

  imm_use_iterator iter;
  gimple *use_stmt;
  FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
    {
      use_operand_p use_p;
      FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
        ;
    }

which expands to (w/o macros)

   imm_use_iterator iter; 
   for (gimple *use_stmt = first_imm_use_stmt (&iter, name);
        !end_imm_use_stmt_p (&iter);
        use_stmt = nest_imm_use_stmt (&iter))
     for (use_operand_p use_p = first_imm_use_on_stmt (&iter);
          !end_imm_use_on_stmt_p (&iter);
          use_p = next_imm_use_on_stmt (&iter))
       ;

and my foolish C++ attempt results in

     for (imm_use_stmt_iter it = SSAVAR; !it.end_p (); ++it)
       for (imm_use_stmt_iter::use_on_stmt it2 = it; !it2.end_p (); ++it2)
         ;

with *it providing the gimple * USE_STMT and *it2 the use_operand_p.
The complication here is to map the two-level iteration to "the C++ way".
Are there any STL examples mimicing this?  Of course with C++11 we could
do

  for (imm_use_stmt_iter it = SSAVAR; !it.end_p (); ++it)
    for (auto it2 = it.first_use_on_stmt (); !it2.end_p (); ++it2)
      ;

but that's not much nicer either.  Doing away with operator++ might
work, doing it.next_stmt () / it.next_use () and end_stmt () / end_use ()
but there's no (type) safety at using the wrong one in the wrong nest.

The FOR_EACH_IMM_USE_STMT iterator is also quite special in that you
can have at most one (safely) on the same chain and that it does
work not on the order of the number of uses but on the order
of the number of uses times the number of operands in the used stmts
(so we should maybe rather get rid of it...  for which Micha has
patches as usual).

For the fast imm use iterations and also the SSA operand iterators
it's easy to make iterator classes which uses look nice enough.

Richard.


Index: gcc/ssa-iterators.h
===================================================================
--- gcc/ssa-iterators.h (revision 277566)
+++ gcc/ssa-iterators.h (working copy)
@@ -1007,4 +1007,62 @@ delink_stmt_imm_use (gimple *stmt)
        delink_imm_use (use_p);
 }
 
+/* Use this iterator to visit each stmt which has a use of SSAVAR.
+     for (imm_use_stmt_iter it = SSAVAR; !it.end_p (); ++it)
+       for (imm_use_stmt_iter::use_on_stmt it2 = it; !it2.end_p (); ++it2)
+         ;
+
+   The macros above expand to the following and require the special
+   BREAK/RETURN_FROM_IMM_USE_STMT for breaking/returning.
+
+   imm_use_iterator iter;
+   for (gimple *use_stmt = first_imm_use_stmt (&iter, name);
+        !end_imm_use_stmt_p (&iter);
+       use_stmt = nest_imm_use_stmt (&iter))
+     for (use_operand_p use_p = first_imm_use_on_stmt (&iter);
+          !end_imm_use_on_stmt_p (&iter);
+         use_p = next_imm_use_on_stmt (&iter))
+       ;
+ */
+
+
+class imm_use_stmt_iter
+{
+public:
+  imm_use_stmt_iter (tree name)
+    {
+      m_stmt = first_imm_use_stmt (&m_iter, name);
+    }
+
+  ~imm_use_stmt_iter ()
+    {
+      delink_imm_use (&(m_iter.iter_node));
+    }
+
+  gimple *operator* () const { return m_stmt; }
+  imm_use_stmt_iter& operator++() { next_imm_use_stmt (&m_iter); return *this; 
}
+  bool end_p() { return m_iter.imm_use == m_iter.end_p; }
+
+class use_on_stmt
+{
+public:
+    use_on_stmt (imm_use_stmt_iter &it) : m_iter (it.m_iter)
+      {
+       m_use_p = first_imm_use_on_stmt (&m_iter);
+      }
+
+    use_operand_p operator*() { return m_use_p; }
+    use_on_stmt& operator++() { next_imm_use_on_stmt (&m_iter); return *this; }
+    bool end_p() { return m_iter.imm_use == &m_iter.iter_node; }
+
+private:
+    imm_use_iterator &m_iter;
+    use_operand_p m_use_p;
+};
+
+private:
+  imm_use_iterator m_iter;
+  gimple *m_stmt;
+};
+
 #endif /* GCC_TREE_SSA_ITERATORS_H */
Index: gcc/tree-ssa-ccp.c
===================================================================
--- gcc/tree-ssa-ccp.c  (revision 277566)
+++ gcc/tree-ssa-ccp.c  (working copy)
@@ -2931,8 +2931,9 @@ optimize_atomic_bit_test_and (gimple_stm
 
   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_lhs))
     use_bool = false;
-  FOR_EACH_IMM_USE_STMT (g, iter, use_lhs)
+  for (imm_use_stmt_iter it = use_lhs; !it.end_p (); ++it)
     {
+      g = *it;
       enum tree_code code = ERROR_MARK;
       tree op0 = NULL_TREE, op1 = NULL_TREE;
       if (is_gimple_debug (g))
@@ -2969,16 +2970,15 @@ optimize_atomic_bit_test_and (gimple_stm
          && op0 == use_lhs
          && integer_zerop (op1))
        {
-         use_operand_p use_p;
          int n = 0;
-         FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+         for (imm_use_stmt_iter::use_on_stmt it2 = it; !it2.end_p (); ++it2)
            n++;
          if (n == 1)
            continue;
        }
 
       use_bool = false;
-      BREAK_FROM_IMM_USE_STMT (iter);
+      break;
     }
 
   tree new_lhs = make_ssa_name (TREE_TYPE (lhs));

Reply via email to