https://gcc.gnu.org/g:402a199e1b446efd569a70d4ce507454b800a5f5
commit 402a199e1b446efd569a70d4ce507454b800a5f5 Author: Michael Matz <[email protected]> Date: Sun Mar 4 03:17:42 2018 +0100 update-stmt: TLC * build_vdef/build_vuse are used only as flags (nearly), so make the bit flags in build_flags. This gets rid of many struct function * args from the operand scanner. * reorder build flags so that volatile > vdef > vuse > nothing * put freed useop entries in add_ssa_op to the free list (requires some change of if (*puse) to if (puse). Diff: --- gcc/tree-ssa-operands.c | 365 ++++++++++++++++++++---------------------------- gcc/tree-ssa-operands.h | 2 +- gcc/tree-ssa.c | 2 +- 3 files changed, 152 insertions(+), 217 deletions(-) diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index f9a45028fce9..cff247957197 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -96,18 +96,14 @@ along with GCC; see the file COPYING3. If not see /* Array for building all the use operands. */ static vec<tree *> build_uses; -/* The built VDEF operand. */ -static tree build_vdef; - -/* The built VUSE operand. */ -static tree build_vuse; - -#define BF_VOLATILE 1 -#define BF_RENAME 2 -#define BF_RENAME_VOP 4 +#define BF_RENAME 1 +#define BF_RENAME_VOP 2 +#define BF_VUSE 4 +#define BF_VDEF 8 +#define BF_VOLATILE 16 static int build_flags; -static void get_expr_operands (struct function *, gimple *, tree *, int); +static void get_expr_operands (gimple *, tree *, int); /* Number of functions with initialized ssa_operands. */ static int n_initialized = 0; @@ -179,8 +175,6 @@ init_ssa_operands (struct function *fn) if (!n_initialized++) { build_uses.create (10); - build_vuse = NULL_TREE; - build_vdef = NULL_TREE; build_flags = 0; } @@ -204,8 +198,6 @@ fini_ssa_operands (struct function *fn) { build_flags = 0; build_uses.release (); - build_vdef = NULL_TREE; - build_vuse = NULL_TREE; } gimple_ssa_operands (fn)->free_uses = NULL; @@ -304,25 +296,18 @@ add_use_op (struct function *fn, gimple *stmt, tree *op, use_optype_p last) } -/* Takes elements from build_defs and turns them into def operands of STMT. - TODO -- Make build_defs vec of tree *. */ +/* Takes elements from build_defs and turns them into def operands of STMT. */ static inline void finalize_ssa_defs (struct function *fn, gimple *stmt) { /* Pre-pend the vdef we may have built. */ - if (build_vdef != NULL_TREE) - { - tree oldvdef = gimple_vdef (stmt); - if (oldvdef - && TREE_CODE (oldvdef) == SSA_NAME) - oldvdef = SSA_NAME_VAR (oldvdef); - if (oldvdef != build_vdef) - gimple_set_vdef (stmt, build_vdef); - } + if (build_flags & BF_VDEF + && !gimple_vdef (stmt)) + gimple_set_vdef (stmt, gimple_vop (fn)); /* Clear and unlink a no longer necessary VDEF. */ - if (build_vdef == NULL_TREE + if (!(build_flags & BF_VDEF) && gimple_vdef (stmt) != NULL_TREE) { if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) @@ -352,28 +337,19 @@ finalize_ssa_uses (struct function *fn, gimple *stmt) use_optype_p old_ops, ptr, last; /* Pre-pend the VUSE we may have built. */ - if (build_vuse != NULL_TREE) - { - tree oldvuse = gimple_vuse (stmt); - if (oldvuse - && TREE_CODE (oldvuse) == SSA_NAME) - oldvuse = SSA_NAME_VAR (oldvuse); - if (oldvuse != (build_vuse != NULL_TREE - ? build_vuse : build_vdef)) - gimple_set_vuse (stmt, NULL_TREE); + if (build_flags & BF_VUSE) build_uses.safe_insert (0, gimple_vuse_ptr (stmt)); - } + + /* Clear a no longer necessary VUSE. */ + if (!(build_flags & BF_VUSE) + && gimple_vuse (stmt) != NULL_TREE) + gimple_set_vuse (stmt, NULL_TREE); new_list.next = NULL; last = &new_list; old_ops = gimple_use_ops (stmt); - /* Clear a no longer necessary VUSE. */ - if (build_vuse == NULL_TREE - && gimple_vuse (stmt) != NULL_TREE) - gimple_set_vuse (stmt, NULL_TREE); - /* If there is anything in the old list, free it. */ if (old_ops) { @@ -386,7 +362,7 @@ finalize_ssa_uses (struct function *fn, gimple *stmt) /* If we added a VUSE, make sure to set the operand if it is not already present and mark it for renaming. */ - if (build_vuse != NULL_TREE + if ((build_flags & BF_VUSE) && gimple_vuse (stmt) == NULL_TREE) { gimple_set_vuse (stmt, gimple_vop (fn)); @@ -411,8 +387,6 @@ finalize_ssa_uses (struct function *fn, gimple *stmt) static inline void cleanup_build_arrays (void) { - build_vdef = NULL_TREE; - build_vuse = NULL_TREE; build_uses.truncate (0); build_flags = 0; } @@ -443,8 +417,6 @@ static inline void start_ssa_stmt_operands (void) { gcc_assert (build_uses.length () == 0); - gcc_assert (build_vuse == NULL_TREE); - gcc_assert (build_vdef == NULL_TREE); gcc_assert (build_flags == 0); } @@ -461,34 +433,24 @@ append_use (tree *use_p) /* Add VAR to the set of variables that require a VDEF operator. */ static inline void -append_vdef (tree var) +append_vdef (void) { - gcc_assert ((build_vdef == NULL_TREE - || build_vdef == var) - && (build_vuse == NULL_TREE - || build_vuse == var)); - - build_vdef = var; - build_vuse = var; + build_flags |= BF_VDEF | BF_VUSE; } /* Add VAR to the set of variables that require a VUSE operator. */ static inline void -append_vuse (tree var) +append_vuse (void) { - gcc_assert (build_vuse == NULL_TREE - || build_vuse == var); - - build_vuse = var; + build_flags |= BF_VUSE; } /* Add virtual operands for STMT. FLAGS is as in get_expr_operands. */ static void -add_virtual_operand (struct function *fn, - gimple *stmt ATTRIBUTE_UNUSED, int flags) +add_virtual_operand (gimple *stmt ATTRIBUTE_UNUSED, int flags) { /* Add virtual operands to the stmt, unless the caller has specifically requested not to do that (used when adding operands inside an @@ -499,9 +461,9 @@ add_virtual_operand (struct function *fn, gcc_assert (!is_gimple_debug (stmt)); if (flags & opf_def) - append_vdef (gimple_vop (fn)); + append_vdef (); else - append_vuse (gimple_vop (fn)); + append_vuse (); } @@ -511,7 +473,7 @@ add_virtual_operand (struct function *fn, added to virtual operands. */ static void -add_stmt_operand (struct function *fn, tree *var_p, gimple *stmt, int flags) +add_stmt_operand (tree *var_p, gimple *stmt, int flags) { tree var = *var_p; @@ -535,7 +497,7 @@ add_stmt_operand (struct function *fn, tree *var_p, gimple *stmt, int flags) build_flags |= BF_VOLATILE; /* The variable is a memory access. Add virtual operands. */ - add_virtual_operand (fn, stmt, flags); + add_virtual_operand (stmt, flags); } } @@ -548,8 +510,7 @@ add_stmt_operand (struct function *fn, tree *var_p, gimple *stmt, int flags) FLAGS is as in get_expr_operands. */ static void -get_mem_ref_operands (struct function *fn, - gimple *stmt, tree expr, int flags) +get_mem_ref_operands (gimple *stmt, tree expr, int flags) { tree *pptr = &TREE_OPERAND (expr, 0); @@ -558,60 +519,67 @@ get_mem_ref_operands (struct function *fn, build_flags |= BF_VOLATILE; /* Add the VOP. */ - add_virtual_operand (fn, stmt, flags); + add_virtual_operand (stmt, flags); /* If requested, add a USE operand for the base pointer. */ - get_expr_operands (fn, stmt, pptr, opf_use | (flags & opf_no_vops)); + get_expr_operands (stmt, pptr, opf_use | (flags & opf_no_vops)); } /* A subroutine of get_expr_operands to handle TARGET_MEM_REF. */ static void -get_tmr_operands (struct function *fn, gimple *stmt, tree expr, int flags) +get_tmr_operands (gimple *stmt, tree expr, int flags) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (expr)) build_flags |= BF_VOLATILE; /* First record the real operands. */ - get_expr_operands (fn, stmt, + get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); - get_expr_operands (fn, stmt, + get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); - get_expr_operands (fn, stmt, + get_expr_operands (stmt, &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); - add_virtual_operand (fn, stmt, flags); + add_virtual_operand (stmt, flags); } /* If STMT is a call that may clobber globals and other symbols that - escape, add them to the VDEF/VUSE lists for it. */ + escape, return an appropriate flag mask for the necessary VDEF/VUSEs. + Otherwise return zero. */ -static void -maybe_add_call_vops (struct function *fn, gcall *stmt) +static int +get_call_vop_flags (gimple *stmt) { int call_flags = gimple_call_flags (stmt); - - /* If aliases have been computed already, add VDEF or VUSE - operands for all the symbols that have been found to be - call-clobbered. */ if (!(call_flags & ECF_NOVOPS)) { - /* A 'pure' or a 'const' function never call-clobbers anything. */ if (!(call_flags & (ECF_PURE | ECF_CONST))) - add_virtual_operand (fn, stmt, opf_def); + return BF_VDEF | BF_VUSE; else if (!(call_flags & ECF_CONST)) - add_virtual_operand (fn, stmt, opf_use); + return BF_VUSE; } + return 0; +} + + +/* If STMT is a call that may clobber globals and other symbols that + escape, add them to the VDEF/VUSE lists for it. */ + +static void +maybe_add_call_vops (gcall *stmt) +{ + build_flags |= get_call_vop_flags (stmt); } /* Scan operands in the ASM_EXPR stmt referred to in INFO. */ static void -get_asm_stmt_operands (struct function *fn, gasm *stmt) +get_asm_stmt_operands (gasm *stmt) { size_t i, noutputs; const char **oconstraints; @@ -633,7 +601,7 @@ get_asm_stmt_operands (struct function *fn, gasm *stmt) /* This should have been split in gimplify_asm_expr. */ gcc_assert (!allows_reg || !is_inout); - get_expr_operands (fn, stmt, &TREE_VALUE (link), opf_def); + get_expr_operands (stmt, &TREE_VALUE (link), opf_def); } /* Gather all input operands. */ @@ -644,12 +612,12 @@ get_asm_stmt_operands (struct function *fn, gasm *stmt) parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints, &allows_mem, &allows_reg); - get_expr_operands (fn, stmt, &TREE_VALUE (link), opf_use); + get_expr_operands (stmt, &TREE_VALUE (link), opf_use); } /* Clobber all memory and addressable symbols for asm ("" : : : "memory"); */ if (gimple_asm_clobbers_memory_p (stmt)) - add_virtual_operand (fn, stmt, opf_def); + add_virtual_operand (stmt, opf_def); } @@ -658,7 +626,7 @@ get_asm_stmt_operands (struct function *fn, gasm *stmt) interpret the operands found. */ static void -get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) +get_expr_operands (gimple *stmt, tree *expr_p, int flags) { enum tree_code code; enum tree_code_class codeclass; @@ -683,7 +651,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) here are ARRAY_REF indices which will always be real operands (GIMPLE does not allow non-registers as array indices). */ flags |= opf_no_vops; - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags | opf_address_taken); return; @@ -692,7 +660,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case PARM_DECL: case RESULT_DECL: if (!(flags & opf_address_taken)) - add_stmt_operand (fn, expr_p, stmt, flags); + add_stmt_operand (expr_p, stmt, flags); return; case DEBUG_EXPR_DECL: @@ -700,11 +668,11 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) return; case MEM_REF: - get_mem_ref_operands (fn, stmt, expr, flags); + get_mem_ref_operands (stmt, expr, flags); return; case TARGET_MEM_REF: - get_tmr_operands (fn, stmt, expr, flags); + get_tmr_operands (stmt, expr, flags); return; case ARRAY_REF: @@ -717,20 +685,20 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) && TREE_THIS_VOLATILE (expr)) build_flags |= BF_VOLATILE; - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); if (code == COMPONENT_REF) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1))) build_flags |= BF_VOLATILE; - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); } else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 3), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags); } return; @@ -739,16 +707,16 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case WITH_SIZE_EXPR: /* WITH_SIZE_EXPR is a pass-through reference to its first argument, and an rvalue reference to its second argument. */ - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; case COND_EXPR: case VEC_COND_EXPR: case VEC_PERM_EXPR: - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), uflags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); return; case CONSTRUCTOR: @@ -768,7 +736,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (expr), idx, &ce); idx++) - get_expr_operands (fn, stmt, &ce->value, uflags); + get_expr_operands (stmt, &ce->value, uflags); return; } @@ -781,7 +749,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case VIEW_CONVERT_EXPR: do_unary: - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); return; case BIT_INSERT_EXPR: @@ -793,8 +761,8 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case ASSERT_EXPR: do_binary: { - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); return; } @@ -806,15 +774,15 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) case FMA_EXPR: { abort(); // hmm, but might exist hidden down in debug stmts? doesn't seem so at present! - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); - get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); + get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); return; } case TREE_LIST: /* Operands of GIMPLE_ASM, real operand is in TREE_VALUE. */ - get_expr_operands (fn, stmt, &TREE_VALUE (expr), flags); + get_expr_operands (stmt, &TREE_VALUE (expr), flags); return; case FUNCTION_DECL: @@ -851,7 +819,7 @@ get_expr_operands (struct function *fn, gimple *stmt, tree *expr_p, int flags) build_* operand vectors will have potential operands in them. */ static void -parse_ssa_operands (struct function *fn, gimple *stmt) +parse_ssa_operands (gimple *stmt) { enum gimple_code code = gimple_code (stmt); size_t i, n, start = 0; @@ -859,32 +827,32 @@ parse_ssa_operands (struct function *fn, gimple *stmt) switch (code) { case GIMPLE_ASM: - get_asm_stmt_operands (fn, as_a <gasm *> (stmt)); + get_asm_stmt_operands (as_a <gasm *> (stmt)); break; case GIMPLE_TRANSACTION: /* The start of a transaction is a memory barrier. */ - add_virtual_operand (fn, stmt, opf_def | opf_use); + add_virtual_operand (stmt, opf_def | opf_use); break; case GIMPLE_DEBUG: if (gimple_debug_bind_p (stmt) && gimple_debug_bind_has_value_p (stmt)) - get_expr_operands (fn, stmt, gimple_debug_bind_get_value_ptr (stmt), + get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt), opf_use | opf_no_vops); break; case GIMPLE_RETURN: - append_vuse (gimple_vop (fn)); + append_vuse (); goto do_default; case GIMPLE_CALL: /* Add call-clobbered operands, if needed. */ - maybe_add_call_vops (fn, as_a <gcall *> (stmt)); + maybe_add_call_vops (as_a <gcall *> (stmt)); /* FALLTHRU */ case GIMPLE_ASSIGN: - get_expr_operands (fn, stmt, gimple_op_ptr (stmt, 0), opf_def); + get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def); start = 1; /* FALLTHRU */ @@ -892,7 +860,7 @@ parse_ssa_operands (struct function *fn, gimple *stmt) do_default: n = gimple_num_ops (stmt); for (i = start; i < n; i++) - get_expr_operands (fn, stmt, gimple_op_ptr (stmt, i), opf_use); + get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use); break; } } @@ -907,14 +875,14 @@ build_ssa_operands (struct function *fn, gimple *stmt) gimple_set_has_volatile_ops (stmt, false); start_ssa_stmt_operands (); - parse_ssa_operands (fn, stmt); + parse_ssa_operands (stmt); finalize_ssa_stmt_operands (fn, stmt); } /* Verifies SSA statement operands. */ DEBUG_FUNCTION bool -verify_ssa_operands (struct function *fn, gimple *stmt) +verify_ssa_operands (gimple *stmt) { use_operand_p use_p; def_operand_p def_p; @@ -924,14 +892,11 @@ verify_ssa_operands (struct function *fn, gimple *stmt) /* build_ssa_operands w/o finalizing them. */ start_ssa_stmt_operands (); - parse_ssa_operands (fn, stmt); + parse_ssa_operands (stmt); /* Now verify the built operands are the same as present in STMT. */ def = gimple_vdef (stmt); - if (def - && TREE_CODE (def) == SSA_NAME) - def = SSA_NAME_VAR (def); - if (build_vdef != def) + if (!!(build_flags & BF_VDEF) != !!def) { error ("virtual definition of statement not up-to-date"); return true; @@ -945,10 +910,7 @@ verify_ssa_operands (struct function *fn, gimple *stmt) } tree use = gimple_vuse (stmt); - if (use - && TREE_CODE (use) == SSA_NAME) - use = SSA_NAME_VAR (use); - if (build_vuse != use) + if (!!(build_flags & BF_VUSE) != !!use) { error ("virtual use of statement not up-to-date"); return true; @@ -1067,7 +1029,7 @@ update_stmt (gimple *s) else ptr = &((*ptr)->next); }*/ - if (verify_ssa_operands (cfun, s)) + if (verify_ssa_operands (s)) { print_gimple_stmt (stderr, s, 0, TDF_VOPS); abort (); @@ -1077,15 +1039,18 @@ update_stmt (gimple *s) } static use_optype_p * -find_use_op (gimple *stmt, tree *pop) +find_delink_use_op (gimple *stmt, tree *pop) { gimple_statement_with_ops *ops_stmt = dyn_cast <gimple_statement_with_ops *> (stmt); use_optype_p *puse; for (puse = &ops_stmt->use_ops; *puse; puse = &((*puse)->next)) if ((*puse)->use_ptr.use == pop) - break; - return puse; + { + delink_imm_use (&((*puse)->use_ptr)); + return puse; + } + return NULL; } static void @@ -1142,7 +1107,7 @@ update_stmt_use (use_operand_p use) && !is_gimple_min_invariant (*pnewval)) { start_ssa_stmt_operands (); - get_expr_operands (cfun, stmt, pnewval, opf_no_vops | opf_use); + get_expr_operands (stmt, pnewval, opf_no_vops | opf_use); for (unsigned i = 0; i < build_uses.length (); i++) { tree *op = build_uses[i]; @@ -1157,8 +1122,8 @@ update_stmt_use (use_operand_p use) /* Check if it's easy to determine if STMT needs a vuse or vdef if we ignore operand I. Returns -1 if it's not easy - (and hence it's unknown), 0 if it won't need a vop, 1 if it - needs a vuse and 2 if it needs a vdef. */ + (and hence it's unknown), 0 if it won't need a vop, BF_VUSE if it + needs a vuse and BF_VDEF|BF_VUSE if it needs a vdef. */ static int easy_stmt_p (gimple *stmt, unsigned i) { @@ -1170,10 +1135,10 @@ easy_stmt_p (gimple *stmt, unsigned i) gcc_assert (i == 0 || i == 1); if (i == 0 && gimple_assign_load_p (stmt)) /* LHS ignored, but RHS is load. */ - return 1; + return BF_VUSE; if (i == 1 && gimple_store_p (stmt)) /* RHS ignored, but LHS a store. */ - return 2; + return BF_VDEF | BF_VUSE; /* All other cases don't create VOPs (except perhaps for operand I). */ return 0; @@ -1183,14 +1148,14 @@ easy_stmt_p (gimple *stmt, unsigned i) /* For a call if we don't ignore the fndecl and that already requires a vdef, it's easy. */ if (i != 1 && !(call_flags & (ECF_NOVOPS | ECF_PURE | ECF_CONST))) - return 2; + return BF_VDEF | BF_VUSE; /* Also, if we ignore the LHS or have none there can only be a vdef if the function isn't pure (or const). */ if ((i == 0 || !gimple_call_lhs (stmt)) && !(call_flags & ECF_NOVOPS)) { /* If it's pure we definitely need a vuse. */ if ((call_flags & (ECF_PURE | ECF_CONST)) == ECF_PURE) - return 1; + return BF_VUSE; /* If it's const and we have no arguments, or we ignore the single argument (and hence have no LHS), then there won't be a vop. */ @@ -1203,10 +1168,10 @@ easy_stmt_p (gimple *stmt, unsigned i) } case GIMPLE_TRANSACTION: - return 2; + return BF_VDEF | BF_VUSE; case GIMPLE_RETURN: - return 1; + return BF_VUSE; default: return -1; @@ -1218,7 +1183,7 @@ static void ensure_vop (gimple *stmt, int flags); static int diddle_vops (gimple *stmt, int oldvop, int newvop, unsigned nop) { - int stmtvop = gimple_vdef (stmt) ? 2 : gimple_vuse (stmt) ? 1 : 0; + int stmtvop = gimple_vdef (stmt) ? BF_VDEF | BF_VUSE : gimple_vuse (stmt) ? BF_VUSE : 0; /* ??? The following might seem like a good test: gcc_assert (stmtvop >= oldvop) but our callers might have already set VOP to NULL in anticipation @@ -1248,7 +1213,7 @@ diddle_vops (gimple *stmt, int oldvop, int newvop, unsigned nop) else gcc_unreachable (); - if (newvop < 2 && gimple_vdef (stmt)) + if (newvop < BF_VDEF && gimple_vdef (stmt)) { if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) { @@ -1258,10 +1223,10 @@ diddle_vops (gimple *stmt, int oldvop, int newvop, unsigned nop) gimple_set_vdef (stmt, NULL_TREE); } - if (newvop) + if (newvop >= BF_VUSE) { gcc_assert (!is_gimple_debug (stmt)); - ensure_vop (stmt, newvop >= 2 ? opf_def : opf_use); + ensure_vop (stmt, newvop >= BF_VDEF ? opf_def : opf_use); } else if (gimple_vuse (stmt)) gimple_set_vuse (stmt, NULL_TREE); @@ -1272,40 +1237,22 @@ diddle_vops (gimple *stmt, int oldvop, int newvop, unsigned nop) static int add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) { - gimple_statement_with_ops *ops_stmt = - dyn_cast <gimple_statement_with_ops *> (stmt); - use_optype_p *puse = NULL; + use_optype_p *puse; int was_vop = 0, newvop; - /* We'd like to search the cache only - if (*pop && SSA_VAR_P (*pop)) - but we can't currently, because the list might contain stale entries - (from setting to constants or such via SET_USE). We must reuse - that entry in case it's there (or remove it and generate a new one). */ if (*pop && SSA_VAR_P (*pop)) - for (puse = &ops_stmt->use_ops; *puse; puse = &((*puse)->next)) - if ((*puse)->use_ptr.use == pop) - break; - if (puse && *puse) { - delink_imm_use (&((*puse)->use_ptr)); + puse = find_delink_use_op (stmt, pop); + /* If there's the danger that we replace the last operand that caused + a vop with one that doesn't we need to revisit everything. */ + if (!(flags & opf_no_vops) + && !is_gimple_reg (*pop) && !virtual_operand_p (*pop)) + was_vop = BF_VUSE | ((flags & opf_def) ? BF_VDEF : 0); } + else + puse = NULL; - /* If there's the danger that we replace the last operand that caused - a vop with one that doesn't we need to revisit everything. */ - if (!(flags & opf_no_vops) && *pop && SSA_VAR_P (*pop) - && !is_gimple_reg (*pop) && !virtual_operand_p (*pop)) - was_vop = (flags & opf_def) ? 2 : 1; if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL) - { - int call_flags = gimple_call_flags (stmt); - if (!(call_flags & ECF_NOVOPS)) - { - if (!(call_flags & (ECF_PURE | ECF_CONST))) - was_vop = 2; - else if (!(call_flags & ECF_CONST)) - was_vop = 1; - } - } + was_vop = get_call_vop_flags (stmt); *pop = val; @@ -1318,10 +1265,10 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) if (DECL_P (val) && !virtual_operand_p (val)) cfun->gimple_df->ssa_renaming_needed = 1; if (flags & opf_def) - gcc_assert (!puse || !*puse); + gcc_assert (!puse); else { - if (!puse || !*puse) + if (!puse) prepend_use_op (stmt, pop); else link_imm_use_stmt (&((*puse)->use_ptr), *pop, stmt); @@ -1329,9 +1276,7 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) } else { - if (TREE_THIS_VOLATILE (val)) - gimple_set_has_volatile_ops (stmt, true); - + gcc_assert (!TREE_THIS_VOLATILE (val)); /* The variable is a memory access. Add virtual operands. */ ensure_vop (stmt, flags); } @@ -1339,20 +1284,16 @@ add_ssa_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) else { gcc_assert (!val || is_gimple_min_invariant (val)); - if (puse && *puse) - *puse = (*puse)->next; - newvop = 0; - if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL) + if (puse) { - int call_flags = gimple_call_flags (stmt); - if (!(call_flags & ECF_NOVOPS)) - { - if (!(call_flags & (ECF_PURE | ECF_CONST))) - newvop = 2; - else if (!(call_flags & ECF_CONST)) - newvop = 1; - } + use_optype_p use = *puse; + *puse = use->next; + use->next = gimple_ssa_operands (cfun)->free_uses; + gimple_ssa_operands (cfun)->free_uses = use; } + newvop = 0; + if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL) + newvop = get_call_vop_flags (stmt); if (was_vop && diddle_vops (stmt, was_vop, newvop, nop) < 0) return 1; } @@ -1374,11 +1315,7 @@ ensure_vop (gimple *stmt, int flags) gimple_set_vdef (stmt, gimple_vop (cfun)); } if (!gimple_vuse (stmt)) - { - gimple_statement_with_memory_ops *mem_ops_stmt = - dyn_cast <gimple_statement_with_memory_ops *> (stmt); - add_ssa_op (stmt, &mem_ops_stmt->vuse, gimple_vop (cfun), -1, flags); - } + add_ssa_op (stmt, gimple_vuse_ptr (stmt), gimple_vop (cfun), -1, flags); if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME) { cfun->gimple_df->rename_vops = 1; @@ -1399,27 +1336,25 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) int oldvop, newvop; start_ssa_stmt_operands (); - get_expr_operands (cfun, stmt, gimple_op_ptr (stmt, nop), flags); + get_expr_operands (stmt, gimple_op_ptr (stmt, nop), flags); if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL) - maybe_add_call_vops (cfun, as_a <gcall *> (stmt)); + maybe_add_call_vops (as_a <gcall *> (stmt)); was_volatile = !!(build_flags & BF_VOLATILE); - oldvop = build_vdef ? 2 : build_vuse ? 1 : 0; + oldvop = build_flags & (BF_VDEF | BF_VUSE); /* Remove all use ops for things in op[nop]. */ for (i = 0; i < build_uses.length (); i++) { tree *op = build_uses[i]; - use_optype_p *puse = find_use_op (stmt, op); - use_optype_p use; - if (!*puse) + use_optype_p *puse = find_delink_use_op (stmt, op); + if (!puse) /* Normally we should have found the old useop cache. But debug statements might change from SOURCE_BIND (without opcache) to DEBUG_BIND (with opcache), so accept that here. */ gcc_assert(is_gimple_debug (stmt)); else { - delink_imm_use (&((*puse)->use_ptr)); - use = *puse; + use_optype_p use = *puse; *puse = use->next; use->next = gimple_ssa_operands (cfun)->free_uses; gimple_ssa_operands (cfun)->free_uses = use; @@ -1431,10 +1366,10 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) /* Now inspect the new value. */ start_ssa_stmt_operands (); - get_expr_operands (cfun, stmt, gimple_op_ptr (stmt, nop), flags); + get_expr_operands (stmt, gimple_op_ptr (stmt, nop), flags); if (nop == 1 && gimple_code (stmt) == GIMPLE_CALL) - maybe_add_call_vops (cfun, as_a <gcall *> (stmt)); - newvop = build_vdef ? 2 : build_vuse ? 1 : 0; + maybe_add_call_vops (as_a <gcall *> (stmt)); + newvop = build_flags & (BF_VDEF | BF_VUSE); /* If the op was volatile and now isn't we need to recheck everything. */ if (was_volatile && !(build_flags & BF_VOLATILE)) @@ -1452,10 +1387,10 @@ exchange_complex_op (gimple *stmt, tree *pop, tree val, unsigned nop, int flags) for (i = 0; i < build_uses.length (); i++) { tree *op = build_uses[i]; - use_optype_p *puse = find_use_op (stmt, op); + use_optype_p *puse = find_delink_use_op (stmt, op); /* All ops should be new (or removed above), otherwise we'd create strange sharing. */ - gcc_assert (!*puse); + gcc_assert (!puse); prepend_use_op (stmt, op); } @@ -1526,22 +1461,22 @@ do_full_update: } void -gimple_set_op_update (gimple *gs, unsigned i, tree val) +gimple_change_in_op (gimple *gs, tree *op_ptr, tree *pop, tree val) { - tree *pop = gimple_op_ptr (gs, i); if (!flag_try_patch || !gs->bb || !ssa_operands_active (cfun)) *pop = val; else - do_change_in_op (gs, pop, pop, val); + do_change_in_op (gs, op_ptr, pop, val); } void -gimple_change_in_op (gimple *gs, tree *op_ptr, tree *pop, tree val) +gimple_set_op_update (gimple *gs, unsigned i, tree val) { + tree *pop = gimple_op_ptr (gs, i); if (!flag_try_patch || !gs->bb || !ssa_operands_active (cfun)) *pop = val; else - do_change_in_op (gs, op_ptr, pop, val); + do_change_in_op (gs, pop, pop, val); } /* Swap operands EXP0 and EXP1 in statement STMT. No attempt is done diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h index 6e2d471cf333..ef0eaaa0e5eb 100644 --- a/gcc/tree-ssa-operands.h +++ b/gcc/tree-ssa-operands.h @@ -93,7 +93,7 @@ struct GTY(()) ssa_operands { extern bool ssa_operands_active (struct function *); extern void init_ssa_operands (struct function *fn); extern void fini_ssa_operands (struct function *); -extern bool verify_ssa_operands (struct function *, gimple *stmt); +extern bool verify_ssa_operands (gimple *stmt); extern void free_stmt_operands (struct function *, gimple *); extern void update_stmt_operands (struct function *, gimple *); extern void swap_ssa_operands (gimple *, tree *, tree *); diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 9632869ba81c..036f86450211 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1125,7 +1125,7 @@ verify_ssa (bool check_modified_stmt, bool check_ssa_operands) goto err; } - if (check_ssa_operands && verify_ssa_operands (cfun, stmt)) + if (check_ssa_operands && verify_ssa_operands (stmt)) { print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); goto err;
