[llvm-dev] code to sort otherwise-unsortable "ilist"s, e.g. symbol tables

Abe Skolnik via llvm-dev llvm-dev at lists.llvm.org
Wed Aug 17 13:25:54 PDT 2016


Dear all,

The below has been tested quite thoroughly by now, including performance-testing by the way of 
using a modified compiler that triggers the below while compiling at least an old part of LLVM 
["Function.cpp"] and sorting a symbol table with >7000 global variables.

Unfortunately, the optimization I have been working on for which I _thought_ I needed the 
ability to sort a symbol table is showing poor performance numbers [from the compiled code, not 
the compiler itself], so I think I probably won`t submit that, at least not in its present form 
-- maybe in a much-more-limited form that doesn`t need the sorting.  However, I thought this 
sorting code might be useful to somebody else, so here it is for feedback.

Maybe somebody wants to add the needed glue code so e.g. "my_ilist.sort()" will call the below 
rather than invoking the relevant ancestor-class "sort()" and crashing?  If so, then ditto for 
e.g. "my_ilist.sort(my_comparator)", please.

Regards,

Abe






===== snippet from altered "llvm/include/llvm/ADT/ilist.h" =====

===== context within "ilist.h": the 2nd "public:" section of "template<typename NodeTy, 
typename Traits=ilist_traits<NodeTy> > class iplist : public Traits" =====



   template <class Compare>
   void sort_without_temporary_list(Compare comp) {
     // The list is empty, vacuously sorted.
     if (empty())
       return;
     // The list has a single element, vacuously sorted.
     if (std::next(begin()) == end())
       return;

     iterator            last_sorted{begin()};
     iterator just_after_last_sorted{std::next(last_sorted)};
     while (end() != just_after_last_sorted) {

       while ( (end() != just_after_last_sorted) && ! comp(*just_after_last_sorted, 
*last_sorted) ) {
         // advance the frontier by one element
         ++just_after_last_sorted;
         ++           last_sorted;
       } // this loop _must_ come _before_ the code to figure out how many elem.s to splice and 
where to splice them to [place-marker: NOTE 668]

       if (end() != just_after_last_sorted) { // check again in case advancing the frontier 
finished the job

         // first, find the insertion point for the first-past-the-frontier elem.
         iterator insertion_point{begin()};
         while ( ! comp(*just_after_last_sorted, *insertion_point) )  ++insertion_point;

         // set up some needed iterators
         const iterator just_after_insertion_point{std::next(insertion_point)};
         iterator prev_elem_checked_for_order_in_sublist_to_splice{ 
just_after_last_sorted};
         iterator 
just_after_last_elem_in_sublist_to_splice{std::next(just_after_last_sorted)};

         // try to make {the sublist to be spliced} as long as it can be while still being correct
         while ( (end() != just_after_last_elem_in_sublist_to_splice) && // ...
         /*...*/ ( ! comp(*just_after_insertion_point, 
*just_after_last_elem_in_sublist_to_splice) ) &&
         /*...*/ ! comp(*just_after_last_elem_in_sublist_to_splice, 
*prev_elem_checked_for_order_in_sublist_to_splice) ) {
           // extend the to-splice sublist by one element "to the right"
           ++prev_elem_checked_for_order_in_sublist_to_splice;
           ++just_after_last_elem_in_sublist_to_splice;
         }

         splice(insertion_point, *this, just_after_last_sorted, 
just_after_last_elem_in_sublist_to_splice);

         just_after_last_sorted = std::next(last_sorted); // refresh the iterator so it points 
to whatever is now just past the frontier
         // We don`t need to refresh the iterator "last_sorted" b/c this is a linked list...
         //   and we definitely did not insert at the frontier [see NOTE 668].

       } // end if
     } // end while
   } // end of "sort_without_temporary_list(Compare comp)"
   void         sort_without_temporary_list() { sort_without_temporary_list(op_less); }


More information about the llvm-dev mailing list