From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 54FD93858C60; Mon, 16 Jan 2023 20:30:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 54FD93858C60 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1673901001; bh=lrXQBV0MSw/vxGyBp9q+Q4yUMQK5hn0GNNSb/ooIHeg=; h=From:To:Subject:Date:In-Reply-To:References:From; b=SzmK80otyPVIBLyxuRy9vZT+KSHhdJX5e3A8YFnRAx5vM7Onk3oRvgWyYdZozfb5m QrlVymudhvqrQpRhgc2fvv8DuLD/DIWXLTTi2FLLIoaSofRVksNh/HnUdmBqHOWpqg +T/1CMi763lrnVoceSIgfJoRMavDEDgXPqbmNlj0= From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/105769] [11/12/13 Regression] program segmentation fault with -ftree-vectorize and nested lambdas Date: Mon, 16 Jan 2023 20:30:00 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: tree-optimization X-Bugzilla-Version: 11.2.1 X-Bugzilla-Keywords: needs-bisection, wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 11.4 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: cc Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D105769 Jakub Jelinek changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |jakub at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- At least when using g++ 12.1.1 (20220507), the crash is because the stack slot holding return value from jacknife is clobbered on the bias =3D est(map); line. I see in main (well, print_cov_ratio and std::function inlined into it): 0x00000000004016d1 : lea 0x50(%rsp),%rsi 0x00000000004016d6 : lea 0x30(%rsp),%rdi =3D> 0x00000000004016db : call *0x48(%rsp) 0x00000000004016df : jmp 0x401742 where 0x30(%rsp) seems to be the est argument to jacknife (32 byte est_t) a= nd 0x50(%rsp) the return value from jacknife (32 byte est_t) (gdb) p/x $rsp+0x50 $49 =3D 0x7fffffffdd20 where the indirect call calls: #0 std::_Function_handler), jacknife<2ul, ab>(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}>::_M_invoke(std::_Any_data const&, std::function&&) ( __functor=3D..., __args#0=3D...) at /usr/include/c++/12/bits/std_functi= on.h:288 #1 0x00000000004016df in std::function)>::operator()(std::function) const (__args#0=3D...,=20 this=3D0x7fffffffdd00) at /usr/include/c++/12/bits/std_function.h:591 #2 print_cov_ratio () at /usr/src/gcc/obj/gcc/pr105769.C:85 #3 main () at /usr/src/gcc/obj/gcc/pr105769.C:121 But later in #0 0x00000000004014f3 in jacknife<2ul, ab>(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}::operator()(std::function) const (map=3D..., __closure=3D0x4172c0) at /usr/src/gcc/obj/gcc/pr105769.C:59 #1 std::__invoke_impl(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}&, std::function >(std::__invoke_other, jacknife<2ul, ab>(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}&, std::function&&) (__f=3D...) at /usr/include/c++/12/bits/invoke.h:61 #2 std::__invoke_r(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}&, std::function >(jacknife<2ul, ab>(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}&, std::function&&) (__fn=3D...) at /usr/include/c++/12/bits/invoke.h:111 #3 std::_Function_handler), jacknife<2ul, ab>(std::function (std::function)>, vec<2ul, vec<2ul, ab> >&, vec<2ul, ab>&)::{lambda(std::function)#1}>::_M_invoke(std::_Any_data const&, std::function&&) ( __functor=3D..., __args#0=3D...) at /usr/include/c++/12/bits/std_functi= on.h:290 #4 0x00000000004016df in std::function)>::operator()(std::function) const (__args#0=3D...,=20 this=3D0x7fffffffdd00) at /usr/include/c++/12/bits/std_function.h:591 #5 print_cov_ratio () at /usr/src/gcc/obj/gcc/pr105769.C:85 #6 main () at /usr/src/gcc/obj/gcc/pr105769.C:121 &bias is equal to the address of the jacknife return value: $50 =3D (vec<2, ab> *) 0x7fffffffdd20 To make the dumps more readable, I've patched the testcase: --- pr105769.C~ 2023-01-16 19:05:01.000000000 +0100 +++ pr105769.C 2023-01-16 20:38:25.101524077 +0100 @@ -40,7 +40,7 @@ using sq_mat =3D mat; using map_t =3D std::function; template -using est_t =3D std::function; +using est_t =3D std::function; template using e= st2_t =3D std::function; map_t id_map() { return [](size_t j) -> size_t { @@ -50,7 +50,7 @@ map_t id_map() { template -est_t jacknife(const est_t> est, +est2_t jacknife(const est_t> est, sq_mat& cov, vec& bias) { return [est, &cov, &bias]( and with that in the *.gimple dump I see: void print_cov_ratio () [pr105769.C:88:1] { struct est2_t D.85904; struct est_t D.85869; struct ._anon_95 D.85344; struct map_t D.85939; struct sq_mat cov_jn; struct vec bias; typedef struct ._anon_95 ._anon_95; try { [pr105769.C:73:16] vec<2, vec<2, ab> >::vec ([pr105769.C:73:16] &cov_= jn); [pr105769.C:74:13] vec<2, ab>::vec ([pr105769.C:74:13] &bias); [pr105769.C:85:23] try { try { try { [pr105769.C:85:23] std::function(std::function)>::function():: > ([pr105769.C:85 try { [pr105769.C:85:23] D.85904 =3D jacknife<2, ab> ([pr105769.C:85:23] &D.85869, [pr105769.C:85:10] &cov_jn, [pr105769.C:85:18] &bias); [return slot optimization] try { try { [pr105769.C:85:23] D.85939 =3D id_map (); [re= turn slot optimization] try { [pr105769.C:85:23] std::function)>::operator() ([pr105769.C:85:23] &D.85904, [pr105769.C:85 } finally { [pr105769.C:85:23] std::function::~function ([pr105769.C:85:23] &D.85939); } } finally { [pr105769.C:85:23] D.85939 =3D {CLOBBER(eol)}; } } finally { [pr105769.C:85:23] std::function)>::~function ([pr105769.C:85:23] &D.85904); } } finally { [pr105769.C:85:23] std::function(std::function)>::~function ([pr105769.C:85:23] &D.85869); } } finally { [pr105769.C:77:7] D.85344 =3D {CLOBBER(eol)}; } } finally { [pr105769.C:85:23] D.85869 =3D {CLOBBER(eol)}; } } finally { [pr105769.C:85:23] D.85904 =3D {CLOBBER(eol)}; } } finally { cov_jn =3D {CLOBBER(eol)}; bias =3D {CLOBBER(eol)}; } } D.85904 above is the return value (est2_t), D.85869 is the est argument, and bias variable is actually constructed even before this, all have 32 bytes in size. So, to me this looks like incorrect stack slot reuse.=