Hi, this patch contines on tract of making us to handle OBJ_TYPE_REF in expressions more gracefully. The change in gimple_fold_stmt_to_constant_1 makes it to skip the wrapper, so valuelize functions of passes never see it, and in addition OBJ_TYPE_REF is stripped once argument becomes constant.
In gimple-fold we also ask type devirtualization machinery for call target the same way as we do for call statements. I think this is rather important, since still we resolve good part of devirtualization only after inlining. Often we however manage to produce a speculative edge and we really do not want to keep the speculation in code after we found real target. Bootstrapped/regtested x86_64-linux, OK? Honza * gimple-fold.c (fold_gimple_assign): Attempt to devirtualize OBJ_TYPE_REF. (gimple_fold_stmt_to_constant_1): Bypass OBJ_TYPE_REF wrappers. Index: gimple-fold.c =================================================================== --- gimple-fold.c (revision 206042) +++ gimple-fold.c (working copy) @@ -374,6 +375,30 @@ fold_gimple_assign (gimple_stmt_iterator if (REFERENCE_CLASS_P (rhs)) return maybe_fold_reference (rhs, false); + else if (TREE_CODE (rhs) == OBJ_TYPE_REF) + { + tree val = OBJ_TYPE_REF_EXPR (rhs); + if (is_gimple_min_invariant (val)) + return val; + else if (flag_devirtualize && virtual_method_call_p (val)) + { + bool final; + vec <cgraph_node *>targets + = possible_polymorphic_call_targets (val, &final); + if (final && targets.length () <= 1) + { + tree fndecl; + if (targets.length () == 1) + fndecl = targets[0]->decl; + else + fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); + val = fold_convert (TREE_TYPE (val), fndecl); + STRIP_USELESS_TYPE_CONVERSION (val); + return val; + } + } + + } else if (TREE_CODE (rhs) == ADDR_EXPR) { tree ref = TREE_OPERAND (rhs, 0); @@ -2525,6 +2550,13 @@ gimple_fold_stmt_to_constant_1 (gimple s return build_vector (TREE_TYPE (rhs), vec); } + if (subcode == OBJ_TYPE_REF) + { + tree val = (*valueize) (OBJ_TYPE_REF_EXPR (rhs)); + /* If calle is constant, we can fold away the wrapper. */ + if (is_gimple_min_invariant (val)) + return val; + } if (kind == tcc_reference) {