aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr69336.C86
-rw-r--r--gcc/tree-ssa-scopedtables.c6
4 files changed, 101 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index dfc2174..a4a9047 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c0dfcf1..9f48678 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..67f87cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr69336.C
@@ -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" } }
diff --git a/gcc/tree-ssa-scopedtables.c b/gcc/tree-ssa-scopedtables.c
index c421f43..613f50b 100644
--- a/gcc/tree-ssa-scopedtables.c
+++ b/gcc/tree-ssa-scopedtables.c
@@ -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)))