]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++: compile time evaluation of prvalues [PR116416]
authorMarek Polacek <polacek@redhat.com>
Thu, 29 Aug 2024 16:58:41 +0000 (12:58 -0400)
committerMarek Polacek <polacek@redhat.com>
Mon, 9 Dec 2024 17:13:42 +0000 (12:13 -0500)
commit12de1942a0a673f9f2f1c2bfce4279a666061ffc
tree803912afbcb253dfa5bc62b142f13685792ab343
parent0c83096f19b075ac1b80113828188a0fd64400af
c++: compile time evaluation of prvalues [PR116416]

This PR reports a missed optimization.  When we have:

  Str str{"Test"};
  callback(str);

as in the test, we're able to evaluate the Str::Str() call at compile
time.  But when we have:

  callback(Str{"Test"});

we are not.  With this patch (in fact, it's Patrick's patch with a little
tweak), we turn

  callback (TARGET_EXPR <D.2890, <<< Unknown tree: aggr_init_expr
    5
    __ct_comp
    D.2890
    (struct Str *) <<< Unknown tree: void_cst >>>
    (const char *) "Test" >>>>)

into

  callback (TARGET_EXPR <D.2890, {.str=(const char *) "Test", .length=4}>)

I explored the idea of calling maybe_constant_value for the whole
TARGET_EXPR in cp_fold.  That has three problems:
- we can't always elide a TARGET_EXPR, so we'd have to make sure the
  result is also a TARGET_EXPR;
- the resulting TARGET_EXPR must have the same flags, otherwise Bad
  Things happen;
- getting a new slot is also problematic.  I've seen a test where we
  had "TARGET_EXPR<D.2680, ...>, D.2680", and folding the whole TARGET_EXPR
  would get us "TARGET_EXPR<D.2681, ...>", but since we don't see the outer
  D.2680, we can't replace it with D.2681, and things break.

With this patch, two tree-ssa tests regressed: pr78687.C and pr90883.C.

FAIL: g++.dg/tree-ssa/pr90883.C   scan-tree-dump dse1 "Deleted redundant store: .*.a = {}"
is easy.  Previously, we would call C::C, so .gimple has:

  D.2590 = {};
  C::C (&D.2590);
  D.2597 = D.2590;
  return D.2597;

Then .einline inlines the C::C call:

  D.2590 = {};
  D.2590.a = {}; // #1
  D.2590.b = 0;  // #2
  D.2597 = D.2590;
  D.2590 ={v} {CLOBBER(eos)};
  return D.2597;

then #2 is removed in .fre1, and #1 is removed in .dse1.  So the test
passes.  But with the patch, .gimple won't have that C::C call, so the
IL is of course going to look different.  The .optimized dump looks the
same though so there's no problem.

pr78687.C is XFAILed because the test passes with r15-5746 but not with
r15-5747 as well.  I opened <https://gcc.gnu.org/PR117971>.

PR c++/116416

gcc/cp/ChangeLog:

* cp-gimplify.cc (cp_fold_r) <case TARGET_EXPR>: Try to fold
TARGET_EXPR_INITIAL and replace it with the folded result if
it's TREE_CONSTANT.

gcc/testsuite/ChangeLog:

* g++.dg/analyzer/pr97116.C: Adjust dg-message.
* g++.dg/tree-ssa/pr78687.C: Add XFAIL.
* g++.dg/tree-ssa/pr90883.C: Adjust dg-final.
* g++.dg/cpp0x/constexpr-prvalue1.C: New test.
* g++.dg/cpp1y/constexpr-prvalue1.C: New test.

Co-authored-by: Patrick Palka <ppalka@redhat.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/cp-gimplify.cc
gcc/testsuite/g++.dg/analyzer/pr97116.C
gcc/testsuite/g++.dg/cpp0x/constexpr-prvalue1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/tree-ssa/pr78687.C
gcc/testsuite/g++.dg/tree-ssa/pr90883.C