This fixes PR49645 - with MEM_REF the value-numbering machinery to look through aggregate copies wasn't working reliably as we have two representations for X, X and MEM[&X]. The following patch fixes that by internally always using the more complicated representation.
The patch needs consistent DECL_HARD_REGISTER settings to avoid generating MEM_REFs for them though and the C frontend fails to set that flag for global variables - hence the c-decl.c part (otherwise compile.exp 20041119-1.c ICEs). Bootstrapped and tested on x86_64-unknown-linux-gnu, are the C frontend parts ok for trunk? Thanks, Richard. 2011-07-06 Richard Guenther <rguent...@suse.de> PR tree-optimization/49645 * c-decl.c (finish_decl): Also set DECL_HARD_REGISTER for global register variables. * tree-ssa-sccvn.c (vn_reference_op_eq): Disregard differences in type qualification here ... (copy_reference_ops_from_ref): ... not here. (vn_reference_lookup_3): ... or here. (copy_reference_ops_from_ref): Record decl bases as MEM[&decl]. (vn_reference_lookup): Do the lookup with a valueized ao-ref. * g++.dg/tree-ssa/pr8781.C: Disable SRA. Index: gcc/c-decl.c =================================================================== *** gcc/c-decl.c (revision 175905) --- gcc/c-decl.c (working copy) *************** finish_decl (tree decl, location_t init_ *** 4357,4362 **** --- 4357,4364 ---- when a tentative file-scope definition is seen. But at end of compilation, do output code for them. */ DECL_DEFER_OUTPUT (decl) = 1; + if (asmspec && C_DECL_REGISTER (decl)) + DECL_HARD_REGISTER (decl) = 1; rest_of_decl_compilation (decl, true, 0); } else Index: gcc/tree-ssa-sccvn.c =================================================================== *** gcc/tree-ssa-sccvn.c (revision 175905) --- gcc/tree-ssa-sccvn.c (working copy) *************** vn_reference_op_eq (const void *p1, cons *** 391,401 **** const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1; const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2; ! return vro1->opcode == vro2->opcode ! && types_compatible_p (vro1->type, vro2->type) ! && expressions_equal_p (vro1->op0, vro2->op0) ! && expressions_equal_p (vro1->op1, vro2->op1) ! && expressions_equal_p (vro1->op2, vro2->op2); } /* Compute the hash for a reference operand VRO1. */ --- 391,405 ---- const_vn_reference_op_t const vro1 = (const_vn_reference_op_t) p1; const_vn_reference_op_t const vro2 = (const_vn_reference_op_t) p2; ! return (vro1->opcode == vro2->opcode ! /* We do not care for differences in type qualification. */ ! && (vro1->type == vro2->type ! || (vro1->type && vro2->type ! && types_compatible_p (TYPE_MAIN_VARIANT (vro1->type), ! TYPE_MAIN_VARIANT (vro2->type)))) ! && expressions_equal_p (vro1->op0, vro2->op0) ! && expressions_equal_p (vro1->op1, vro2->op1) ! && expressions_equal_p (vro1->op2, vro2->op2)); } /* Compute the hash for a reference operand VRO1. */ *************** copy_reference_ops_from_ref (tree ref, V *** 579,585 **** memset (&temp, 0, sizeof (temp)); /* We do not care for spurious type qualifications. */ ! temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref)); temp.opcode = TREE_CODE (ref); temp.op0 = TMR_INDEX (ref); temp.op1 = TMR_STEP (ref); --- 583,589 ---- memset (&temp, 0, sizeof (temp)); /* We do not care for spurious type qualifications. */ ! temp.type = TREE_TYPE (ref); temp.opcode = TREE_CODE (ref); temp.op0 = TMR_INDEX (ref); temp.op1 = TMR_STEP (ref); *************** copy_reference_ops_from_ref (tree ref, V *** 610,617 **** vn_reference_op_s temp; memset (&temp, 0, sizeof (temp)); ! /* We do not care for spurious type qualifications. */ ! temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref)); temp.opcode = TREE_CODE (ref); temp.off = -1; --- 614,620 ---- vn_reference_op_s temp; memset (&temp, 0, sizeof (temp)); ! temp.type = TREE_TYPE (ref); temp.opcode = TREE_CODE (ref); temp.off = -1; *************** copy_reference_ops_from_ref (tree ref, V *** 676,691 **** temp.off = off.low; } break; case STRING_CST: case INTEGER_CST: case COMPLEX_CST: case VECTOR_CST: case REAL_CST: case CONSTRUCTOR: - case VAR_DECL: - case PARM_DECL: - case CONST_DECL: - case RESULT_DECL: case SSA_NAME: temp.op0 = ref; break; --- 679,711 ---- temp.off = off.low; } break; + case VAR_DECL: + if (DECL_HARD_REGISTER (ref)) + { + temp.op0 = ref; + break; + } + /* Fallthru. */ + case PARM_DECL: + case CONST_DECL: + case RESULT_DECL: + /* Canonicalize decls to MEM[&decl] which is what we end up with + when valueizing MEM[ptr] with ptr = &decl. */ + temp.opcode = MEM_REF; + temp.op0 = build_int_cst (build_pointer_type (TREE_TYPE (ref)), 0); + temp.off = 0; + VEC_safe_push (vn_reference_op_s, heap, *result, &temp); + temp.opcode = ADDR_EXPR; + temp.op0 = build_fold_addr_expr (ref); + temp.type = TREE_TYPE (temp.op0); + temp.off = -1; + break; case STRING_CST: case INTEGER_CST: case COMPLEX_CST: case VECTOR_CST: case REAL_CST: case CONSTRUCTOR: case SSA_NAME: temp.op0 = ref; break; *************** vn_reference_lookup_3 (ao_ref *ref, tree *** 1580,1586 **** op.op0 = build_int_cst (ptr_type_node, at - rhs_offset); op.off = at - lhs_offset + rhs_offset; VEC_replace (vn_reference_op_s, vr->operands, 0, &op); ! op.type = TYPE_MAIN_VARIANT (TREE_TYPE (rhs)); op.opcode = TREE_CODE (rhs); op.op0 = rhs; op.off = -1; --- 1600,1606 ---- op.op0 = build_int_cst (ptr_type_node, at - rhs_offset); op.off = at - lhs_offset + rhs_offset; VEC_replace (vn_reference_op_s, vr->operands, 0, &op); ! op.type = TREE_TYPE (rhs); op.opcode = TREE_CODE (rhs); op.op0 = rhs; op.off = -1; *************** vn_reference_lookup (tree op, tree vuse, *** 1692,1698 **** { vn_reference_t wvnresult; ao_ref r; ! ao_ref_init (&r, op); vn_walk_kind = kind; wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, --- 1712,1723 ---- { vn_reference_t wvnresult; ao_ref r; ! /* Make sure to use a valueized reference ... */ ! if (!ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type, vr1.operands)) ! ao_ref_init (&r, op); ! else ! /* ... but also preserve a full reference tree for advanced TBAA. */ ! r.ref = op; vn_walk_kind = kind; wvnresult = (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, Index: gcc/testsuite/g++.dg/tree-ssa/pr8781.C =================================================================== *** gcc/testsuite/g++.dg/tree-ssa/pr8781.C (revision 175905) --- gcc/testsuite/g++.dg/tree-ssa/pr8781.C (working copy) *************** *** 1,5 **** /* { dg-do compile } */ ! /* { dg-options "-O -fdump-tree-fre1-details" } */ int f(); --- 1,5 ---- /* { dg-do compile } */ ! /* { dg-options "-O -fno-tree-sra -fdump-tree-fre1-details" } */ int f();