On 28 Oct 2011, at 13:57, Richard Guenther wrote:
We fail to keep the cannot-inline flag up-to-date when turning
indirect to direct calls. The following patch arranges to do
this during statement folding (which should always be called
when that happens). It also makes sure to copy the updated flag
to the edge when iterating early inlining.
This: http://gcc.gnu.org/ml/gcc-cvs/2011-11/msg00046.html
regresses:
acats/c740203a (x86-64-darwin10)
gnat/aliasing3.adb (m64 i486-darwin9 and x86-64-darwin10)
... don't know about other platforms at present.
with messages like:
FAIL: gnat.dg/aliasing3.adb (test for excess errors)
Excess errors:
+===========================GNAT BUG
DETECTED==============================+
| 4.7.0 20111102 (experimental) [trunk revision 180763] (i686-apple-
darwin9) GCC error:|
| in estimate_function_body_sizes, at ipa-inline-analysis.c:
1977 |
| Error detected around /GCC/gcc-live-trunk/gcc/testsuite/gnat.dg/
aliasing3_pkg.adb:8:6|
| Please submit a bug report; see http://gcc.gnu.org/
bugs.html. |
| Use a subject line meaningful to you and us to track the
bug. |
| Include the entire contents of this bug box in the
report. |
| Also include sources listed below in gnatchop
format |
| (concatenated together with no headers between
files). |
+
=
=
=
=======================================================================+
Please include these source files with error report
Note that list may not be accurate in some cases,
so please double check that the problem can still
be reproduced with the set of files listed.
Consider also -gnatd.n switch (see debug.adb).
/Volumes/ScratchCS/gcc-4-7-trunk-build/i686-apple-darwin9/x86_64/
libada/adainclude/system.ads
/GCC/gcc-live-trunk/gcc/testsuite/gnat.dg/aliasing3.adb
/GCC/gcc-live-trunk/gcc/testsuite/gnat.dg/aliasing3_pkg.ads
/GCC/gcc-live-trunk/gcc/testsuite/gnat.dg/aliasing3_pkg.adb
raised TYPES.UNRECOVERABLE_ERROR : comperr.adb:432
Bootstrap and regtest running on x86_64-unknown-linux-gnu, ok?
Thanks,
Richard.
2010-10-28 Richard Guenther <rguent...@suse.de>
PR tree-optimization/50890
* gimple.h (gimple_fold_call): Remove.
* gimple-fold.c (fold_stmt_1): Move all call related code to ...
(gimple_fold_call): ... here. Make static. Update the
cannot-inline flag on direct calls.
* ipa-inline.c (early_inliner): Copy the cannot-inline flag
from the statements to the edges.
* gcc.dg/torture/pr50890.c: New testcase.
Index: gcc/gimple.h
===================================================================
*** gcc/gimple.h (revision 180608)
--- gcc/gimple.h (working copy)
*************** unsigned get_gimple_rhs_num_ops (enum tr
*** 909,915 ****
#define gimple_alloc(c, n) gimple_alloc_stat (c, n MEM_STAT_INFO)
gimple gimple_alloc_stat (enum gimple_code, unsigned MEM_STAT_DECL);
const char *gimple_decl_printable_name (tree, int);
- bool gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace);
tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
void gimple_adjust_this_by_delta (gimple_stmt_iterator *, tree);
tree gimple_extract_devirt_binfo_from_cst (tree);
--- 909,914 ----
Index: gcc/gimple-fold.c
===================================================================
*** gcc/gimple-fold.c (revision 180608)
--- gcc/gimple-fold.c (working copy)
*************** gimple_extract_devirt_binfo_from_cst (tr
*** 1057,1109 ****
simplifies to a constant value. Return true if any changes were
made.
It is assumed that the operands have been previously folded. */
! bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{
gimple stmt = gsi_stmt (*gsi);
tree callee;
! /* Check for builtins that CCP can handle using information not
! available in the generic fold routines. */
! callee = gimple_call_fndecl (stmt);
! if (!inplace && callee && DECL_BUILT_IN (callee))
! {
! tree result = gimple_fold_builtin (stmt);
!
! if (result)
! {
! if (!update_call_from_tree (gsi, result))
! gimplify_and_update_call_from_tree (gsi, result);
! return true;
! }
! }
/* Check for virtual calls that became direct calls. */
callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{
- tree binfo, fndecl, obj;
- HOST_WIDE_INT token;
-
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) !=
NULL_TREE)
{
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
! return true;
}
! obj = OBJ_TYPE_REF_OBJECT (callee);
! binfo = gimple_extract_devirt_binfo_from_cst (obj);
! if (!binfo)
! return false;
! token = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
! fndecl = gimple_get_virt_method_for_binfo (token, binfo);
! if (!fndecl)
! return false;
! gimple_call_set_fndecl (stmt, fndecl);
! return true;
}
! return false;
}
/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE
argument
--- 1057,1138 ----
simplifies to a constant value. Return true if any changes were
made.
It is assumed that the operands have been previously folded. */
! static bool
gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace)
{
gimple stmt = gsi_stmt (*gsi);
tree callee;
+ bool changed = false;
+ unsigned i;
! /* Fold *& in call arguments. */
! for (i = 0; i < gimple_call_num_args (stmt); ++i)
! if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
! {
! tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i), false);
! if (tmp)
! {
! gimple_call_set_arg (stmt, i, tmp);
! changed = true;
! }
! }
/* Check for virtual calls that became direct calls. */
callee = gimple_call_fn (stmt);
if (callee && TREE_CODE (callee) == OBJ_TYPE_REF)
{
if (gimple_call_addr_fndecl (OBJ_TYPE_REF_EXPR (callee)) !=
NULL_TREE)
{
gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee));
! changed = true;
}
+ else
+ {
+ tree obj = OBJ_TYPE_REF_OBJECT (callee);
+ tree binfo = gimple_extract_devirt_binfo_from_cst (obj);
+ if (binfo)
+ {
+ HOST_WIDE_INT token
+ = TREE_INT_CST_LOW (OBJ_TYPE_REF_TOKEN (callee));
+ tree fndecl = gimple_get_virt_method_for_binfo (token,
binfo);
+ if (fndecl)
+ {
+ gimple_call_set_fndecl (stmt, fndecl);
+ changed = true;
+ }
+ }
+ }
+ }
! /* Check whether propagating into the function address made the
! call direct, and thus possibly non-inlineable.
! ??? This asks for a more conservative setting of the non-
inlinable
! flag, namely true for all indirect calls. But that would
require
! that we can re-compute the flag conservatively, thus it isn't
! ever initialized from something else than return/argument type
! checks . */
! callee = gimple_call_fndecl (stmt);
! if (callee
! && !gimple_check_call_matching_types (stmt, callee))
! gimple_call_set_cannot_inline (stmt, true);
!
! if (inplace)
! return changed;
!
! /* Check for builtins that CCP can handle using information not
! available in the generic fold routines. */
! if (callee && DECL_BUILT_IN (callee))
! {
! tree result = gimple_fold_builtin (stmt);
! if (result)
! {
! if (!update_call_from_tree (gsi, result))
! gimplify_and_update_call_from_tree (gsi, result);
! changed = true;
! }
}
! return changed;
}
/* Worker for both fold_stmt and fold_stmt_inplace. The INPLACE
argument
*************** fold_stmt_1 (gimple_stmt_iterator *gsi,
*** 1162,1178 ****
break;
case GIMPLE_CALL:
- /* Fold *& in call arguments. */
- for (i = 0; i < gimple_call_num_args (stmt); ++i)
- if (REFERENCE_CLASS_P (gimple_call_arg (stmt, i)))
- {
- tree tmp = maybe_fold_reference (gimple_call_arg (stmt, i),
false);
- if (tmp)
- {
- gimple_call_set_arg (stmt, i, tmp);
- changed = true;
- }
- }
changed |= gimple_fold_call (gsi, inplace);
break;
--- 1191,1196 ----
Index: gcc/ipa-inline.c
===================================================================
*** gcc/ipa-inline.c (revision 180608)
--- gcc/ipa-inline.c (working copy)
*************** early_inliner (void)
*** 1949,1954 ****
--- 1949,1956 ----
= estimate_num_insns (edge->call_stmt, &eni_size_weights);
es->call_stmt_time
= estimate_num_insns (edge->call_stmt, &eni_time_weights);
+ edge->call_stmt_cannot_inline_p
+ = gimple_call_cannot_inline_p (edge->call_stmt);
}
timevar_pop (TV_INTEGRATION);
iterations++;
Index: gcc/testsuite/gcc.dg/torture/pr50890.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr50890.c (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr50890.c (revision 0)
***************
*** 0 ****
--- 1,17 ----
+ /* { dg-do compile } */
+
+ static float make_insn_raw (void)
+ {
+ return 0;
+ }
+
+ static int emit_pattern_after_noloc (int (make_raw) ())
+ {
+ return make_raw ();
+ }
+
+ void emit_insn_after_noloc (void)
+ {
+ emit_pattern_after_noloc ((void *) make_insn_raw);
+ }
+