[PATCH] vectorizer: add _bb_vec_info::const_iterator

Richard Sandiford richard.sandiford@arm.com
Wed Jun 17 20:05:02 GMT 2020


Martin Liška <mliska@suse.cz> writes:
> On 6/16/20 4:14 PM, Richard Sandiford wrote:
>> Martin Liška <mliska@suse.cz> writes:
>>> Hmm, sounds like a nice abstraction but I see 2 problems with that:
>>>
>>> 1) How can I define a constructor of the iterator_pair when I need something like:
>>> iterator_pair<const_iterator> (region_begin, region_end)?
>> 
>> Not sure if I'm answering the right question, sorry, but I meant
>> something along the lines of:
>> 
>>    template<typename T>
>>    struct iterator_pair
>>    {
>>    public:
>>      iterator_pair (const T &begin, const T &end)
>>        : m_begin (begin), m_end (end) {}
>> 
>>      T begin () const { return m_begin; }
>>      T end () const { return m_end; }
>> 
>>    private:
>>      T m_begin;
>>      T m_end;
>>    };
>> 
>>> 2) rbegin function is more complex than begin function:
>>>
>>>         reverse_iterator rbegin () const
>>> 	{
>>> 	  reverse_iterator it = reverse_iterator (m_region_end);
>>> 	  if (*it == NULL)
>>> 	    return reverse_iterator (gsi_last_bb (m_region_end.bb));
>>> 	  else
>>> 	    return ++it;
>>> 	}
>>>
>>>         const_iterator begin () const { return const_iterator (m_region_begin); }
>>>
>>> How can we abstract that?
>> 
>> With the change above, we'd replace “rbegin” and “rend”
>> with a “reverse_region_stmts” function that returns an
>> “iterator_pair<const_reverse_iterator>”.  Its “begin” iterator
>> would have the value that “rbegin” calculates above and its “end”
>> iterator would have the same value as the current patch's “rend”.
>
> All right, you provided a nice hints! There's updated version of the patch.
>
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
>
> Ready to be installed?
> Thanks,
> Martin
>
> [...]
> +    gimple *operator* () const { return gsi_stmt (gsi); }
> +
> +    bool
> +    operator== (const const_iterator& other) const

I think the usual formatting in GCC (though not elsewhere) is to put the
space before rather than after the “&”, like for pointers.  Same for the
rest of the patch.

> +    {
> +      return gsi_stmt (gsi) == gsi_stmt (other.gsi);
> +    }
> +
> +    bool
> +    operator!= (const const_iterator& other) const
> +    {
> +      return !(*this == other);
> +    }
> +
> +    gimple_stmt_iterator gsi;
> +  };
> +
> +  /* GIMPLE statement iterator going from region_end to region_begin.  */
> +
> +  struct reverse_const_iterator

The standard name for this abstraction is const_reverse_iterator rather
than reverse_const_iterator.

> +  {
> +    reverse_const_iterator (gimple_stmt_iterator _gsi) : gsi (_gsi) {}
> +
> +    const reverse_const_iterator &
> +    operator++ ()
> +    {
> +      gsi_prev (&gsi); return *this;
> +    }
> +
> +    gimple *operator* () const { return gsi_stmt (gsi); }
> +
> +    bool
> +    operator== (const reverse_const_iterator& other) const
> +    {
> +      return gsi_stmt (gsi) == gsi_stmt (other.gsi);
> +    }
> +
> +    bool
> +    operator!= (const reverse_const_iterator& other) const
> +    {
> +      return !(*this == other);
> +    }
> +
> +    gimple_stmt_iterator gsi;
> +  };
> +
> +  /* Returns iterator_pair for range-based loop.  */
> +
> +  iterator_pair<const_iterator>
> +  region_stmts ()
> +  {
> +    return iterator_pair<const_iterator> (const_iterator (region_begin),
> +					  const_iterator (region_end));

The const_iterator(…)s aren't necessary here, just:

    return iterator_pair<const_iterator> (region_begin, region_end);

is IMO more readable.

> +  }
> +
> +  /* Returns iterator_pair for range-based loop in a reverse order.  */
> +
> +  iterator_pair<reverse_const_iterator>
> +  reverse_region_stmts ()
> +  {
> +    reverse_const_iterator begin = reverse_const_iterator (region_end);
> +    if (*begin == NULL)
> +      begin = reverse_const_iterator (gsi_last_bb (region_end.bb));
> +    else
> +      ++begin;

Similarly here we don't need the reverse_const_iterator(…)s
(= const_reverse_iterator(…)s after the change above).  It can just be:

    const_reverse_iterator begin = region_end;
    if (*begin == NULL)
      begin = gsi_last_bb (region_end.bb);
    else
      ++begin;

> +    reverse_const_iterator end = reverse_const_iterator (region_begin);
> +
> +    return iterator_pair<reverse_const_iterator> (begin, end);

Not sure the “end” temporary really buys much, could just be:

    return iterator_pair<const_reverse_iterator> (begin, region_begin);

> +  }
>  
>    basic_block bb;
>    gimple_stmt_iterator region_begin;
>    gimple_stmt_iterator region_end;
> +
> +  _bb_vec_info (gimple_stmt_iterator, gimple_stmt_iterator, vec_info_shared *);
> +  ~_bb_vec_info ();
> +
>  } *bb_vec_info;

I realise it just ended up this way through the various iterations,
but I think the constructor and destructor should go between the
new types and the new member functions, rather than at the end.
The coding conventions say;

- first define all public types,
- then define all non-public types,
- then declare all public constructors,
- then declare the public destructor,
- then declare all public member functions,
- then declare all public member variables,

There should be no blank line before the final “}”.

OK with those changes, and thanks for your patience :-)

Richard


More information about the Gcc-patches mailing list