Re: [x86_64 PATCH] Allow any immediate constant in *cmp_doubleword splitter.

2022-08-06 Thread Uros Bizjak via Gcc-patches
On Fri, Aug 5, 2022 at 3:14 PM Roger Sayle  wrote:
>
>
> This patch tweaks i386.md's *cmp_doubleword splitter's predicate to
> allow general_operand, not just x86_64_hilo_general_operand, to improve
> code generation.  As a general rule, i386.md's _doubleword splitters should
> be post-reload splitters that require integer immediate operands to be
> x86_64_hilo_int_operand, so that each part is a valid word mode immediate
> constant.  As an exception to this rule, doubleword patterns that must be
> split before reload, because they require additional scratch registers,
> can take advantage of this ability to create new pseudos, to accept
> any immediate constant, and call force_reg on the high and/or low parts
> if they are not suitable immediate operands in word mode.
>
> The benefit is shown in the new cmpti3.c test case below.
>
> __int128 x;
> int foo()
> {
> __int128 t = 0x1234567890abcdefLL;
> return x == t;
> }
>
> where GCC with -O2 currently generates:
>
> movabsq $1311768467294899695, %rax
> xorl%edx, %edx
> xorqx(%rip), %rax
> xorqx+8(%rip), %rdx
> orq %rdx, %rax
> sete%al
> movzbl  %al, %eax
> ret
>
> but with this patch now generates:
>
> movabsq $1311768467294899695, %rax
> xorqx(%rip), %rax
> orq x+8(%rip), %rax
> sete%al
> movzbl  %al, %eax
> ret
>
> This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> and make -k check, both with and without --target_board=unix{-m32},
> with no new failures.  The first two new test cases aren't affected
> by this patch, but as I had them in my directory, it seemed reasonable to
> increase the testsuite's coverage of TImode comparison code generation.
> Ok for mainline?
>
> 2022-08-05  Roger Sayle  
>
> gcc/ChangeLog
> * config/i386/i386.md (*cmp_doubleword): Change predicate
> for x86_64_hilo_general_operand to general operand.  Call
> force_reg on parts that are not x86_64_immediate_operand.
>
> gcc/testsuite/ChangeLog
> * gcc.target/i386/cmpti1.c: New test case.
> * gcc.target/i386/cmpti2.c: Likewise.
> * gcc.target/i386/cmpti3.c: Likewise.

OK.

Thanks,
Uros.


[PATCH] c++: Extend -Wredundant-move for const-qual objects [PR90428]

2022-08-06 Thread Marek Polacek via Gcc-patches
In this PR, Jon suggested extending the -Wredundant-move warning
to warn when the user is moving a const object as in:

  struct T { };

  T f(const T& t)
  {
return std::move(t);
  }

where the std::move is redundant, because T does not have
a T(const T&&) constructor (which is very unlikely).  Even with
the std::move, T(T&&) would not be used because it would mean
losing the const.  Instead, T(const T&) will be called.

I had to restructure the function a bit, but it's better now.  This patch
depends on my other recent patches to maybe_warn_pessimizing_move.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/90428

gcc/cp/ChangeLog:

* typeck.cc (maybe_warn_pessimizing_move): Extend the
-Wredundant-move warning to warn about std::move on a
const-qualified object.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wredundant-move1.C: Adjust dg-warning.
* g++.dg/cpp0x/Wredundant-move9.C: Likewise.
* g++.dg/cpp0x/Wredundant-move10.C: New test.
---
 gcc/cp/typeck.cc  | 157 +++---
 gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C |   3 +-
 .../g++.dg/cpp0x/Wredundant-move10.C  |  61 +++
 gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C |   3 +-
 4 files changed, 162 insertions(+), 62 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 70a5efc45de..802bc9c43fb 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10411,72 +10411,109 @@ maybe_warn_pessimizing_move (tree expr, tree type, 
bool return_p)
return;
 }
 
-  /* We're looking for *std::move ((T &) &arg).  */
-  if (REFERENCE_REF_P (expr)
-  && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
-{
-  tree fn = TREE_OPERAND (expr, 0);
-  if (is_std_move_p (fn))
-   {
- tree arg = CALL_EXPR_ARG (fn, 0);
- tree moved;
- if (TREE_CODE (arg) != NOP_EXPR)
-   return;
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (arg) != ADDR_EXPR)
-   return;
- arg = TREE_OPERAND (arg, 0);
- arg = convert_from_reference (arg);
- if (can_do_rvo_p (arg, type))
-   {
- auto_diagnostic_group d;
- if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
- && warning_at (loc, OPT_Wpessimizing_move,
-"moving a temporary object prevents copy "
-"elision"))
-   inform (loc, "remove % call");
-   }
- /* The rest of the warnings is only relevant for when we are
-returning from a function.  */
- else if (!return_p)
-   return;
- /* Warn if we could do copy elision were it not for the move.  */
- else if (can_do_nrvo_p (arg, type))
+  /* First, check if this is a call to std::move.  */
+  if (!REFERENCE_REF_P (expr)
+  || TREE_CODE (TREE_OPERAND (expr, 0)) != CALL_EXPR)
+return;
+  tree fn = TREE_OPERAND (expr, 0);
+  if (!is_std_move_p (fn))
+return;
+  tree arg = CALL_EXPR_ARG (fn, 0);
+  if (TREE_CODE (arg) != NOP_EXPR)
+return;
+  /* If we're looking at *std::move ((T &) &arg), do the pessimizing N/RVO
+ and implicitly-movable warnings.  */
+  if (TREE_CODE (TREE_OPERAND (arg, 0)) == ADDR_EXPR)
+{
+  arg = TREE_OPERAND (arg, 0);
+  arg = TREE_OPERAND (arg, 0);
+  arg = convert_from_reference (arg);
+  if (can_do_rvo_p (arg, type))
+   {
+ auto_diagnostic_group d;
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a temporary object prevents copy elision"))
+   inform (loc, "remove % call");
+   }
+  /* The rest of the warnings is only relevant for when we are returning
+from a function.  */
+  if (!return_p)
+   return;
+
+  tree moved;
+  /* Warn if we could do copy elision were it not for the move.  */
+  if (can_do_nrvo_p (arg, type))
+   {
+ auto_diagnostic_group d;
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a local object in a return statement "
+"prevents copy elision"))
+   inform (loc, "remove % call");
+   }
+  /* Warn if the move is redundant.  It is redundant when we would
+do maybe-rvalue overload resolution even without std::move.  */
+  else if (warn_redundant_move
+  && !warning_suppressed_p (expr, OPT_Wredundant_move)
+  && (moved = treat_lvalue_as_rvalue_p (arg, /*return*/true)))
+   {
+ /* Make sure that overload resolution would actually succeed
+if we removed the std::move call.  */
+ tree t = convert_for_initialization (NULL_TREE, type,
+

[PING^6] nvptx: forward '-v' command-line option to assembler, linker

2022-08-06 Thread Thomas Schwinge
Hi Tom!

Ping.


Grüße
 Thomas


On 2022-07-27T17:48:46+0200, I wrote:
> Hi Tom!
>
> Ping.
>
>
> Grüße
>  Thomas
>
>
> On 2022-07-20T14:44:36+0200, I wrote:
>> Hi Tom!
>>
>> Ping.
>>
>>
>> Grüße
>>  Thomas
>>
>>
>> On 2022-07-13T10:41:23+0200, I wrote:
>>> Hi Tom!
>>>
>>> Ping.
>>>
>>>
>>> Grüße
>>>  Thomas
>>>
>>>
>>> On 2022-07-05T16:58:54+0200, I wrote:
 Hi Tom!

 Ping.


 Grüße
  Thomas


 On 2022-06-07T17:41:16+0200, I wrote:
> Hi!
>
> On 2022-05-30T09:06:21+0200, Tobias Burnus  
> wrote:
>> On 29.05.22 22:49, Thomas Schwinge wrote:
>>> Not sure if that's what you had in mind, but what do you think about the
>>> attached "nvptx: forward '-v' command-line option to assembler, linker"?
>>> OK to push to GCC master branch (after merging
>>> 
>>> "Put '-v' verbose output onto stderr instead of stdout")?
>>
>> I was mainly thinking of some way to have it available — which
>> '-foffload-options=-Wa,-v' already permits on the GCC side. (Once the
>> nvptx-tools patch actually makes use of the '-v'.)
>
> (Merged a week ago.)
>
>> If I understand your patch correctly, this patch now causes 'gcc -v' to
>> imply 'gcc -v -Wa,-v'. I think that's okay, since 'gcc -v' already
>> outputs a lot of lines and those lines can be helpful to understand what
>> happens and what not.
>
> ACK.
>
>> Tom, your thoughts on this?
>
> Ping.
>
>
> Grüße
>  Thomas


-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
>From 17c35607d4927299b0c4bd19dd6fd205c85c4a4b Mon Sep 17 00:00:00 2001
From: Thomas Schwinge 
Date: Sun, 29 May 2022 22:31:43 +0200
Subject: [PATCH] nvptx: forward '-v' command-line option to assembler, linker

For example, for offloading compilation with '-save-temps -v', before vs. after
word-diff then looks like:

[...]
 [...]/build-gcc-offload-nvptx-none/gcc/as {+-v -v+} -o ./a.xnvptx-none.mkoffload.o ./a.xnvptx-none.mkoffload.s
{+Verifying sm_30 code with sm_35 code generation.+}
{+ ptxas -c -o /dev/null ./a.xnvptx-none.mkoffload.o --gpu-name sm_35 -O0+}
[...]
 [...]/build-gcc-offload-nvptx-none/gcc/collect2 {+-v -v+} -o ./a.xnvptx-none.mkoffload [...] @./a.xnvptx-none.mkoffload.args.1 -lgomp -lgcc -lc -lgcc
{+collect2 version 12.0.1 20220428 (experimental)+}
{+[...]/build-gcc-offload-nvptx-none/gcc/collect-ld -v -v -o ./a.xnvptx-none.mkoffload [...] ./a.xnvptx-none.mkoffload.o -lgomp -lgcc -lc -lgcc+}
{+Linking ./a.xnvptx-none.mkoffload.o as 0+}
{+trying lib libc.a+}
{+trying lib libgcc.a+}
{+trying lib libgomp.a+}
{+Resolving abort+}
{+Resolving acc_on_device+}
{+Linking libgomp.a::oacc-init.o/ as 1+}
{+Linking libc.a::lib_a-abort.o/   as 2+}
[...]

(This depends on 
"Put '-v' verbose output onto stderr instead of stdout".)

	gcc/
	* config/nvptx/nvptx.h (ASM_SPEC, LINK_SPEC): Define.
---
 gcc/config/nvptx/nvptx.h | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h
index ed72c253191..b184f1d0150 100644
--- a/gcc/config/nvptx/nvptx.h
+++ b/gcc/config/nvptx/nvptx.h
@@ -27,6 +27,13 @@
 
 /* Run-time Target.  */
 
+/* Assembler supports '-v' option; handle similar to
+   '../../gcc.cc:asm_options', 'HAVE_GNU_AS'.  */
+#define ASM_SPEC "%{v}"
+
+/* Linker supports '-v' option.  */
+#define LINK_SPEC "%{v}"
+
 #define STARTFILE_SPEC "%{mmainkernel:crt0.o}"
 
 #define TARGET_CPU_CPP_BUILTINS() nvptx_cpu_cpp_builtins ()
-- 
2.25.1



[PING^5] nvptx: Allow '--with-arch' to override the default '-misa' (was: nvptx multilib setup)

2022-08-06 Thread Thomas Schwinge
Hi Tom!

Ping.


Grüße
 Thomas


On 2022-07-27T17:48:58+0200, I wrote:
> Hi Tom!
>
> Ping.
>
>
> Grüße
>  Thomas
>
>
> On 2022-07-20T14:46:03+0200, I wrote:
>> Hi Tom!
>>
>> Ping.
>>
>>
>> Grüße
>>  Thomas
>>
>>
>> On 2022-07-13T10:42:44+0200, I wrote:
>>> Hi Tom!
>>>
>>> Ping.
>>>
>>>
>>> Grüße
>>>  Thomas
>>>
>>>
>>> On 2022-07-05T16:59:23+0200, I wrote:
 Hi Tom!

 Ping.


 Grüße
  Thomas


 On 2022-06-15T23:18:10+0200, I wrote:
> Hi Tom!
>
> On 2022-05-13T16:20:14+0200, I wrote:
>> On 2022-02-04T13:09:29+0100, Tom de Vries via Gcc  
>> wrote:
>>> On 2/4/22 08:21, Thomas Schwinge wrote:
 On 2022-02-03T13:35:55+, "vries at gcc dot gnu.org via Gcc-bugs" 
  wrote:
> I've tested this using (recommended) driver 470.94 on boards:
>>
> while iterating over dimensions { -mptx=3.1 , -mptx=6.3 } x { 
> GOMP_NVPTX_JIT=-O0,  }.

 Do you use separate (nvptx-none offload target only?) builds for
 different '-mptx' variants (likewise: '-misa'), or have you hacked up 
 the
 multilib configuration?
>>>
>>> Neither, I'm using --target_board=unix/foffload= for that.
>>
>> ACK, I see.  So these flags then only affect GCC/nvptx code generation
>> for the actual user code (here: GCC libgomp test cases), but for the
>> GCC/nvptx target libraries (such as: libc, libm, libgfortran, libgomp --
>> the latter especially relevant for OpenMP), it uses PTX code from one of
>> the two "pre-compiled" GCC/nvptx multilibs: default or '-mptx=3.1'.
>>
>> Meaning, one can't just use such a flag for "completely building code"
>> for a specific configuration.  Random example,
>> '-foffload-options=nvptx-none=-march=sm_75': as GCC/nvptx target
>> libraries aren't being built for '-march=sm_75' multilib,
>> '-foffload-options=nvptx-none=-march=sm_75' uses the default multilib,
>> which isn't '-march=sm_75'.
>>
>>
>>>   ('gcc/config/nvptx/t-nvptx:MULTILIB_OPTIONS'
 etc., I suppose?)  Should we add a few representative configurations to
 be built by default?  And/or, should we have a way to 'configure' per
 user needs (I suppose: '--with-multilib-list=[...]', as supported for a
 few other targets?)?  (I see there's also a new
 '--with-multilib-generator=[...]', haven't looked in detail.)  No 
 matter
 which way: again, combinatorial explosion is a problem, of course...
>>>
>>> As far as I know, the gcc build doesn't finish when switching default to
>>> higher than sm_35, so there's little point to go to a multilib setup at
>>> this point.  But once we fix that, we could reconsider, otherwise,
>>> things are likely to regress again.
>>
>> As far as I remember, several issues have been fixed.  Still waiting for
>> Roger's "middle-end: Support ABIs that pass FP values as wider integers"
>> or something similar, but that PR104489 issue is being worked around by
>> "Limit HFmode support to mexperimental", if I got that right.
>>
>> Now I'm not suggesting we should now enable all or any random GCC/nvptx
>> multilibs, to get all these variants of GCC/nvptx target libraries built;
>> especially also given that GCC/nvptx code generation currently doesn't
>> make too much use of the new capabilities.
>>
>> However, we do have a specific request that a customer would like to be
>> able to change at GCC 'configure' time the GCC/nvptx default multilib
>> (including that being used for building corresponding GCC/nvptx target
>> libraries).
>>
>> Per 'gcc/doc/install.texi', I do see that some GCC targets allow for
>> GCC 'configure'-time '--with-multilib-list=[...]', or
>> '--with-multilib-generator=[...]', and I suppose we could be doing
>> something similar?  But before starting implementing, I'd like your
>> input, as you'll be the one to approve in the end.  And/or, maybe you've
>> already made up your own ideas about that?
>
> So, instead of "random GCC/nvptx multilib configuration" (last
> paragraph), I've come up with a way to implement our customer's request
> (second last paragraph): 'configure' GCC/nvptx '--with-arch=sm_70'.
>
> I think I've implemented this in a way so that "random GCC/nvptx multilib
> configuration" may eventually be implemented on top of that.  For easy
> review/testing I've split my changes into three commits, see attached
> "nvptx: Make default '-misa=sm_30' explicit",
> "nvptx: Introduce dummy multilib option for default '-misa=sm_30'",
> "nvptx: Allow '--with-arch' to override the default '-misa'".
>
> To the best of my knowledge, the first two patches do not change any
> user-visible behavior (I generally 'diff'ed target libraries, and
> compared a good number of 'gcc -print-multi-directo

[PATCH] RISC-V: Use the X iterator for eh_set_lr_{si,di}

2022-08-06 Thread Palmer Dabbelt
These two patterns were independent, but exactly match the semantics of
X.  Replace them with a single paramaterized pattern.  Thanks to Andrew
for pointing this one out over IRC.

gcc/ChangeLog

* config/riscv/riscv.md (eh_set_lr_): New pattern.
(eh_set_lr_si): Remove.
(eh_set_lr_di): Likewise.
---
No new failures on the Linux multilibs on trunk.
---
 gcc/config/riscv/riscv.md | 14 --
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0796f91dd30..11a59f98a9f 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2562,16 +2562,10 @@
 ;; Clobber the return address on the stack.  We can't expand this
 ;; until we know where it will be put in the stack frame.
 
-(define_insn "eh_set_lr_si"
-  [(unspec [(match_operand:SI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
-   (clobber (match_scratch:SI 1 "=&r"))]
-  "! TARGET_64BIT"
-  "#")
-
-(define_insn "eh_set_lr_di"
-  [(unspec [(match_operand:DI 0 "register_operand" "r")] UNSPEC_EH_RETURN)
-   (clobber (match_scratch:DI 1 "=&r"))]
-  "TARGET_64BIT"
+(define_insn "eh_set_lr_"
+  [(unspec [(match_operand:X 0 "register_operand" "r")] UNSPEC_EH_RETURN)
+   (clobber (match_scratch:X 1 "=&r"))]
+  ""
   "#")
 
 (define_split
-- 
2.34.1



[PATCH] RISC-V: Fix the sge ..., x0, ... pattern

2022-08-06 Thread Palmer Dabbelt
There's no operand 2 here, so referencing it doesn't make sense.  I
couldn't find a way to trigger bad assembly output so I don't have a
test.

gcc/ChangeLog

PR target/106543
* config/riscv/riscv.md (sge_): Remove
reference to non-existent operand.
---
No new failures on the Linux multilibs on trunk.
---
 gcc/config/riscv/riscv.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 0796f91dd30..ed1c7f241e6 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -2386,7 +2386,7 @@
(any_ge:GPR (match_operand:X 1 "register_operand" " r")
(const_int 1)))]
   ""
-  "slt%i2\t%0,zero,%1"
+  "slt\t%0,zero,%1"
   [(set_attr "type" "slt")
(set_attr "mode" "")])
 
-- 
2.34.1



Re: [PATCH] c-family: Honor -Wno-init-self for cv-qual vars [PR102633]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 7/26/22 14:31, Marek Polacek wrote:

On Tue, Jul 26, 2022 at 04:24:18PM -0400, Jason Merrill wrote:

On 7/26/22 15:03, Marek Polacek wrote:

Since r11-5188-g32934a4f45a721, we drop qualifiers during l-to-r
conversion by creating a NOP_EXPR.  For e.g.

const int i = i;

that means that the DECL_INITIAL is '(int) i' and not 'i' anymore.
Consequently, we don't suppress_warning here:

711 case DECL_EXPR:
715   if (VAR_P (DECL_EXPR_DECL (*expr_p))
716   && !DECL_EXTERNAL (DECL_EXPR_DECL (*expr_p))
717   && !TREE_STATIC (DECL_EXPR_DECL (*expr_p))
718   && (DECL_INITIAL (DECL_EXPR_DECL (*expr_p)) == DECL_EXPR_DECL 
(*expr_p))
719   && !warn_init_self)
720 suppress_warning (DECL_EXPR_DECL (*expr_p), OPT_Winit_self);

because of the check on line 718 -- (int) i is not i.  So -Wno-init-self
doesn't disable the warning as it's supposed to.

The following patch fixes it...except it doesn't, for volatile variables
in C++.  The problem is that for

volatile int k = k;

we see that the initializer has TREE_SIDE_EFFECTS, so we perform dynamic
initialization.  So there's no DECL_INITIAL and the suppress_warning
call above is never done.  I suppose we could amend get_no_uninit_warning
to return true for volatile-qualified expressions.  I mean, can we ever
say for a fact that a volatile variable is uninitialized?

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR middle-end/102633

gcc/c-family/ChangeLog:

* c-gimplify.cc (c_gimplify_expr): Strip NOPs of DECL_INITIAL.


I wonder if we want to handle this i = i case earlier, like in finish_decl.


I could, something like

@@ -5381,7 +5381,14 @@ finish_decl (tree decl, location_t init_loc, tree init,
  init = NULL_TREE;

if (init)
-store_init_value (init_loc, decl, init, origtype);
+{
+  /* In the self-init case, undo the artificial NOP_EXPR we may have
+added in convert_lvalue_to_rvalue so that c_gimplify_expr/DECL_EXPR
+can perform suppress_warning.  */
+  if (TREE_CODE (init) == NOP_EXPR && TREE_OPERAND (init, 0) == decl)
+   init = TREE_OPERAND (init, 0);
+  store_init_value (init_loc, decl, init, origtype);
+}

but then I'd have to do the same thing in cp_finish_decl because
decay_conversion also adds a NOP_EXPR for cv-qualified non-class prvalues.
Is that what we want?  To me that seems less clean than having c_gimplify_expr
see through NOP_EXPRs.


I was thinking of checking the form of the initializer before 
decay_conversion or anything else messes with it, and calling 
suppress_warning at that point instead of in c_gimplify_expr.


Jason



Re: [PATCH] gimple, internal-fn: Add IFN_TRAP and use it for __builtin_unreachable [PR106099]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 7/27/22 03:09, Richard Biener wrote:

On Wed, 27 Jul 2022, Jakub Jelinek wrote:


On Wed, Jul 27, 2022 at 09:33:47AM +, Richard Biener wrote:

__builtin_unreachable and __ubsan_handle_builtin_unreachable don't
use vops, they are marked const/leaf/noreturn/nothrow/cold.
But __builtin_trap uses vops, isn't const, just leaf/noreturn/nothrow/cold.
This is I believe so that when users explicitly use __builtin_trap in their
sources they get stores visible at the trap side.
-fsanitize=unreachable -fsanitize-undefined-trap-on-error used to transform
__builtin_unreachable to __builtin_trap even in the past, but the sanopt pass
has TODO_update_ssa, so it worked fine.

Now that gimple_build_builtin_unreachable can build a __builtin_trap call
right away, we can run into problems that whenever we need it we would need
to either manually or through TODO_update* ensure the vops being updated.

Though, as it is originally __builtin_unreachable which is just implemented
as trap, I think for this case it is fine to avoid vops.  For this the
patch introduces IFN_TRAP, which has ECF_* flags like __builtin_unreachable
and is expanded as __builtin_trap.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


I think for the sake of sanitizing unreachable as trap this is OK
but it seems this isn't actually what is done.


We chose to sanitize not just explicit user __builtin_unreachable calls,
but also the internally generated __builtin_unreachable calls (with the
one exception of fall through to end of C++ function returning non-void,
which had before a separate sanitizer) and we've been doing it since 2013
when ubsan was added.
Even for the internally generated unreachable calls like those from
devirtualization or other reasons like ivcanon/unrolling, having the
possibility to get some runtime diagnostics or trap can be useful over
just falling through to random following code.


So at least for the unrolling use the intent is to have the
unreachable () fully elided by later passes.  Honza can correct me
if I'm wrong.  Using __builtin_trap from the start until sanopt
may prevent some of that from happening, keeping dead conditions
live, no?


Previously we'd always emit __builtin_unreachable, then perhaps in some
cases could e.g. optimize it away (say if there is a guarding condition
around the implicitly added unreachable turning the condition into VRP
info and optimizing the conditional away), otherwise the sanopt pass
would turn those __builtin_unreachable calls into __builtin_trap.
With the recent changes, we don't run the sanopt pass when only
doing -fsanitize=unreachable (or -funrechable-traps) though, so we need
to emit the trap/__ubsan_handle_unreachable/__builtin_unreachable right
away.


Why did the recent changes not just replace __builtin_unreachable
at RTL expansion time?  Was the intent really to force the paths
to be kept live?  I can see that for user or frontend generated
unreachables but not so much for some of the middle-end ones.


Yes, the intent was to force user and frontend generated unreachables to 
be kept live, particularly the one for flowing off the end of a non-void 
function.  I have also wondered if treating middle-end unreachables the 
same was a mistake.


Jason



Re: [PATCH] c++, v4: Add support for __real__/__imag__ modifications in constant expressions [PR88174]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 7/27/22 02:09, Jakub Jelinek wrote:

On Tue, Jul 05, 2022 at 04:44:41PM -0400, Jason Merrill wrote:

But preeval should always be true, so we'd never reach the new handling in
the if (!preeval) block.  Certainly the new testcase doesn't exercise this
code.


Ok, changed now.

I had to keep the ctors[i] = valp; statement in the !preeval block, because
otherwise e.g. 20_util/optional/monadic/transform.cc test fails randomly.
It was wrong already before the patch, it would adjust
TREE_CONSTANT/TREE_SIDE_EFFECTS sometimes on no longer used trees,
but with the vector holding pointers to trees rather than trees it is even
more severe.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


OK, thanks.


2022-07-27  Jakub Jelinek  

PR c++/88174
* constexpr.cc (cxx_eval_store_expression): Handle REALPART_EXPR
and IMAGPART_EXPR.  Change ctors from releasing_vec to
auto_vec, adjust all uses.  For !preeval, update ctors
vector.

* g++.dg/cpp1y/constexpr-complex1.C: New test.

--- gcc/cp/constexpr.cc.jj  2022-07-04 12:26:18.147053851 +0200
+++ gcc/cp/constexpr.cc 2022-07-26 17:35:53.100556949 +0200
@@ -5726,6 +5726,20 @@ cxx_eval_store_expression (const constex
  }
  break;
  
+	case REALPART_EXPR:

+ gcc_assert (probe == target);
+ vec_safe_push (refs, probe);
+ vec_safe_push (refs, TREE_TYPE (probe));
+ probe = TREE_OPERAND (probe, 0);
+ break;
+
+   case IMAGPART_EXPR:
+ gcc_assert (probe == target);
+ vec_safe_push (refs, probe);
+ vec_safe_push (refs, TREE_TYPE (probe));
+ probe = TREE_OPERAND (probe, 0);
+ break;
+
default:
  if (evaluated)
object = probe;
@@ -5764,7 +5778,8 @@ cxx_eval_store_expression (const constex
type = TREE_TYPE (object);
bool no_zero_init = true;
  
-  releasing_vec ctors, indexes;

+  auto_vec ctors;
+  releasing_vec indexes;
auto_vec index_pos_hints;
bool activated_union_member_p = false;
bool empty_base = false;
@@ -5804,14 +5819,36 @@ cxx_eval_store_expression (const constex
  *valp = ary_ctor;
}
  
-  /* If the value of object is already zero-initialized, any new ctors for

-subobjects will also be zero-initialized.  */
-  no_zero_init = CONSTRUCTOR_NO_CLEARING (*valp);
-
enum tree_code code = TREE_CODE (type);
tree reftype = refs->pop();
tree index = refs->pop();
  
+  if (code == COMPLEX_TYPE)

+   {
+ if (TREE_CODE (*valp) == COMPLEX_CST)
+   *valp = build2 (COMPLEX_EXPR, type, TREE_REALPART (*valp),
+   TREE_IMAGPART (*valp));
+ else if (TREE_CODE (*valp) == CONSTRUCTOR
+  && CONSTRUCTOR_NELTS (*valp) == 0
+  && CONSTRUCTOR_NO_CLEARING (*valp))
+   {
+ tree r = build_constructor (reftype, NULL);
+ CONSTRUCTOR_NO_CLEARING (r) = 1;
+ *valp = build2 (COMPLEX_EXPR, type, r, r);
+   }
+ gcc_assert (TREE_CODE (*valp) == COMPLEX_EXPR);
+ ctors.safe_push (valp);
+ vec_safe_push (indexes, index);
+ valp = &TREE_OPERAND (*valp, TREE_CODE (index) == IMAGPART_EXPR);
+ gcc_checking_assert (refs->is_empty ());
+ type = reftype;
+ break;
+   }
+
+  /* If the value of object is already zero-initialized, any new ctors for
+subobjects will also be zero-initialized.  */
+  no_zero_init = CONSTRUCTOR_NO_CLEARING (*valp);
+
if (code == RECORD_TYPE && is_empty_field (index))
/* Don't build a sub-CONSTRUCTOR for an empty base or field, as they
   have no data and might have an offset lower than previously declared
@@ -5854,7 +5891,7 @@ cxx_eval_store_expression (const constex
  no_zero_init = true;
}
  
-  vec_safe_push (ctors, *valp);

+  ctors.safe_push (valp);
vec_safe_push (indexes, index);
  
constructor_elt *cep

@@ -5916,11 +5953,11 @@ cxx_eval_store_expression (const constex
 semantics are not applied on an object under construction.
 They come into effect when the constructor for the most
 derived object ends."  */
- for (tree elt : *ctors)
+ for (tree *elt : ctors)
if (same_type_ignoring_top_level_qualifiers_p
-   (TREE_TYPE (const_object_being_modified), TREE_TYPE (elt)))
+   (TREE_TYPE (const_object_being_modified), TREE_TYPE (*elt)))
  {
-   fail = TREE_READONLY (elt);
+   fail = TREE_READONLY (*elt);
break;
  }
}
@@ -5961,6 +5998,7 @@ cxx_eval_store_expression (const constex
valp = ctx->global->values.get (object);
for (unsigned i = 0; i < vec_safe_length (indexes); i++)
{
+ ctors[i] = valp;
  constructor_elt *cep
= get_or_insert_ctor

Re: [PATCH] c++: Extend -Wpessimizing-move for class prvalues [PR106276]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 7/27/22 17:14, Marek Polacek wrote:

We already have a warning that warns about pessimizing std::move
in a return statement, when it prevents the NRVO:

   T fn()
   {
 T t;
 return std::move (t); // warning \o/
   }

However, the warning doesn't warn when what we are returning is a class
prvalue, that is, when std::move prevents the RVO:

   T fn()
   {
 T t;
 return std::move (T{}); // no warning :-(
   }

This came up recently in GCC:
.

This patch fixes that.  I would like to extend the warning further, so
that it warns in more contexts, e.g.:

   T t = std::move(T());

or

   void foo (T);
   foo (std::move(T()));

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/106276

gcc/cp/ChangeLog:

* typeck.cc (can_do_rvo_p): New.
(maybe_warn_pessimizing_move): Warn when moving a temporary object
in a return statement prevents copy elision.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wpessimizing-move7.C: New test.
---
  gcc/cp/typeck.cc  | 31 -
  .../g++.dg/cpp0x/Wpessimizing-move7.C | 63 +++
  2 files changed, 91 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6e4f23af982..9500c4e2fe8 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10287,12 +10287,29 @@ can_do_nrvo_p (tree retval, tree functype)
  /* The cv-unqualified type of the returned value must be the
 same as the cv-unqualified return type of the
 function.  */
- && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
- (TYPE_MAIN_VARIANT (functype)))
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+ TYPE_MAIN_VARIANT (functype))
  /* And the returned value must be non-volatile.  */
  && !TYPE_VOLATILE (TREE_TYPE (retval)));
  }
  
+/* Like can_do_nrvo_p, but we check if we're trying to move a class

+   prvalue.  */
+
+static bool
+can_do_rvo_p (tree retval, tree functype)
+{
+  if (functype == error_mark_node)
+return false;
+  if (retval)
+STRIP_ANY_LOCATION_WRAPPER (retval);
+  return (retval != NULL_TREE
+ && TREE_CODE (retval) == TARGET_EXPR


Maybe use !glvalue_p instead of specifically checking for TARGET_EXPR? 
I don't feel strongly about this.



+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+ TYPE_MAIN_VARIANT (functype))
+ && !TYPE_VOLATILE (TREE_TYPE (retval)));
+}
+
  /* If we should treat RETVAL, an expression being returned, as if it were
 designated by an rvalue, returns it adjusted accordingly; otherwise, 
returns
 NULL_TREE.  See [class.copy.elision].  RETURN_P is true if this is a return
@@ -10401,12 +10418,20 @@ maybe_warn_pessimizing_move (tree retval, tree 
functype)
  "prevents copy elision"))
inform (loc, "remove % call");
}
+ else if (can_do_rvo_p (arg, functype))
+   {
+ auto_diagnostic_group d;
+ if (warning_at (loc, OPT_Wpessimizing_move,
+ "moving a temporary object in a return statement "
+ "prevents copy elision"))


It doesn't just prevent copy elision, it produces a dangling reference. 
 This is a special case of the warning we talked about passing a 
temporary to a function that returns a reference argument unchanged, and 
should probably use a different warning flag.



+   inform (loc, "remove % call");
+   }
  /* Warn if the move is redundant.  It is redundant when we would
 do maybe-rvalue overload resolution even without std::move.  */
  else if (warn_redundant_move
   && (moved = treat_lvalue_as_rvalue_p (arg, /*return*/true)))
{
- /* Make sure that the overload resolution would actually succeed
+ /* Make sure that overload resolution would actually succeed
 if we removed the std::move call.  */
  tree t = convert_for_initialization (NULL_TREE, functype,
   moved,
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C 
b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C
new file mode 100644
index 000..cd4eaa09aae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C
@@ -0,0 +1,63 @@
+// PR c++/106276
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+  template
+struct remove_reference
+{ typedef _Tp   type; };
+
+  template
+struct remove_reference<_Tp&>
+{ typedef _Tp   type; };
+
+  template
+struct remove_reference<_Tp&&>
+{ typedef _Tp   type; };
+
+  templa

Re: [PATCH] c++: Tweak for -Wpessimizing-move in templates [PR89780]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 8/4/22 11:46, Marek Polacek wrote:

In my previous patches I've been extending our std::move warnings,
but this tweak actually dials it down a little bit.  As reported in
bug 89780, it's questionable to warn about expressions in templates
that were type-dependent, but aren't anymore because we're instantiating
the template.  As in,

   template 
   Dest withMove() {
 T x;
 return std::move(x);
   }

   template Dest withMove(); // #1
   template Dest withMove(); // #2

Saying that the std::move is pessimizing for #1 is not incorrect, but
it's not useful, because removing the std::move would then pessimize #2.
So the user can't really win.  At the same time, disabling the warning
just because we're in a template would be going too far, I still want to
warn for

   template 
   Dest withMove() {
 Dest x;
 return std::move(x);
   }

because the std::move therein will be pessimizing for any instantiation.

So I'm using the suppress_warning machinery to that effect.
Problem: I had to add a new group to nowarn_spec_t, otherwise
suppressing the -Wpessimizing-move warning would disable a whole bunch
of other warnings, which we really don't want.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/89780

gcc/cp/ChangeLog:

* pt.cc (tsubst_copy_and_build) : Maybe suppress
-Wpessimizing-move.
* typeck.cc (maybe_warn_pessimizing_move): Don't issue warnings
if they are suppressed.
(check_return_expr): Disable -Wpessimizing-move when returning
a dependent expression.

gcc/ChangeLog:

* diagnostic-spec.cc (nowarn_spec_t::nowarn_spec_t): Handle
OPT_Wpessimizing_move and OPT_Wredundant_move.
* diagnostic-spec.h (nowarn_spec_t): Add NW_REDUNDANT enumerator.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wpessimizing-move3.C: Remove dg-warning.
* g++.dg/cpp0x/Wpessimizing-move7.C: Likewise.
* g++.dg/cpp0x/Wredundant-move2.C: Likewise.
* g++.dg/cpp0x/Wpessimizing-move9.C: New test.
---
  gcc/cp/pt.cc  |  3 +
  gcc/cp/typeck.cc  | 20 +++--
  gcc/diagnostic-spec.cc|  7 +-
  gcc/diagnostic-spec.h |  4 +-
  .../g++.dg/cpp0x/Wpessimizing-move3.C |  2 +-
  .../g++.dg/cpp0x/Wpessimizing-move7.C |  2 +-
  .../g++.dg/cpp0x/Wpessimizing-move9.C | 89 +++
  gcc/testsuite/g++.dg/cpp0x/Wredundant-move2.C |  4 +-
  8 files changed, 119 insertions(+), 12 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move9.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 6c581fe0fb7..fe7e809fc2d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21215,6 +21215,9 @@ tsubst_copy_and_build (tree t,
  CALL_EXPR_ORDERED_ARGS (call) = ord;
  CALL_EXPR_REVERSE_ARGS (call) = rev;
}
+   if (warning_suppressed_p (t, OPT_Wpessimizing_move))
+ /* This also suppresses -Wredundant-move.  */
+ suppress_warning (ret, OPT_Wpessimizing_move);
  }
  
  	RETURN (ret);

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 2650beb780e..70a5efc45de 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10430,9 +10430,10 @@ maybe_warn_pessimizing_move (tree expr, tree type, 
bool return_p)
  if (can_do_rvo_p (arg, type))
{
  auto_diagnostic_group d;
- if (warning_at (loc, OPT_Wpessimizing_move,
- "moving a temporary object prevents copy "
- "elision"))
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)


I don't think we ever want to suppress this warning; moving it to a 
different warning flag (as I suggested on the other patch) would 
accomplish that.



+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a temporary object prevents copy "
+"elision"))
inform (loc, "remove % call");
}
  /* The rest of the warnings is only relevant for when we are
@@ -10443,14 +10444,16 @@ maybe_warn_pessimizing_move (tree expr, tree type, 
bool return_p)
  else if (can_do_nrvo_p (arg, type))
{
  auto_diagnostic_group d;
- if (warning_at (loc, OPT_Wpessimizing_move,
- "moving a local object in a return statement "
- "prevents copy elision"))
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a local object in a return statement "
+"prevents copy elision"))
inform (loc, "remove % call");
}
  /* Warn if the move is redundant.  It is redundant when we would
 do maybe-rv

Re: [PATCH] c++: Extend -Wpessimizing-move for class prvalues [PR106276]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 8/6/22 15:49, Jason Merrill wrote:

On 7/27/22 17:14, Marek Polacek wrote:

We already have a warning that warns about pessimizing std::move
in a return statement, when it prevents the NRVO:

   T fn()
   {
 T t;
 return std::move (t); // warning \o/
   }

However, the warning doesn't warn when what we are returning is a class
prvalue, that is, when std::move prevents the RVO:

   T fn()
   {
 T t;
 return std::move (T{}); // no warning :-(
   }

This came up recently in GCC:
.

This patch fixes that.  I would like to extend the warning further, so
that it warns in more contexts, e.g.:

   T t = std::move(T());

or

   void foo (T);
   foo (std::move(T()));

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/106276

gcc/cp/ChangeLog:

* typeck.cc (can_do_rvo_p): New.
(maybe_warn_pessimizing_move): Warn when moving a temporary object
in a return statement prevents copy elision.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wpessimizing-move7.C: New test.
---
  gcc/cp/typeck.cc  | 31 -
  .../g++.dg/cpp0x/Wpessimizing-move7.C | 63 +++
  2 files changed, 91 insertions(+), 3 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 6e4f23af982..9500c4e2fe8 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10287,12 +10287,29 @@ can_do_nrvo_p (tree retval, tree functype)
    /* The cv-unqualified type of the returned value must be the
   same as the cv-unqualified return type of the
   function.  */
-  && same_type_p ((TYPE_MAIN_VARIANT (TREE_TYPE (retval))),
-  (TYPE_MAIN_VARIANT (functype)))
+  && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+  TYPE_MAIN_VARIANT (functype))
    /* And the returned value must be non-volatile.  */
    && !TYPE_VOLATILE (TREE_TYPE (retval)));
  }
+/* Like can_do_nrvo_p, but we check if we're trying to move a class
+   prvalue.  */
+
+static bool
+can_do_rvo_p (tree retval, tree functype)
+{
+  if (functype == error_mark_node)
+    return false;
+  if (retval)
+    STRIP_ANY_LOCATION_WRAPPER (retval);
+  return (retval != NULL_TREE
+  && TREE_CODE (retval) == TARGET_EXPR


Maybe use !glvalue_p instead of specifically checking for TARGET_EXPR? I 
don't feel strongly about this.



+  && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (retval)),
+  TYPE_MAIN_VARIANT (functype))
+  && !TYPE_VOLATILE (TREE_TYPE (retval)));
+}
+
  /* If we should treat RETVAL, an expression being returned, as if it 
were
 designated by an rvalue, returns it adjusted accordingly; 
otherwise, returns
 NULL_TREE.  See [class.copy.elision].  RETURN_P is true if this 
is a return
@@ -10401,12 +10418,20 @@ maybe_warn_pessimizing_move (tree retval, 
tree functype)

    "prevents copy elision"))
  inform (loc, "remove % call");
  }
+  else if (can_do_rvo_p (arg, functype))
+    {
+  auto_diagnostic_group d;
+  if (warning_at (loc, OPT_Wpessimizing_move,
+  "moving a temporary object in a return statement "
+  "prevents copy elision"))


It doesn't just prevent copy elision, it produces a dangling reference. 
  This is a special case of the warning we talked about passing a 
temporary to a function that returns a reference argument unchanged, and 
should probably use a different warning flag.


Wait, no, I'm confused, the temporary does live long enough to get copied.

I still don't think we want to suppress this warning in the other patch.


+    inform (loc, "remove % call");
+    }
    /* Warn if the move is redundant.  It is redundant when we would
   do maybe-rvalue overload resolution even without 
std::move.  */

    else if (warn_redundant_move
 && (moved = treat_lvalue_as_rvalue_p (arg, /*return*/true)))
  {
-  /* Make sure that the overload resolution would actually 
succeed

+  /* Make sure that overload resolution would actually succeed
   if we removed the std::move call.  */
    tree t = convert_for_initialization (NULL_TREE, functype,
 moved,
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C 
b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C

new file mode 100644
index 000..cd4eaa09aae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move7.C
@@ -0,0 +1,63 @@
+// PR c++/106276
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+  template
+    struct remove_reference
+    { typedef _Tp   type; };
+
+  template
+    struct remove_reference<_Tp&>
+    { typedef _Tp   type; };
+
+  template
+    struct remove_reference<_Tp&&>
+    { typedef _Tp   type; };
+
+  te

Re: [PATCH] c++: Extend -Wredundant-move for const-qual objects [PR90428]

2022-08-06 Thread Jason Merrill via Gcc-patches

On 8/6/22 11:13, Marek Polacek wrote:

In this PR, Jon suggested extending the -Wredundant-move warning
to warn when the user is moving a const object as in:

   struct T { };

   T f(const T& t)
   {
 return std::move(t);
   }

where the std::move is redundant, because T does not have
a T(const T&&) constructor (which is very unlikely).  Even with
the std::move, T(T&&) would not be used because it would mean
losing the const.  Instead, T(const T&) will be called.

I had to restructure the function a bit, but it's better now.  This patch
depends on my other recent patches to maybe_warn_pessimizing_move.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

PR c++/90428

gcc/cp/ChangeLog:

* typeck.cc (maybe_warn_pessimizing_move): Extend the
-Wredundant-move warning to warn about std::move on a
const-qualified object.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/Wredundant-move1.C: Adjust dg-warning.
* g++.dg/cpp0x/Wredundant-move9.C: Likewise.
* g++.dg/cpp0x/Wredundant-move10.C: New test.
---
  gcc/cp/typeck.cc  | 157 +++---
  gcc/testsuite/g++.dg/cpp0x/Wredundant-move1.C |   3 +-
  .../g++.dg/cpp0x/Wredundant-move10.C  |  61 +++
  gcc/testsuite/g++.dg/cpp0x/Wredundant-move9.C |   3 +-
  4 files changed, 162 insertions(+), 62 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/Wredundant-move10.C

diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 70a5efc45de..802bc9c43fb 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -10411,72 +10411,109 @@ maybe_warn_pessimizing_move (tree expr, tree type, 
bool return_p)
return;
  }
  
-  /* We're looking for *std::move ((T &) &arg).  */

-  if (REFERENCE_REF_P (expr)
-  && TREE_CODE (TREE_OPERAND (expr, 0)) == CALL_EXPR)
-{
-  tree fn = TREE_OPERAND (expr, 0);
-  if (is_std_move_p (fn))
-   {
- tree arg = CALL_EXPR_ARG (fn, 0);
- tree moved;
- if (TREE_CODE (arg) != NOP_EXPR)
-   return;
- arg = TREE_OPERAND (arg, 0);
- if (TREE_CODE (arg) != ADDR_EXPR)
-   return;
- arg = TREE_OPERAND (arg, 0);
- arg = convert_from_reference (arg);
- if (can_do_rvo_p (arg, type))
-   {
- auto_diagnostic_group d;
- if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
- && warning_at (loc, OPT_Wpessimizing_move,
-"moving a temporary object prevents copy "
-"elision"))
-   inform (loc, "remove % call");
-   }
- /* The rest of the warnings is only relevant for when we are
-returning from a function.  */
- else if (!return_p)
-   return;
- /* Warn if we could do copy elision were it not for the move.  */
- else if (can_do_nrvo_p (arg, type))
+  /* First, check if this is a call to std::move.  */
+  if (!REFERENCE_REF_P (expr)
+  || TREE_CODE (TREE_OPERAND (expr, 0)) != CALL_EXPR)
+return;
+  tree fn = TREE_OPERAND (expr, 0);
+  if (!is_std_move_p (fn))
+return;
+  tree arg = CALL_EXPR_ARG (fn, 0);
+  if (TREE_CODE (arg) != NOP_EXPR)
+return;
+  /* If we're looking at *std::move ((T &) &arg), do the pessimizing N/RVO
+ and implicitly-movable warnings.  */
+  if (TREE_CODE (TREE_OPERAND (arg, 0)) == ADDR_EXPR)
+{
+  arg = TREE_OPERAND (arg, 0);
+  arg = TREE_OPERAND (arg, 0);
+  arg = convert_from_reference (arg);
+  if (can_do_rvo_p (arg, type))


Incidentally, this function should probably have a different name if 
we're checking it in non-return situations.



+   {
+ auto_diagnostic_group d;
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a temporary object prevents copy elision"))
+   inform (loc, "remove % call");
+   }
+  /* The rest of the warnings is only relevant for when we are returning
+from a function.  */
+  if (!return_p)
+   return;
+
+  tree moved;
+  /* Warn if we could do copy elision were it not for the move.  */
+  if (can_do_nrvo_p (arg, type))
+   {
+ auto_diagnostic_group d;
+ if (!warning_suppressed_p (expr, OPT_Wpessimizing_move)
+ && warning_at (loc, OPT_Wpessimizing_move,
+"moving a local object in a return statement "
+"prevents copy elision"))
+   inform (loc, "remove % call");
+   }
+  /* Warn if the move is redundant.  It is redundant when we would
+do maybe-rvalue overload resolution even without std::move.  */
+  else if (warn_redundant_move
+  && !warning_suppressed_p (expr, OPT_Wredundant_move)
+  && (moved = treat_lvalue_as_rvalue_p (arg, /*return*/true)))
+   {
+ /* M