2016-01-19 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Jan 2016 13:27:11 +0000 (13:27 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 19 Jan 2016 13:27:11 +0000 (13:27 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232559 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/tree-ssa/pr69336.C [new file with mode: 0644]
gcc/tree-ssa-scopedtables.c

index dfc2174..a4a9047 100644 (file)
@@ -1,3 +1,10 @@
+2016-01-19  Richard Biener  <rguenther@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.
+
 2016-01-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/65779
index c0dfcf1..9f48678 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-19  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/69336
+       * g++.dg/tree-ssa/pr69336.C: New testcase.
+
 2016-01-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/65779
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr69336.C b/gcc/testsuite/g++.dg/tree-ssa/pr69336.C
new file mode 100644 (file)
index 0000000..67f87cf
--- /dev/null
@@ -0,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" } }
index c421f43..613f50b 100644 (file)
@@ -214,7 +214,7 @@ avail_expr_hash (class expr_hash_elt *p)
     {
       /* 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)
+      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
@@ -252,9 +252,9 @@ avail_expr_hash (class expr_hash_elt *p)
 static bool
 equal_mem_array_ref_p (tree t0, tree t1)
 {
-  if (TREE_CODE (t0) != MEM_REF && TREE_CODE (t0) != ARRAY_REF)
+  if (TREE_CODE (t0) != MEM_REF && ! handled_component_p (t0))
     return false;
-  if (TREE_CODE (t1) != MEM_REF && TREE_CODE (t1) != ARRAY_REF)
+  if (TREE_CODE (t1) != MEM_REF && ! handled_component_p (t1))
     return false;
 
   if (!types_compatible_p (TREE_TYPE (t0), TREE_TYPE (t1)))