Re: Fix vector C++11 allocator bug

2013-03-09 Thread François Dumont

On 03/08/2013 10:26 PM, Jonathan Wakely wrote:

On 8 March 2013 20:16, François Dumont wrote:

This is indeed better so I applied the patch as you proposed.

Thanks, can you also make the same changes to the 4.7 branch? If not I
can do so.


Attached patch tested under Linux x86_64 and applied to 4.7 branch.

2013-03-09  François Dumont  

* include/bits/vector.tcc (vector<>operator=(const vector<>&):
Reset pointers after deallocation when memory can be reused.
* testsuite/23_containers/vector/allocator/minimal.cc: Insert
elements to really challenge C++11 allocator integration.
* testsuite/23_containers/vector/allocator/copy.cc: Likewise.
* testsuite/23_containers/vector/allocator/copy_assign.cc:
Likewise.
* testsuite/23_containers/vector/allocator/move_assign.cc:
Likewise.
* testsuite/23_containers/vector/allocator/swap.cc: Likewise and
swap vector back before checks on memory/personality mapping are
performed.

Index: include/bits/vector.tcc
===
--- include/bits/vector.tcc	(revision 196569)
+++ include/bits/vector.tcc	(working copy)
@@ -174,6 +174,9 @@
 		  _M_deallocate(this->_M_impl._M_start,
 this->_M_impl._M_end_of_storage
 - this->_M_impl._M_start);
+		  this->_M_impl._M_start = nullptr;
+		  this->_M_impl._M_finish = nullptr;
+		  this->_M_impl._M_end_of_storage = nullptr;
 		}
 	  std::__alloc_on_copy(_M_get_Tp_allocator(),
    __x._M_get_Tp_allocator());
Index: testsuite/23_containers/vector/allocator/copy.cc
===
--- testsuite/23_containers/vector/allocator/copy.cc	(revision 196569)
+++ testsuite/23_containers/vector/allocator/copy.cc	(working copy)
@@ -31,6 +31,7 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(v1);
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(0 == v2.get_allocator().get_personality());
@@ -42,6 +43,7 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(v1);
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(1 == v2.get_allocator().get_personality());
Index: testsuite/23_containers/vector/allocator/move_assign.cc
===
--- testsuite/23_containers/vector/allocator/move_assign.cc	(revision 196569)
+++ testsuite/23_containers/vector/allocator/move_assign.cc	(working copy)
@@ -31,7 +31,9 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(alloc_type(2));
+  v2.push_back(T());
   v2 = std::move(v1);
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(2 == v2.get_allocator().get_personality());
@@ -43,8 +45,10 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(alloc_type(2));
   v2 = std::move(v1);
+  v2.push_back(T());
   VERIFY(0 == v1.get_allocator().get_personality());
   VERIFY(1 == v2.get_allocator().get_personality());
 }
Index: testsuite/23_containers/vector/allocator/swap.cc
===
--- testsuite/23_containers/vector/allocator/swap.cc	(revision 196569)
+++ testsuite/23_containers/vector/allocator/swap.cc	(working copy)
@@ -31,10 +31,14 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(alloc_type(2));
+  v2.push_back(T());
   std::swap(v1, v2);
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(2 == v2.get_allocator().get_personality());
+  // swap back so assertions in uneq_allocator::deallocate don't fail
+  std::swap(v1, v2);
 }
 
 void test02()
Index: testsuite/23_containers/vector/allocator/copy_assign.cc
===
--- testsuite/23_containers/vector/allocator/copy_assign.cc	(revision 196569)
+++ testsuite/23_containers/vector/allocator/copy_assign.cc	(working copy)
@@ -31,7 +31,9 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(alloc_type(2));
+  v2.push_back(T());
   v2 = v1;
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(2 == v2.get_allocator().get_personality());
@@ -43,7 +45,9 @@
   typedef propagating_allocator alloc_type;
   typedef std::vector test_type;
   test_type v1(alloc_type(1));
+  v1.push_back(T());
   test_type v2(alloc_type(2));
+  v2.push_back(T());
   v2 = v1;
   VERIFY(1 == v1.get_allocator().get_personality());
   VERIFY(1 == v2.get_allocator().get_personality());
Index: testsuite/23_containers/vector/allocator/mini

[v3] Tweak a recent testcase vs -Wunused

2013-03-09 Thread Paolo Carlini

Hi,

just avoid spurious fails with -Wunused (or -Wall 
-Wno-unused-local-typdefs, which is what I often actually try).


Thanks,
Paolo.


2013-03-09  Paolo Carlini  

* testsuite/20_util/function_objects/mem_fn/55463.cc: Avoid
-Wunused warnings.
Index: testsuite/20_util/function_objects/mem_fn/55463.cc
===
--- testsuite/20_util/function_objects/mem_fn/55463.cc  (revision 196571)
+++ testsuite/20_util/function_objects/mem_fn/55463.cc  (working copy)
@@ -50,59 +50,63 @@
 
 void test01()
 {
-  int& i1 = std::mem_fn( &X::func )( X() );
-  int& i2 = std::mem_fn( &X::func )( Y() );
-  int& i3 = std::mem_fn( &X::func )( ref() );
-  int& i4 = std::mem_fn( &X::func )( yref() );
-  int& i5 = std::mem_fn( &X::func )( X_ptr() );
-  int& i6 = std::mem_fn( &X::func )( smart_ptr() );
+  int& i1 __attribute__((unused)) = std::mem_fn( &X::func )( X() );
+  int& i2 __attribute__((unused)) = std::mem_fn( &X::func )( Y() );
+  int& i3 __attribute__((unused)) = std::mem_fn( &X::func )( ref() );
+  int& i4 __attribute__((unused)) = std::mem_fn( &X::func )( yref() );
+  int& i5 __attribute__((unused)) = std::mem_fn( &X::func )( X_ptr() );
+  int& i6 __attribute__((unused)) = std::mem_fn( &X::func )( smart_ptr() );
 
-  char& c1 = std::mem_fn( &X::func_c )( X() );
-  char& c2 = std::mem_fn( &X::func_c )( CX() );
-  char& c3 = std::mem_fn( &X::func_c )( Y() );
-  char& c4 = std::mem_fn( &X::func_c )( ref() );
-  char& c5 = std::mem_fn( &X::func_c )( cref() );
-  char& c6 = std::mem_fn( &X::func_c )( yref() );
-  char& c7 = std::mem_fn( &X::func_c )( X_ptr() );
-  char& c8 = std::mem_fn( &X::func_c )( smart_ptr() );
+  char& c1 __attribute__((unused)) = std::mem_fn( &X::func_c )( X() );
+  char& c2 __attribute__((unused)) = std::mem_fn( &X::func_c )( CX() );
+  char& c3 __attribute__((unused)) = std::mem_fn( &X::func_c )( Y() );
+  char& c4 __attribute__((unused)) = std::mem_fn( &X::func_c )( ref() );
+  char& c5 __attribute__((unused)) = std::mem_fn( &X::func_c )( cref() );
+  char& c6 __attribute__((unused)) = std::mem_fn( &X::func_c )( yref() );
+  char& c7 __attribute__((unused)) = std::mem_fn( &X::func_c )( X_ptr() );
+  char& c8 __attribute__((unused)) = std::mem_fn( &X::func_c )( smart_ptr() );
 
-  short& s1 = std::mem_fn( &X::func_v )( X() );
-  short& s2 = std::mem_fn( &X::func_v )( Y() );
-  short& s3 = std::mem_fn( &X::func_v )( ref() );
-  short& s4 = std::mem_fn( &X::func_v )( yref() );
-  short& s5 = std::mem_fn( &X::func_v )( X_ptr() );
-  short& s6 = std::mem_fn( &X::func_v )( smart_ptr() );
+  short& s1 __attribute__((unused)) = std::mem_fn( &X::func_v )( X() );
+  short& s2 __attribute__((unused)) = std::mem_fn( &X::func_v )( Y() );
+  short& s3 __attribute__((unused)) = std::mem_fn( &X::func_v )( ref() );
+  short& s4 __attribute__((unused)) = std::mem_fn( &X::func_v )( yref() );
+  short& s5 __attribute__((unused)) = std::mem_fn( &X::func_v )( X_ptr() );
+  short& s6 __attribute__((unused)) = std::mem_fn( &X::func_v )( smart_ptr() );
 
-  double& d1 = std::mem_fn( &X::func_cv )( X() );
-  double& d2 = std::mem_fn( &X::func_cv )( CX() );
-  double& d3 = std::mem_fn( &X::func_cv )( Y() );
-  double& d4 = std::mem_fn( &X::func_cv )( ref() );
-  double& d5 = std::mem_fn( &X::func_cv )( cref() );
-  double& d6 = std::mem_fn( &X::func_cv )( yref() );
-  double& d7 = std::mem_fn( &X::func_cv )( X_ptr() );
-  double& d8 = std::mem_fn( &X::func_cv )( smart_ptr() );
+  double& d1 __attribute__((unused)) = std::mem_fn( &X::func_cv )( X() );
+  double& d2 __attribute__((unused)) = std::mem_fn( &X::func_cv )( CX() );
+  double& d3 __attribute__((unused)) = std::mem_fn( &X::func_cv )( Y() );
+  double& d4 __attribute__((unused)) = std::mem_fn( &X::func_cv )( ref() );
+  double& d5 __attribute__((unused)) = std::mem_fn( &X::func_cv )( cref() );
+  double& d6 __attribute__((unused)) = std::mem_fn( &X::func_cv )( yref() );
+  double& d7 __attribute__((unused)) = std::mem_fn( &X::func_cv )( X_ptr() );
+  double& d8 __attribute__((unused))
+= std::mem_fn( &X::func_cv )( smart_ptr() );
 
   // [expr.mptr.oper]
   // The result of a .* expression whose second operand is a pointer to a
   // data member is of the same value category (3.10) as its first operand.
-  int&& rval = std::mem_fn( &X::data )( X() );
-  const int&& crval = std::mem_fn( &X::data )( CX() );
-  int&& yrval = std::mem_fn( &X::data )( Y() );
-  const int&& ycrval = std::mem_fn( &X::data )( CY() );
+  int&& rval __attribute__((unused)) = std::mem_fn( &X::data )( X() );
+  const int&& crval __attribute__((unused)) = std::mem_fn( &X::data )( CX() );
+  int&& yrval __attribute__((unused)) = std::mem_fn( &X::data )( Y() );
+  const int&& ycrval __attribute__((unused)) = std::mem_fn( &X::data )( CY() );
 
-  int& val = std::mem_fn( &X::data )( ref() );
-  const int& cval = std::mem_fn( &X::data )( cref() );
-  int& yval = std::mem_fn( &X::data )( yref() );
+  int& 

New German PO file for 'cpplib' (version 4.8-b20130224)

2013-03-09 Thread Translation Project Robot
Hello, gentle maintainer.

This is a message from the Translation Project robot.

A revised PO file for textual domain 'cpplib' has been submitted
by the German team of translators.  The file is available at:

http://translationproject.org/latest/cpplib/de.po

(This file, 'cpplib-4.8-b20130224.de.po', has just now been sent to you in
a separate email.)

All other PO files for your package are available in:

http://translationproject.org/latest/cpplib/

Please consider including all of these in your next release, whether
official or a pretest.

Whenever you have a new distribution with a new version number ready,
containing a newer POT file, please send the URL of that distribution
tarball to the address below.  The tarball may be just a pretest or a
snapshot, it does not even have to compile.  It is just used by the
translators when they need some extra translation context.

The following HTML page has been updated:

http://translationproject.org/domain/cpplib.html

If any question arises, please contact the translation coordinator.

Thank you for all your work,

The Translation Project robot, in the
name of your translation coordinator.




New German PO file for 'cpplib' (version 4.8-b20130224)

2013-03-09 Thread Translation Project Robot
Hello, gentle maintainer.

This is a message from the Translation Project robot.

A revised PO file for textual domain 'cpplib' has been submitted
by the German team of translators.  The file is available at:

http://translationproject.org/latest/cpplib/de.po

(This file, 'cpplib-4.8-b20130224.de.po', has just now been sent to you in
a separate email.)

All other PO files for your package are available in:

http://translationproject.org/latest/cpplib/

Please consider including all of these in your next release, whether
official or a pretest.

Whenever you have a new distribution with a new version number ready,
containing a newer POT file, please send the URL of that distribution
tarball to the address below.  The tarball may be just a pretest or a
snapshot, it does not even have to compile.  It is just used by the
translators when they need some extra translation context.

The following HTML page has been updated:

http://translationproject.org/domain/cpplib.html

If any question arises, please contact the translation coordinator.

Thank you for all your work,

The Translation Project robot, in the
name of your translation coordinator.




Re: [lra] Merged with trunk

2013-03-09 Thread Steven Bosscher
On Fri, Mar 8, 2013 at 10:24 PM, Vladimir Makarov  wrote:
> LRA branch has been merged with trunk @ 196555.
>
> The branch was successfully bootstrapped on x86/x86-64.

Also on powerpc64-unknown-linux-gnu, and ia64-unknown-linux-gnu, as
well as cross to mipsisa64-elf.

There is one powerpc64 failure on the lra-branch that works on the trunk:

+FAIL: gcc.target/powerpc/pr53199.c scan-assembler-times stwbrx 6

This FAIL has been there since my autotester started, but half of the
problem disappeared with one of the merges in February:

Compiler version: 4.8.0 20130201 (experimental) [lra revision 195682]:
FAIL: gcc.target/powerpc/pr53199.c scan-assembler-times lwbrx 6
FAIL: gcc.target/powerpc/pr53199.c scan-assembler-times stwbrx 6

Compiler version: 4.8.0 20130222 (experimental) [lra revision 196227]:
FAIL: gcc.target/powerpc/pr53199.c scan-assembler-times stwbrx 6

Ciao!
Steven


[patch] Make dse.c dumps less verbose unless dumping details

2013-03-09 Thread Steven Bosscher
Hello,

Debugging a DSE bug, I found the dumps to be almost unusable because
they are so verbose. For my test case, the -fdump-rtl-dse1 dump is a
~17GB file without the attached patch (the test case has ~5
insns). With the patch, all this extra information is only dumped with
-fdump-rtl-dse1-details.

Bootstrapped&tested on x86_64-unknown-linux-gnu and
powerpc64-unknown-linux-gnu. Will commit as obvious.

Ciao!
Steven

* dse.c (delete_dead_store_insn): Respect TDF_DETAILS.
(canon_address, record_store, replace_read, check_mem_read_rtx,
scan_insn, dse_step1, dse_step2_init, dse_step2_spill,
dse_step4, dse_step5_nospill, dse_step5_spill, dse_step6,
rest_of_handle_dse): Likewise.


dse_dump_details.diff
Description: Binary data


[patch PR middle-end/39326 - compile time and memory explosion in combine

2013-03-09 Thread Steven Bosscher
Hello,

The attached patch fixes one of the (at least) three scalability
problems reported in PR middle-end/39326. This problem is that combine
takes forever and increases the memory footprint from ~650MB to >7GB.
The cause is DSE creating a lot of new registers in replace_read, and
those registers are not copy-prop'd out between dse1 and combine. The
result is many overlapping live ranges and single-set-single-use
registers that combine is made to work on.

The fix is to just not create so many new registers in DSE in the
first place. It is wasteful and unnecessary if an existing register
can be re-used.

With this patch, for the test case of the PR the combine time in
combine goes down from ~350s to ~4.5s, and the memory footprint
explosion is avoided. For my set of cc1-i files this also helps reduce
compile time a modest amount, especially for the larger files of
course.

Bootstrapped&tested on {x86_64,powerpc64}-unknown-linux-gnu.
OK for trunk?

Ciao!
Steven


PR middle-end/39326
* dse.c (replace_read): If the stored value is a pseudo-register
that is set only once, re-use it to replace the load instead of
creating a new register.


PR39326_RTLDSE.diff
Description: Binary data


[patch] PR middle-end/39326 - limit LIM

2013-03-09 Thread Steven Bosscher
Hello,

The attached patch fixes another one of the scalability problems
reported in PR middle-end/39326.

This problem is that tree loop-invariant code motion explodes on basic
blocks with many memory references. Compile time is quadratic in the
number of memory references in the basic block, and so are the memory
requirements when the dependences or independences are propagated
bottom-up through the loop tree.

The fix is to give up on loops with too many memory references to
handle. There is already a param for that for loop dependence
analysis, and this patch makes LIM use the same param.

Bootstrapped&tested on {x86_64,powerpc64}-unknown-linux-gnu.
OK for trunk?

Ciao!
Steven

(The ChangeLog is a bit long but the patch is relatively straight-forward.)

* tree-flow.h (enum move_pos): Moved to tree-ssa-loop-im.c.
* tree-ssa-loop-im.c: Include diagnostic-core.h for warning_at()
(enum move_pos): Moved here.
(movement_possibility): Made static.  Reject memory operations in
loops with too many memory references to handle.
(determine_max_movement): Take loops_with_too_many_memrefs argument.
For statements referencing memory, find the outermost superloop
that is not in the loops_with_too_many_memrefs set.
(determine_invariantness_stmt): Take loops_with_too_many_memrefs
via dom_walk_data.global_data, and pass it along where necessary.
Hoist "pos == MOVE_POSSIBLE" test.
(determine_invariantness): Take loops_with_too_many_memrefs argument.
(move_computations): Likewise, but unused for now.
(gather_mem_refs_stmt): Fail if there are too many memory references.
Use PARAM_LOOP_MAX_DATAREFS_FOR_DATADEPS as threshold.  Add disabled
optimization warning.
(gather_mem_refs_in_loops): Take loops_with_too_many_memrefs argument.
Propagate it from inner loops to outer loops.  Do not propagate
recorded memory references for loops on which memory optimizations
are disabled.
(create_vop_ref_mapping): Take loops_with_too_many_memrefs argument.
Don't create a mapping on loops that are in this set.
(analyze_memory_references): Take loops_with_too_many_memrefs argument
and let subroutines fill it.
(store_motion): Take loops_with_too_many_memrefs argument.
Skip loops that are in this set.
(tree_ssa_lim): Allocate, pass, and free loops_with_too_many_memrefs.


PR39326_LIM.diff
Description: Binary data


[C++ Patch] PR 56582

2013-03-09 Thread Paolo Carlini

Hi,

in cxx_eval_array_reference we don't check whether the subscript is 
negative and we end up either ICEing or emitting wrong code. Adding the 
check seems trivial, but I'm not sure if there is something more subtle 
to the issue which I'm missing.


Also note that in principle we could have somewhat neater code but, as 
far as I can see, we would end up doing more comparisons (see the _alt 
patch).


Tested x86_64-linux.

Thanks,
Paolo.


/cp
2013-03-09  Paolo Carlini  

PR c++/56582
* semantics.c (cxx_eval_array_reference): Check for negative index.

/testsuite
2013-03-09  Paolo Carlini  

PR c++/56582
* g++.dg/cpp0x/constexpr-array5.C: New.
Index: cp/semantics.c
===
--- cp/semantics.c  (revision 196574)
+++ cp/semantics.c  (working copy)
@@ -7007,6 +7007,13 @@ cxx_eval_array_reference (const constexpr_call *ca
   *non_constant_p = true;
   return t;
 }
+  else if (tree_int_cst_lt (index, integer_zero_node))
+{
+  if (!allow_non_constant)
+   error ("negative array subscript");
+  *non_constant_p = true;
+  return t;
+}
   i = tree_low_cst (index, 0);
   if (TREE_CODE (ary) == CONSTRUCTOR)
 return (*CONSTRUCTOR_ELTS (ary))[i].value;
Index: testsuite/g++.dg/cpp0x/constexpr-array5.C
===
--- testsuite/g++.dg/cpp0x/constexpr-array5.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/constexpr-array5.C   (working copy)
@@ -0,0 +1,9 @@
+// PR c++/56582
+// { dg-do compile { target c++11 } }
+
+// Reliable ICE
+constexpr int n[3] = {};
+constexpr int k = n[-1];// { dg-error "negative" }
+
+// Some random byte
+constexpr char c = "foo"[-1000];// { dg-error "negative" }
Index: cp/semantics.c
===
--- cp/semantics.c  (revision 196574)
+++ cp/semantics.c  (working copy)
@@ -6990,23 +6990,23 @@ cxx_eval_array_reference (const constexpr_call *ca
   VERIFY_CONSTANT (ary);
   gcc_unreachable ();
 }
-  if (compare_tree_int (index, len) >= 0)
+  if (tree_int_cst_lt (index, integer_zero_node)
+  || !tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary
 {
-  if (tree_int_cst_lt (index, array_type_nelts_top (TREE_TYPE (ary
-   {
- /* If it's within the array bounds but doesn't have an explicit
-initializer, it's value-initialized.  */
- tree val = build_value_init (elem_type, tf_warning_or_error);
- return cxx_eval_constant_expression (call, val,
-  allow_non_constant, addr,
-  non_constant_p, overflow_p);
-   }
-
   if (!allow_non_constant)
error ("array subscript out of bound");
   *non_constant_p = true;
   return t;
 }
+  if (compare_tree_int (index, len) >= 0)
+{
+  /* If it's within the array bounds but doesn't have an explicit
+initializer, it's value-initialized.  */
+  tree val = build_value_init (elem_type, tf_warning_or_error);
+  return cxx_eval_constant_expression (call, val,
+  allow_non_constant, addr,
+  non_constant_p, overflow_p);
+}
   i = tree_low_cst (index, 0);
   if (TREE_CODE (ary) == CONSTRUCTOR)
 return (*CONSTRUCTOR_ELTS (ary))[i].value;
Index: testsuite/g++.dg/cpp0x/constexpr-array5.C
===
--- testsuite/g++.dg/cpp0x/constexpr-array5.C   (revision 0)
+++ testsuite/g++.dg/cpp0x/constexpr-array5.C   (working copy)
@@ -0,0 +1,9 @@
+// PR c++/56582
+// { dg-do compile { target c++11 } }
+
+// Reliable ICE
+constexpr int n[3] = {};
+constexpr int k = n[-1];// { dg-error "out of bound" }
+
+// Some random byte
+constexpr char c = "foo"[-1000];// { dg-error "out of bound" }