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));