On Tue, Jan 19, 2016 at 10:08:17AM +0100, Richard Biener wrote:
> 
> The following patch enhances the recent change to DOMs memory reference
> value-numbering to cover PR69336 (all handled components instead of
> just ones with outermost ARRAY_REF).
> 
> Bootstrapped and tested on x86_64-unknown-linux-gnu.

The new test case fails on s390x:

-- snip --
  void * D.35681;
  size_t n;
  const struct static_map cmap;
  const char * _4;
  int _5;
  int _11;
  void * _15;
  int _25;

  <bb 2>:
  cmap = *.LC3;
  _5 = cmap._values[0].second.first;
  if (_5 == 8)
    goto <bb 5>;
  else
    goto <bb 3>;

  <bb 3>:
  _25 = cmap._values[1].second.first;
  if (_25 == 8)
    goto <bb 5>;
  else
    goto <bb 4>;

  <bb 4>:
  _11 = cmap._values[2].second.first;
  if (_11 == 8)
    goto <bb 5>;
  else
    goto <bb 6>;

  <bb 5>:
  # n_8 = PHI <2(4), 0(2), 1(3)>
  _4 = MEM[(const char * const &)&cmap]._values[n_8].second.second;
  if (_4 == 0B)
    goto <bb 9>;
  else
    goto <bb 10>;

  <bb 6>:
  _15 = __cxa_allocate_exception (16);
  std::out_of_range::out_of_range (_15, "Key not found");

  <bb 7>:
  __cxa_throw (_15, &_ZTISt12out_of_range, __comp_dtor );

<L6>:
  __cxa_free_exception (_15);
  _3 = __builtin_eh_pointer (5);
  __builtin_unwind_resume (_3);

  <bb 9>:
  abort ();

  <bb 10>:
  cmap ={v} {CLOBBER};
  return 0;
-- snip --

> 2016-01-19  Richard Biener  <rguent...@suse.de>
> 
>       PR tree-optimization/69336
>       * tree-ssa-scopedtables.c (avail_expr_hash): Handle all
>       handled components with get_ref_base_and_extent.
>       (equal_mem_array_ref_p): Adjust.
> 
>       * g++.dg/tree-ssa/pr69336.C: New testcase.
> 
> Index: gcc/tree-ssa-scopedtables.c
> ===================================================================
> *** gcc/tree-ssa-scopedtables.c       (revision 232508)
> --- gcc/tree-ssa-scopedtables.c       (working copy)
> *************** avail_expr_hash (class expr_hash_elt *p)
> *** 214,220 ****
>       {
>         /* T could potentially be a switch index or a goto dest.  */
>         tree t = expr->ops.single.rhs;
> !       if (TREE_CODE (t) == MEM_REF || TREE_CODE (t) == ARRAY_REF)
>       {
>         /* Make equivalent statements of both these kinds hash together.
>            Dealing with both MEM_REF and ARRAY_REF allows us not to care
> --- 214,220 ----
>       {
>         /* T could potentially be a switch index or a goto dest.  */
>         tree t = expr->ops.single.rhs;
> !       if (TREE_CODE (t) == MEM_REF || handled_component_p (t))
>       {
>         /* Make equivalent statements of both these kinds hash together.
>            Dealing with both MEM_REF and ARRAY_REF allows us not to care
> *************** avail_expr_hash (class expr_hash_elt *p)
> *** 251,259 ****
>   static bool
>   equal_mem_array_ref_p (tree t0, tree t1)
>   {
> !   if (TREE_CODE (t0) != MEM_REF && TREE_CODE (t0) != ARRAY_REF)
>       return false;
> !   if (TREE_CODE (t1) != MEM_REF && TREE_CODE (t1) != ARRAY_REF)
>       return false;
>   
>     if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1)))
> --- 251,259 ----
>   static bool
>   equal_mem_array_ref_p (tree t0, tree t1)
>   {
> !   if (TREE_CODE (t0) != MEM_REF && ! handled_component_p (t0))
>       return false;
> !   if (TREE_CODE (t1) != MEM_REF && ! handled_component_p (t1))
>       return false;
>   
>     if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1)))
> Index: gcc/testsuite/g++.dg/tree-ssa/pr69336.C
> ===================================================================
> *** gcc/testsuite/g++.dg/tree-ssa/pr69336.C   (revision 0)
> --- gcc/testsuite/g++.dg/tree-ssa/pr69336.C   (working copy)
> ***************
> *** 0 ****
> --- 1,86 ----
> + // { dg-do compile }
> + // { dg-options "-O3 -fdump-tree-optimized -std=c++14" }
> + 
> + #include <array>
> + #include <utility>
> + 
> + 
> + template<class Key, class T, size_t N> struct static_map
> + {
> +   using key_type = Key;
> +   using mapped_type = T;
> +   using value_type = std::pair<const key_type, mapped_type>;
> + private:
> +   using _value_type = std::pair<size_t, value_type>;
> +   _value_type _values[N];
> +   static constexpr _value_type _new_value_type(const std::pair<Key, T> &v)
> +   {
> +     return std::make_pair(0, std::make_pair(v.first, v.second));
> +   }
> + public:
> +   template<class... U> constexpr static_map(U &&...il) : _values{ 
> _new_value_type(il)... } { }
> +   constexpr mapped_type &operator[](const key_type &k) { return at(k); }
> +   constexpr const mapped_type &operator[](const key_type &k) const { return 
> at(k); }
> +   constexpr mapped_type &at(const key_type &k)
> +   {
> +     for (size_t n = 0; n < N; n++)
> +       if (_values[n].second.first == k)
> +         return _values[n].second.second;
> +     throw std::out_of_range("Key not found");
> +   }
> +   constexpr const mapped_type &at(const key_type &k) const
> +   {
> +     for (size_t n = 0; n < N; n++)
> +       if (_values[n].second.first == k)
> +         return _values[n].second.second;
> +     throw std::out_of_range("Key not found");
> +   }
> + };
> + namespace detail
> + {
> +   template<class Key, class T, size_t N, size_t... I> constexpr 
> static_map<Key, T, N> static_map_from_array(const std::pair<Key, T>(&il)[N], 
> std::index_sequence<I...>)
> +   {
> +     return static_map<Key, T, N>(il[I]...);
> +   }
> + }
> + template<class Key, class T, size_t N> constexpr static_map<Key, T, N> 
> make_static_map(const std::pair<Key, T> (&il)[N])
> + {
> +   return detail::static_map_from_array<Key, T, N>(il, 
> std::make_index_sequence<N>());
> + }
> + 
> + /* Two phase construction, required because heterogeneous braced init
> + in C++ 14 has a big limitation: template<class... Args> auto make(Args 
> &&...)
> + will accept make({ 5, "apple" }) as make(int, const char *) but
> + make({ 5, "apple" }, { 8, "pear" }) will fail to deduce Args as a
> + heterogeneous initializer_list is not permitted. This forces something
> + like make(make_pair{ 5, "apple" }, make_pair{ 8, "pear" }, ...) which
> + is less succinct than using a constexpr C array for the nested braced init.
> + */
> + constexpr std::pair<const int, const char *> map_data[] = {
> +   { 5, "apple" },
> +   { 8, "pear" },
> +   { 0, "banana" }
> + };
> + 
> + template<size_t N> constexpr int cstrcmp(const char *a, const char *b)
> + {
> +   for (size_t n = 0; n < N; n++)
> +   {
> +     if (a[n] < b[n]) return -1;
> +     if (a[n] > b[n]) return 1;
> +   }
> +   return 0;
> + }
> + 
> + int main(void)
> + {
> +   constexpr auto cmap = make_static_map(map_data);
> +   // No abort() appears in assembler, so this was executed constexpr
> +   if(!cmap[8]) abort();
> +   // This however does cause code implementing a lookup to be generated,
> +   // so this was NOT executed constexpr
> +   //const char *foo=cmap[5];
> +   return 0;
> + }
> + 
> + // { dg-final { scan-tree-dump-not "cmap" "optimized" } }

Ciao

Dominik ^_^  ^_^

-- 

Dominik Vogt
IBM Germany

Reply via email to