From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26442 invoked by alias); 26 Jul 2005 11:43:46 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 26087 invoked by uid 48); 26 Jul 2005 11:43:40 -0000 Date: Tue, 26 Jul 2005 11:57:00 -0000 Message-ID: <20050726114340.26086.qmail@sourceware.org> From: "steven at gcc dot gnu dot org" To: gcc-bugs@gcc.gnu.org In-Reply-To: <20050721155650.22591.Simon.Finn@reify.co.uk> References: <20050721155650.22591.Simon.Finn@reify.co.uk> Reply-To: gcc-bugzilla@gcc.gnu.org Subject: [Bug tree-optimization/22591] [4.0/4.1 Regression] std::swap() followed by list::erase() produces incorrect list::begin() X-Bugzilla-Reason: CC X-SW-Source: 2005-07/txt/msg03328.txt.bz2 List-Id: ------- Additional Comments From steven at gcc dot gnu dot org 2005-07-26 11:43 ------- Smaller test case: ====================================================== void abort (); typedef struct _Node { struct _Node *next, *prev; } Node; inline void swap (Node ** a, Node ** b) { Node *tmp = *a; *a = *b; *b = tmp; } /* Miscompilation seems to happen here. If one removes the if condition (which should be true) the program works fine. */ void ListSwap (Node * x, Node * y) { Node *tmp; if (x->next) { swap (&x->next, &y->next); x->next->prev = x->prev->next = x; } } ====================================================== Gives this .vars dump: ====================================================== ListSwap (x, y) { struct Node * * a; struct Node * * b; struct Node * tmp; struct _Node * D.1610; : D.1610 = x->next; if (D.1610 != 0B) goto ; else goto ; :; a = &x->next; b = &y->next; tmp = *a; *a = *b; *b = tmp; x->prev->next = x; D.1610->prev = x; :; return; } ====================================================== In the .t22.ccp dump the function still looks OK: D.1610_10 = x_1->next; D.1613_11 = x_1->prev; D.1613_11->next = x_1; D.1614_12 = D.1613_11->next; D.1610_10->prev = D.1614_12; Then .t23.fre causes the problem because the wrong alias info is wrong: D.1610_10 = D.1610_2; D.1613_11 = x_1->prev; D.1613_11->next = x_1; D.1614_12 = D.1613_11->next; D.1610_10->prev = D.1614_12; Note btw how FRE does not replace "D.1614_12" with x_1, which is a missed optimization. The alias info is already wrong when it is computed, so at least it is not some kind of weird updating problem: ListSwap (xD.1605, yD.1606) { struct NodeD.1598 * * aD.1660; struct NodeD.1598 * * bD.1661; struct NodeD.1598 * tmpD.1662; struct NodeD.1598 * D.1663; struct NodeD.1598 * tmpD.1609; struct _Node * D.1614; struct _Node * D.1613; struct _Node * * D.1612; struct _Node * * D.1611; struct _Node * D.1610; # BLOCK 0 # PRED: ENTRY (fallthru) # VUSE ; D.1610_2 = xD.1605_1->nextD.1596; if (D.1610_2 != 0B) goto ; else goto ; # SUCC: 1 (true) 2 (false) # BLOCK 1 # PRED: 0 (true) :; D.1611_4 = &yD.1606_3->nextD.1596; D.1612_5 = &xD.1605_1->nextD.1596; aD.1660_6 = (struct NodeD.1598 * *) D.1612_5; bD.1661_7 = (struct NodeD.1598 * *) D.1611_4; # VUSE ; tmpD.1662_8 = *aD.1660_6; # VUSE ; D.1663_9 = *bD.1661_7; # TMT.32D.1670_15 = V_MAY_DEF ; *aD.1660_6 = D.1663_9; # TMT.32D.1670_16 = V_MAY_DEF ; *bD.1661_7 = tmpD.1662_8; # VUSE ; D.1610_10 = xD.1605_1->nextD.1596; # VUSE ; D.1613_11 = xD.1605_1->prevD.1597; # TMT.31D.1669_17 = V_MAY_DEF ; D.1613_11->nextD.1596 = xD.1605_1; # VUSE ; D.1614_12 = D.1613_11->nextD.1596; # TMT.31D.1669_18 = V_MAY_DEF ; D.1610_10->prevD.1597 = D.1614_12; # SUCC: 2 (fallthru) # BLOCK 2 # PRED: 0 (false) 1 (fallthru) :; return; # SUCC: EXIT } Notice that the stores to *a and *b are not killing TMT.31D.1669_13. That is wrong. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=22591