static inline void finalize_ssa_uses (struct function *fn, gimple *stmt) { unsigned new_i; struct use_optype_d new_list; 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); build_uses.safe_insert (0, gimple_vuse_ptr (stmt)); } 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) { for (ptr = old_ops; ptr->next; ptr = ptr->next) delink_imm_use (USE_OP_PTR (ptr)); delink_imm_use (USE_OP_PTR (ptr)); ptr->next = gimple_ssa_operands (fn)->free_uses; gimple_ssa_operands (fn)->free_uses = old_ops; } /* 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 && gimple_vuse (stmt) == NULL_TREE) { gimple_set_vuse (stmt, gimple_vop (fn)); fn->gimple_df->rename_vops = 1; fn->gimple_df->ssa_renaming_needed = 1; } /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < build_uses.length (); new_i++) { tree *op = build_uses[new_i]; last = add_use_op (fn, stmt, op, last); } /* Now set the stmt's operands. */ gimple_set_use_ops (stmt, new_list.next); }
static inline void finalize_ssa_uses (gimple stmt) { unsigned new_i; struct use_optype_d new_list; 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); VEC_safe_insert (tree, heap, build_uses, 0, (tree)gimple_vuse_ptr (stmt)); } 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) { for (ptr = old_ops; ptr; ptr = ptr->next) delink_imm_use (USE_OP_PTR (ptr)); old_ops->next = gimple_ssa_operands (cfun)->free_uses; gimple_ssa_operands (cfun)->free_uses = old_ops; } /* 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 && gimple_vuse (stmt) == NULL_TREE) { gimple_set_vuse (stmt, gimple_vop (cfun)); mark_sym_for_renaming (gimple_vop (cfun)); } /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < VEC_length (tree, build_uses); new_i++) last = add_use_op (stmt, (tree *) VEC_index (tree, build_uses, new_i), last); /* Now set the stmt's operands. */ gimple_set_use_ops (stmt, new_list.next); }
void free_stmt_operands (gimple stmt) { def_optype_p defs = gimple_def_ops (stmt), last_def; use_optype_p uses = gimple_use_ops (stmt), last_use; if (defs) { for (last_def = defs; last_def->next; last_def = last_def->next) continue; last_def->next = gimple_ssa_operands (cfun)->free_defs; gimple_ssa_operands (cfun)->free_defs = defs; gimple_set_def_ops (stmt, NULL); } if (uses) { for (last_use = uses; last_use->next; last_use = last_use->next) delink_imm_use (USE_OP_PTR (last_use)); delink_imm_use (USE_OP_PTR (last_use)); last_use->next = gimple_ssa_operands (cfun)->free_uses; gimple_ssa_operands (cfun)->free_uses = uses; gimple_set_use_ops (stmt, NULL); } if (gimple_has_mem_ops (stmt)) { gimple_set_vuse (stmt, NULL_TREE); gimple_set_vdef (stmt, NULL_TREE); } }
static void adjust_simduid_builtins (hash_table<simduid_to_vf> *htab) { basic_block bb; FOR_EACH_BB_FN (bb, cfun) { gimple_stmt_iterator i; for (i = gsi_start_bb (bb); !gsi_end_p (i); ) { unsigned int vf = 1; enum internal_fn ifn; gimple *stmt = gsi_stmt (i); tree t; if (!is_gimple_call (stmt) || !gimple_call_internal_p (stmt)) { gsi_next (&i); continue; } ifn = gimple_call_internal_fn (stmt); switch (ifn) { case IFN_GOMP_SIMD_LANE: case IFN_GOMP_SIMD_VF: case IFN_GOMP_SIMD_LAST_LANE: break; case IFN_GOMP_SIMD_ORDERED_START: case IFN_GOMP_SIMD_ORDERED_END: if (integer_onep (gimple_call_arg (stmt, 0))) { enum built_in_function bcode = (ifn == IFN_GOMP_SIMD_ORDERED_START ? BUILT_IN_GOMP_ORDERED_START : BUILT_IN_GOMP_ORDERED_END); gimple *g = gimple_build_call (builtin_decl_explicit (bcode), 0); tree vdef = gimple_vdef (stmt); gimple_set_vdef (g, vdef); SSA_NAME_DEF_STMT (vdef) = g; gimple_set_vuse (g, gimple_vuse (stmt)); gsi_replace (&i, g, true); continue; } gsi_remove (&i, true); unlink_stmt_vdef (stmt); continue; default: gsi_next (&i); continue; } tree arg = gimple_call_arg (stmt, 0); gcc_assert (arg != NULL_TREE); gcc_assert (TREE_CODE (arg) == SSA_NAME); simduid_to_vf *p = NULL, data; data.simduid = DECL_UID (SSA_NAME_VAR (arg)); /* Need to nullify loop safelen field since it's value is not valid after transformation. */ if (bb->loop_father && bb->loop_father->safelen > 0) bb->loop_father->safelen = 0; if (htab) { p = htab->find (&data); if (p) vf = p->vf; } switch (ifn) { case IFN_GOMP_SIMD_VF: t = build_int_cst (unsigned_type_node, vf); break; case IFN_GOMP_SIMD_LANE: t = build_int_cst (unsigned_type_node, 0); break; case IFN_GOMP_SIMD_LAST_LANE: t = gimple_call_arg (stmt, 1); break; default: gcc_unreachable (); } update_call_from_tree (&i, t); gsi_next (&i); } }
static void use_internal_fn (gcall *call) { /* We'll be inserting another call with the same arguments after the lhs has been set, so prevent any possible coalescing failure from having both values live at once. See PR 71020. */ replace_abnormal_ssa_names (call); unsigned nconds = 0; auto_vec<gimple *, 12> conds; if (can_test_argument_range (call)) { gen_shrink_wrap_conditions (call, conds, &nconds); gcc_assert (nconds != 0); } else gcc_assert (edom_only_function (call)); internal_fn ifn = replacement_internal_fn (call); gcc_assert (ifn != IFN_LAST); /* Construct the new call, with the same arguments as the original one. */ auto_vec <tree, 16> args; unsigned int nargs = gimple_call_num_args (call); for (unsigned int i = 0; i < nargs; ++i) args.safe_push (gimple_call_arg (call, i)); gcall *new_call = gimple_build_call_internal_vec (ifn, args); gimple_set_location (new_call, gimple_location (call)); gimple_call_set_nothrow (new_call, gimple_call_nothrow_p (call)); /* Transfer the LHS to the new call. */ tree lhs = gimple_call_lhs (call); gimple_call_set_lhs (new_call, lhs); gimple_call_set_lhs (call, NULL_TREE); SSA_NAME_DEF_STMT (lhs) = new_call; /* Insert the new call. */ gimple_stmt_iterator gsi = gsi_for_stmt (call); gsi_insert_before (&gsi, new_call, GSI_SAME_STMT); if (nconds == 0) { /* Skip the call if LHS == LHS. If we reach here, EDOM is the only valid errno value and it is used iff the result is NaN. */ conds.quick_push (gimple_build_cond (EQ_EXPR, lhs, lhs, NULL_TREE, NULL_TREE)); nconds++; /* Try replacing the original call with a direct assignment to errno, via an internal function. */ if (set_edom_supported_p () && !stmt_ends_bb_p (call)) { gimple_stmt_iterator gsi = gsi_for_stmt (call); gcall *new_call = gimple_build_call_internal (IFN_SET_EDOM, 0); gimple_set_vuse (new_call, gimple_vuse (call)); gimple_set_vdef (new_call, gimple_vdef (call)); SSA_NAME_DEF_STMT (gimple_vdef (new_call)) = new_call; gimple_set_location (new_call, gimple_location (call)); gsi_replace (&gsi, new_call, false); call = new_call; } } shrink_wrap_one_built_in_call_with_conds (call, conds, nconds); }