This is another case of ADDR_EXPRs not comparing equal from operand_equal_p if they contain volatile field references. The issue is that we should compare the FIELD_DECLs with retaining OEP_CONSTANT_ADDRESS_OF (or maybe not set TREE_SIDE_EFFECTS on them - but that's a bigger change).
Bootstrap / regtest pending on x86_64-unknown-linux-gnu. Richard. 2013-05-23 Richard Biener <rguent...@suse.de> PR middle-end/57380 * fold-const.c (operand_equal_p): Compare FIELD_DECLs with OEP_CONSTANT_ADDRESS_OF retained. * gcc.dg/torture/pr57381.c: New testcase. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 199199) --- gcc/fold-const.c (working copy) *************** operand_equal_p (const_tree arg0, const_ *** 2664,2673 **** case COMPONENT_REF: /* Handle operand 2 the same as for ARRAY_REF. Operand 0 may be NULL when we're called to compare MEM_EXPRs. */ ! if (!OP_SAME_WITH_NULL (0)) return 0; flags &= ~OEP_CONSTANT_ADDRESS_OF; ! return OP_SAME (1) && OP_SAME_WITH_NULL (2); case BIT_FIELD_REF: if (!OP_SAME (0)) --- 2664,2673 ---- case COMPONENT_REF: /* Handle operand 2 the same as for ARRAY_REF. Operand 0 may be NULL when we're called to compare MEM_EXPRs. */ ! if (!OP_SAME_WITH_NULL (0) || !OP_SAME (1)) return 0; flags &= ~OEP_CONSTANT_ADDRESS_OF; ! return OP_SAME_WITH_NULL (2); case BIT_FIELD_REF: if (!OP_SAME (0)) Index: gcc/testsuite/gcc.dg/torture/pr57381.c =================================================================== *** gcc/testsuite/gcc.dg/torture/pr57381.c (revision 0) --- gcc/testsuite/gcc.dg/torture/pr57381.c (working copy) *************** *** 0 **** --- 1,24 ---- + /* { dg-do compile } */ + + struct S0 { int f0, f1, f2; }; + + struct S1 { + int f0; + volatile struct S0 f2; + }; + + static struct S1 s = {0x47BED265,{0x06D4EB3E,5,0U}}; + + int foo(struct S0 p) + { + for (s.f2.f2 = 0; (s.f2.f2 <= 12); s.f2.f2++) + { + volatile int *l_61[5][2][2] = {{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,(void*)0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{&s.f2.f0,&s.f2.f0}},{{&s.f2.f0,&s.f2.f0},{(void*)0,&s.f2.f0}}}; + + volatile int **l_68 = &l_61[0][0][1]; + volatile int *l_76 = &s.f2.f0; + (*l_68) = l_61[0][0][0]; + if ((*l_76 = (p.f2 % 5))) ; + } + return p.f0; + }