From 43320568b265d6f0448e6f8ae7e6a8ace3a13be0 Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Tue, 12 Feb 2013 14:04:44 +0000 Subject: [PATCH] re PR lto/56295 (Missed optimization with LTO) 2013-02-12 Richard Biener PR lto/56295 * gimple-streamer-in.c (input_gimple_stmt): Strip MEM_REFs off decls again if possible. From-SVN: r195976 --- gcc/ChangeLog | 6 +++++ gcc/gimple-streamer-in.c | 53 ++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 18 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec0d8c1d8b0..a0ced1db78c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2013-02-12 Richard Biener + + PR lto/56295 + * gimple-streamer-in.c (input_gimple_stmt): Strip MEM_REFs off + decls again if possible. + 2013-02-12 Richard Biener PR middle-end/56288 diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index f2dfc4dd5c8..aff589a4c8f 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -143,22 +143,23 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, case GIMPLE_DEBUG: for (i = 0; i < num_ops; i++) { - tree op = stream_read_tree (ib, data_in); + tree *opp, op = stream_read_tree (ib, data_in); gimple_set_op (stmt, i, op); if (!op) continue; - if (TREE_CODE (op) == ADDR_EXPR) - op = TREE_OPERAND (op, 0); - while (handled_component_p (op)) + opp = gimple_op_ptr (stmt, i); + if (TREE_CODE (*opp) == ADDR_EXPR) + opp = &TREE_OPERAND (*opp, 0); + while (handled_component_p (*opp)) { - if (TREE_CODE (op) == COMPONENT_REF) + if (TREE_CODE (*opp) == COMPONENT_REF) { /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled by decl merging. */ tree field, type, tem; tree closest_match = NULL_TREE; - field = TREE_OPERAND (op, 1); + field = TREE_OPERAND (*opp, 1); type = DECL_CONTEXT (field); for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { @@ -186,12 +187,12 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, if (warning_at (gimple_location (stmt), 0, "use of type %<%E%> with two mismatching " "declarations at field %<%E%>", - type, TREE_OPERAND (op, 1))) + type, TREE_OPERAND (*opp, 1))) { if (TYPE_FIELDS (type)) inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)), "original type declared here"); - inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)), + inform (DECL_SOURCE_LOCATION (TREE_OPERAND (*opp, 1)), "field in mismatching type declared here"); if (TYPE_NAME (TREE_TYPE (field)) && (TREE_CODE (TYPE_NAME (TREE_TYPE (field))) @@ -208,28 +209,44 @@ input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in, "type of mismatching field declared here"); } /* And finally fixup the types. */ - TREE_OPERAND (op, 0) + TREE_OPERAND (*opp, 0) = build1 (VIEW_CONVERT_EXPR, type, - TREE_OPERAND (op, 0)); + TREE_OPERAND (*opp, 0)); } else - TREE_OPERAND (op, 1) = tem; + TREE_OPERAND (*opp, 1) = tem; } - else if ((TREE_CODE (op) == ARRAY_REF - || TREE_CODE (op) == ARRAY_RANGE_REF) - && (TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) + else if ((TREE_CODE (*opp) == ARRAY_REF + || TREE_CODE (*opp) == ARRAY_RANGE_REF) + && (TREE_CODE (TREE_TYPE (TREE_OPERAND (*opp, 0))) != ARRAY_TYPE)) { /* And ARRAY_REFs to objects that had mismatched types during symbol merging to avoid ICEs. */ - TREE_OPERAND (op, 0) + TREE_OPERAND (*opp, 0) = build1 (VIEW_CONVERT_EXPR, - build_array_type (TREE_TYPE (op), NULL_TREE), - TREE_OPERAND (op, 0)); + build_array_type (TREE_TYPE (*opp), NULL_TREE), + TREE_OPERAND (*opp, 0)); } - op = TREE_OPERAND (op, 0); + opp = &TREE_OPERAND (*opp, 0); } + /* At LTO output time we wrap all global decls in MEM_REFs to + allow seamless replacement with prevailing decls. Undo this + here if the prevailing decl allows for this. + ??? Maybe we should simply fold all stmts. */ + if (TREE_CODE (*opp) == MEM_REF + && TREE_CODE (TREE_OPERAND (*opp, 0)) == ADDR_EXPR + && integer_zerop (TREE_OPERAND (*opp, 1)) + && (TREE_THIS_VOLATILE (*opp) + == TREE_THIS_VOLATILE + (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0))) + && !TYPE_REF_CAN_ALIAS_ALL (TREE_TYPE (TREE_OPERAND (*opp, 1))) + && (TREE_TYPE (*opp) + == TREE_TYPE (TREE_TYPE (TREE_OPERAND (*opp, 1)))) + && (TREE_TYPE (*opp) + == TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*opp, 0), 0)))) + *opp = TREE_OPERAND (TREE_OPERAND (*opp, 0), 0); } if (is_gimple_call (stmt)) {