This fixes PR52772 - prev_bb does not have any relation to the new pre-landing-pad block (not sure what I was thinking here), so this moves the loop updating code to the place where we connect the new block into the CFG.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk. Richard. 2012-03-30 Richard Guenther <rguent...@suse.de> PR middle-end/52780 * except.c (emit_to_new_bb_before): Move loop updating ... (dw2_build_landing_pads): ... here. Use a proper block for querying the loop father. * g++.dg/torture/pr52772.C: New testcase. Index: gcc/except.c =================================================================== *** gcc/except.c (revision 186007) --- gcc/except.c (working copy) *************** emit_to_new_bb_before (rtx seq, rtx insn *** 918,929 **** bb = create_basic_block (seq, last, prev_bb); update_bb_for_insn (bb); bb->flags |= BB_SUPERBLOCK; - if (current_loops) - { - add_bb_to_loop (bb, prev_bb->loop_father); - if (prev_bb->loop_father->header == prev_bb) - prev_bb->loop_father->header = bb; - } return bb; } --- 918,923 ---- *************** dw2_build_landing_pads (void) *** 995,1000 **** --- 989,1004 ---- e = make_edge (bb, bb->next_bb, e_flags); e->count = bb->count; e->probability = REG_BR_PROB_BASE; + if (current_loops) + { + struct loop *loop = bb->next_bb->loop_father; + /* If we created a pre-header block, add the new block to the + outer loop, otherwise to the loop itself. */ + if (bb->next_bb == loop->header) + add_bb_to_loop (bb, loop_outer (loop)); + else + add_bb_to_loop (bb, loop); + } } } Index: gcc/testsuite/g++.dg/torture/pr52772.C =================================================================== *** gcc/testsuite/g++.dg/torture/pr52772.C (revision 0) --- gcc/testsuite/g++.dg/torture/pr52772.C (revision 0) *************** *** 0 **** --- 1,85 ---- + // { dg-do compile } + + typedef __SIZE_TYPE__ size_t; + + class c1; + + class c2 { + public: c2() { }; + void *operator new(size_t size, const c1 & crc1); + }; + + class c3 { + public: c3() { _Obj = 0; } + ~c3() { if (_Obj) delete _Obj; } + void set(c2 *pObj); + protected: c2 *_Obj; + }; + + void c3::set(c2 *pObj) { _Obj = pObj; }; + + template<class TYPE> class tc1 : public c2 { + public: tc1(int n=0){}; + int get() const; + TYPE& operator[] (int id); + TYPE * _data; + int _size; + }; + + template<class TYPE> TYPE & tc1<TYPE>::operator[] (int id) { + return _data[id]; + } + + template<class TYPE> int tc1<TYPE>::get() const { + return _size; + } + + class c4 { + public: c4(); + }; + + class c5 : public c2 { + protected: c2 * _own; + public: c5(c2 *o) : _own(o) { } + c5(const c4 & box); + int add(const c4 & ext); + }; + + class c6 { + public: int get() const {}; + }; + + class c7 { + friend class c8; + int find(c6 * loop) const; + }; + + class c8 { + const c1 & _rc1; + int tria(c7 * face, c5 * vtree0 = 0); + }; + + int c8::tria(c7 * face, c5 * vtree0) { + c6 *sLData[64]; + tc1<c6*> loops(64); + while (loops.get() > 1) { + c6 *iloop = 0; + for (int j=1; j<loops.get(); j++) { + if (loops[j]->get() < 32) { + iloop = loops[j]; + } + } + face->find(iloop); + } + c4 box; + c3 ctree; + c5 *vtree = vtree0; + if (!vtree) { + vtree = new (_rc1) c5(box); + ctree.set(vtree); + for (int j=0; j<1; j++) { + c4 sVBBox; + vtree->add(sVBBox); + } + } + }