+ /* Add a VUSE for each call-clobbered variable. */
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
+ {
+ tree var = referenced_var (u);
+ tree real_var = var;
+ bool not_read;
+
+ clobber_stats.readonly_clobbers++;
+
+ /* Not read and not written are computed on regular vars, not
+ subvars, so look at the parent var if this is an SFT. */
+
+ if (TREE_CODE (var) == STRUCT_FIELD_TAG)
+ real_var = SFT_PARENT_VAR (var);
+
+ not_read = not_read_b ? bitmap_bit_p (not_read_b, DECL_UID (real_var))
+ : false;
+
+ if (not_read)
+ {
+ clobber_stats.static_readonly_clobbers_avoided++;
+ continue;
+ }
+
+ add_stmt_operand (&var, s_ann, opf_none | opf_non_specific);
+ }
+}
+
+
+/* A subroutine of get_expr_operands to handle CALL_EXPR. */
+
+static void
+get_call_expr_operands (tree stmt, tree expr)
+{
+ tree op;
+ int call_flags = call_expr_flags (expr);
+
+ /* If aliases have been computed already, add V_MAY_DEF or V_USE
+ operands for all the symbols that have been found to be
+ call-clobbered.
+
+ Note that if aliases have not been computed, the global effects
+ of calls will not be included in the SSA web. This is fine
+ because no optimizer should run before aliases have been
+ computed. By not bothering with virtual operands for CALL_EXPRs
+ we avoid adding superfluous virtual operands, which can be a
+ significant compile time sink (See PR 15855). */
+ if (aliases_computed_p
+ && !bitmap_empty_p (call_clobbered_vars)
+ && !(call_flags & ECF_NOVOPS))
+ {
+ /* A 'pure' or a 'const' function never call-clobbers anything.
+ A 'noreturn' function might, but since we don't return anyway
+ there is no point in recording that. */
+ if (TREE_SIDE_EFFECTS (expr)
+ && !(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN)))
+ add_call_clobber_ops (stmt, get_callee_fndecl (expr));
+ else if (!(call_flags & ECF_CONST))
+ add_call_read_ops (stmt, get_callee_fndecl (expr));
+ }
+
+ /* Find uses in the called function. */
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 0), opf_none);
+
+ for (op = TREE_OPERAND (expr, 1); op; op = TREE_CHAIN (op))
+ get_expr_operands (stmt, &TREE_VALUE (op), opf_none);
+
+ get_expr_operands (stmt, &TREE_OPERAND (expr, 2), opf_none);
+}
+
+
+/* Scan operands in the ASM_EXPR stmt referred to in INFO. */
+
+static void
+get_asm_expr_operands (tree stmt)
+{
+ stmt_ann_t s_ann = stmt_ann (stmt);
+ int noutputs = list_length (ASM_OUTPUTS (stmt));
+ const char **oconstraints
+ = (const char **) alloca ((noutputs) * sizeof (const char *));
+ int i;
+ tree link;
+ const char *constraint;
+ bool allows_mem, allows_reg, is_inout;
+
+ for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ oconstraints[i] = constraint;
+ parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
+ &allows_reg, &is_inout);
+
+ /* This should have been split in gimplify_asm_expr. */
+ gcc_assert (!allows_reg || !is_inout);
+
+ /* Memory operands are addressable. Note that STMT needs the
+ address of this operand. */
+ if (!allows_reg && allows_mem)
+ {
+ tree t = get_base_address (TREE_VALUE (link));
+ if (t && DECL_P (t) && s_ann)
+ add_to_addressable_set (t, &s_ann->addresses_taken);
+ }
+
+ get_expr_operands (stmt, &TREE_VALUE (link), opf_is_def);
+ }
+
+ for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link))
+ {
+ constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link)));
+ parse_input_constraint (&constraint, 0, 0, noutputs, 0,
+ oconstraints, &allows_mem, &allows_reg);
+
+ /* Memory operands are addressable. Note that STMT needs the
+ address of this operand. */
+ if (!allows_reg && allows_mem)
+ {
+ tree t = get_base_address (TREE_VALUE (link));
+ if (t && DECL_P (t) && s_ann)
+ add_to_addressable_set (t, &s_ann->addresses_taken);
+ }
+
+ get_expr_operands (stmt, &TREE_VALUE (link), 0);
+ }
+
+
+ /* Clobber memory for asm ("" : : : "memory"); */
+ for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link))
+ if (strcmp (TREE_STRING_POINTER (TREE_VALUE (link)), "memory") == 0)
+ {
+ unsigned i;
+ bitmap_iterator bi;
+
+ /* Clobber all call-clobbered variables (or .GLOBAL_VAR if we
+ decided to group them). */
+ if (global_var)
+ add_stmt_operand (&global_var, s_ann, opf_is_def);
+ else
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
+ {
+ tree var = referenced_var (i);
+ add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
+ }
+
+ /* Now clobber all addressables. */
+ EXECUTE_IF_SET_IN_BITMAP (addressable_vars, 0, i, bi)
+ {
+ tree var = referenced_var (i);
+
+ /* Subvars are explicitly represented in this list, so
+ we don't need the original to be added to the clobber
+ ops, but the original *will* be in this list because
+ we keep the addressability of the original
+ variable up-to-date so we don't screw up the rest of
+ the backend. */
+ if (var_can_have_subvars (var)
+ && get_subvars_for_var (var) != NULL)
+ continue;
+
+ add_stmt_operand (&var, s_ann, opf_is_def | opf_non_specific);
+ }
+
+ break;
+ }