From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id D9CBC3858408; Tue, 28 Sep 2021 07:36:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org D9CBC3858408 From: "aldyh at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug tree-optimization/102511] [12 Regression] GCC produces incorrect code for -O3: first element of the array is skipped after r12-3903 Date: Tue, 28 Sep 2021 07:36:26 +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: 12.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: blocker X-Bugzilla-Who: aldyh at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P1 X-Bugzilla-Assigned-To: aldyh at gcc dot gnu.org X-Bugzilla-Target-Milestone: 12.0 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: priority assigned_to 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 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Sep 2021 07:36:27 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D102511 Aldy Hernandez changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P3 |P1 Assignee|unassigned at gcc dot gnu.org |aldyh at gcc dot gn= u.org --- Comment #6 from Aldy Hernandez --- [Bumping this up to a P1.] The problem here is that we're incorrectly threading a path in the vrp-thre= ad2 pass. As there is only one registered thread in the dump file (-fdump-tree-vrp-thread2-details), it's easy to find the culprit: Registering jump thread: (2, 6) incoming edge; (6, 5) normal; With a little bisecting, we can find the exact path as its being registered: $ ./xgcc -B./ -O3 a.c -fdbg-cnt=3Dregistered_jump_thread:10,10 && ./a.out ***dbgcnt: lower limit 1 reached for registered_jump_thread.*** ***dbgcnt: upper limit 10 reached for registered_jump_thread.*** Aborted (core dumped) That is, the 10th attempt at registering a path. If we turn on debugging in the solver (DEBUG_SOLVER in gimple-range-path.cc= ), we can see the solver as it precomputes the SSAs along the path. Basically= , we find the dbg counter and look at the dump prior to that: ***dbgcnt: upper limit 10 reached for registered_jump_thread.*** Registering jump thread: (2, 6) incoming edge; (6, 5) normal;=20 Immediately before this, we see the solver output: *********** path_range_query ****************** Registering value_relation (path_oracle) (ivtmp.21_14 =3D=3D ivtmp.21_32) = (bb2) path_range_query: compute_ranges for path: BB 2, BB 6 range_defined_in_block (BB2) for iftmp.1_11 is short unsigned int [0, 0][12= 2, 122] range_defined_in_block (BB2) for _8 is long long unsigned int [0, 0] range_defined_in_block (BB2) for iftmp.2_12 is short unsigned int [0, 0] range_defined_in_block (BB2) for _5 is short unsigned int [0, 0][122, 122] range_defined_in_block (BB2) for _6 is int [0, 0][122, 122] Registering value_relation (path_oracle) (_7 < _6) (bb2) range_defined_in_block (BB2) for _7 is int [-64055, -64055][-63933, -63933] range_defined_in_block (BB2) for iftmp.1_11 is short unsigned int [0, 0][12= 2, 122] Path is (length=3D2): =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D BB 2 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D b_15(D) short unsigned int VARYING c_20(D) long long unsigned int VARYING Equivalence set : [_36] Relational : (_7 < _6) Relational : (d_16 < _1) [local count: 29527901]: _1 =3D (int) b_15(D); d_16 =3D _1 + -8; iftmp.1_11 =3D f_18(D) !=3D 0 ? 122 : 0; _8 =3D a_19(D) !=3D 0 ? c_20(D) : 0; iftmp.2_12 =3D (short unsigned int) _8; _5 =3D iftmp.1_11 ^ iftmp.2_12; _6 =3D (int) _5; _7 =3D _6 + -64055; ivtmp.21_14 =3D (sizetype) d_16; _36 =3D (sizetype) b_15(D); goto ; [100.00%] _1 : int [0, 65535] _6 : int [0, 65535] _7 : int [-64055, 1480] iftmp.1_11 : short unsigned int [0, 0][122, 122] ivtmp.21_14 : sizetype [0, 65527][18446744073709551608, +INF] d_16 : int [-8, 65527] _36 : sizetype [0, 65535] =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D BB 6 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D Imports: _7 iftmp.1_11 c_20(D)=20=20 Exports: _5 _6 _7 _8 iftmp.1_11 iftmp.2_12 c_20(D)=20=20 _7 int [-64055, 1480] _36 sizetype [0, 65535] [local count: 118111600]: # ivtmp.21_32 =3D PHI if (_7 > 0) goto ; [89.00%] else goto ; [11.00%] 6->8 (T) _7 : int [1, 1480] 6->5 (F) _7 : int [-64055, 0] The problematic thread is out of BB6, so the threader thinks it knows enough about _7 to solve _7 > 0. Chasing back the definition of _7 we end up in _= 8, which the solver incorrectly thinks is 0: range_defined_in_block (BB2) for _8 is long long unsigned int [0, 0] If we assume _8 is 0, shit rolls downhill from here. Describing the process to get here makes it abundantly clear that we need to improve the process of debugging this. We need a way to turn on the solver debugging from the command line (--param??), and not by some magic #define.= =20 Also, some counter that matches the path being registered with the equivale= nt solver dump would be useful. This way someone could easily find the problematic thread in the solver dump. I'll look into this. Anywhoo... The issue here is that range_on_path_entry is incorrectly returning UNDEFIN= ED if it can't find any incoming edges (excluding the entry block). In this c= ase BB2's only predecessor is the entry block, so we return UNDEFINED by mistak= e.=20 UNDEFINED means unreachable, so things go very badly, very quickly. Here is a proposed patch I will test: diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index 71e04e4deba..9da67d2a35b 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -136,14 +136,23 @@ path_range_query::range_on_path_entry (irange &r, tree name) { int_range_max tmp; basic_block entry =3D entry_bb (); + bool changed =3D false; + r.set_undefined (); for (unsigned i =3D 0; i < EDGE_COUNT (entry->preds); ++i) { edge e =3D EDGE_PRED (entry, i); if (e->src !=3D ENTRY_BLOCK_PTR_FOR_FN (cfun) && m_ranger.range_on_edge (tmp, e, name)) - r.union_ (tmp); + { + r.union_ (tmp); + changed =3D true; + } } + + // Make sure we don't return UNDEFINED by mistake. + if (!changed) + r.set_varying (TREE_TYPE (name)); } // Return the range of NAME at the end of the path being analyzed.=