static void lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data) { tree old_block = data->block; gimple stmt = gsi_stmt (*gsi); tree new_block = gimple_bind_block (stmt); if (new_block) { if (new_block == old_block) { /* The outermost block of the original function may not be the outermost statement chain of the gimplified function. So we may see the outermost block just inside the function. */ gcc_assert (new_block == DECL_INITIAL (current_function_decl)); new_block = NULL; } else { /* We do not expect to handle duplicate blocks. */ gcc_assert (!TREE_ASM_WRITTEN (new_block)); TREE_ASM_WRITTEN (new_block) = 1; /* Block tree may get clobbered by inlining. Normally this would be fixed in rest_of_decl_compilation using block notes, but since we are not going to emit them, it is up to us. */ BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block); BLOCK_SUBBLOCKS (old_block) = new_block; BLOCK_SUBBLOCKS (new_block) = NULL_TREE; BLOCK_SUPERCONTEXT (new_block) = old_block; data->block = new_block; } } record_vars (gimple_bind_vars (stmt)); lower_sequence (gimple_bind_body_ptr (stmt), data); if (new_block) { gcc_assert (data->block == new_block); BLOCK_SUBBLOCKS (new_block) = blocks_nreverse (BLOCK_SUBBLOCKS (new_block)); data->block = old_block; } /* The GIMPLE_BIND no longer carries any useful information -- kill it. */ gsi_insert_seq_before (gsi, gimple_bind_body (stmt), GSI_SAME_STMT); gsi_remove (gsi, false); }
void gsi_replace_with_seq (gimple_stmt_iterator *gsi, gimple_seq seq, bool update_eh_info) { gimple_stmt_iterator seqi; gimple *last; if (gimple_seq_empty_p (seq)) { gsi_remove (gsi, true); return; } seqi = gsi_last (seq); last = gsi_stmt (seqi); gsi_remove (&seqi, false); gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT); gsi_replace (gsi, last, update_eh_info); }
basic_block gsi_insert_seq_on_edge_immediate (edge e, gimple_seq stmts) { gimple_stmt_iterator gsi; basic_block new_bb = NULL; bool ins_after; gcc_assert (!PENDING_STMT (e)); ins_after = gimple_find_edge_insert_loc (e, &gsi, &new_bb); update_call_edge_frequencies (gimple_seq_first (stmts), gsi.bb); if (ins_after) gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT); else gsi_insert_seq_before (&gsi, stmts, GSI_NEW_STMT); return new_bb; }
tree force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr, gimple_predicate gimple_test_f, tree var, bool before, enum gsi_iterator_update m) { gimple_seq stmts; expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var); if (!gimple_seq_empty_p (stmts)) { if (before) gsi_insert_seq_before (gsi, stmts, m); else gsi_insert_seq_after (gsi, stmts, m); } return expr; }
static void handle_task_call (gimple_stmt_iterator gsi, const tracked_func_t* tf) { /* iterator points to the call instruction */ /* . generate the following statement list: generate type T; declare T* var; var = call __xkaapi_pushdata(sizeof(T)); foreach args, var->member = local_value; call __xkaapi_pushtask(); call __xkaapi_barrier(); */ tree dummy_adapter; tree sp; tree thread; gimple_seq stmts; gimple call; init_decls(); /* kaapi_pushdata_aligned */ gen_alloca_stmts(&stmts, &sp); gsi_insert_seq_before(&gsi, stmts, GSI_SAME_STMT); /* fixme: gimple_seq_free(alloca_stmts); */ /* generate the adapter routine */ /* dummy_adapter = create_dummy_adapter(); */ /* kaapi_pushtask(self_thread, sp); */ thread = build_int_cst(ptr_type_node, 0xdeadc0c0); call = gimple_build_call(kaapi_pushtask_decl, 2, sp, thread); gsi_insert_before(&gsi, call, GSI_SAME_STMT); /* kaapi_barrier(); */ call = gimple_build_call(kaapi_barrier_decl, 0); gsi_replace(&gsi, call, true); }
void gsi_commit_one_edge_insert (edge e, basic_block *new_bb) { if (new_bb) *new_bb = NULL; if (PENDING_STMT (e)) { gimple_stmt_iterator gsi; gimple_seq seq = PENDING_STMT (e); bool ins_after; PENDING_STMT (e) = NULL; ins_after = gimple_find_edge_insert_loc (e, &gsi, new_bb); update_call_edge_frequencies (gimple_seq_first (seq), gsi.bb); if (ins_after) gsi_insert_seq_after (&gsi, seq, GSI_NEW_STMT); else gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT); } }
void gimple_regimplify_operands (gimple stmt, gimple_stmt_iterator *gsi_p) { size_t i, num_ops; tree lhs; gimple_seq pre = NULL; gimple post_stmt = NULL; push_gimplify_context (gimple_in_ssa_p (cfun)); switch (gimple_code (stmt)) { case GIMPLE_COND: gimplify_expr (gimple_cond_lhs_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); gimplify_expr (gimple_cond_rhs_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); break; case GIMPLE_SWITCH: gimplify_expr (gimple_switch_index_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); break; case GIMPLE_OMP_ATOMIC_LOAD: gimplify_expr (gimple_omp_atomic_load_rhs_ptr (stmt), &pre, NULL, is_gimple_val, fb_rvalue); break; case GIMPLE_ASM: { size_t i, noutputs = gimple_asm_noutputs (stmt); const char *constraint, **oconstraints; bool allows_mem, allows_reg, is_inout; oconstraints = (const char **) alloca ((noutputs) * sizeof (const char *)); for (i = 0; i < noutputs; i++) { tree op = gimple_asm_output_op (stmt, i); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); oconstraints[i] = constraint; parse_output_constraint (&constraint, i, 0, 0, &allows_mem, &allows_reg, &is_inout); gimplify_expr (&TREE_VALUE (op), &pre, NULL, is_inout ? is_gimple_min_lval : is_gimple_lvalue, fb_lvalue | fb_mayfail); } for (i = 0; i < gimple_asm_ninputs (stmt); i++) { tree op = gimple_asm_input_op (stmt, i); constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op))); parse_input_constraint (&constraint, 0, 0, noutputs, 0, oconstraints, &allows_mem, &allows_reg); if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem) allows_reg = 0; if (!allows_reg && allows_mem) gimplify_expr (&TREE_VALUE (op), &pre, NULL, is_gimple_lvalue, fb_lvalue | fb_mayfail); else gimplify_expr (&TREE_VALUE (op), &pre, NULL, is_gimple_asm_val, fb_rvalue); } } break; default: /* NOTE: We start gimplifying operands from last to first to make sure that side-effects on the RHS of calls, assignments and ASMs are executed before the LHS. The ordering is not important for other statements. */ num_ops = gimple_num_ops (stmt); for (i = num_ops; i > 0; i--) { tree op = gimple_op (stmt, i - 1); if (op == NULL_TREE) continue; if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt))) gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue); else if (i == 2 && is_gimple_assign (stmt) && num_ops == 2 && get_gimple_rhs_class (gimple_expr_code (stmt)) == GIMPLE_SINGLE_RHS) gimplify_expr (&op, &pre, NULL, rhs_predicate_for (gimple_assign_lhs (stmt)), fb_rvalue); else if (i == 2 && is_gimple_call (stmt)) { if (TREE_CODE (op) == FUNCTION_DECL) continue; gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue); } else gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue); gimple_set_op (stmt, i - 1, op); } lhs = gimple_get_lhs (stmt); /* If the LHS changed it in a way that requires a simple RHS, create temporary. */ if (lhs && !is_gimple_reg (lhs)) { bool need_temp = false; if (is_gimple_assign (stmt) && num_ops == 2 && get_gimple_rhs_class (gimple_expr_code (stmt)) == GIMPLE_SINGLE_RHS) gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL, rhs_predicate_for (gimple_assign_lhs (stmt)), fb_rvalue); else if (is_gimple_reg (lhs)) { if (is_gimple_reg_type (TREE_TYPE (lhs))) { if (is_gimple_call (stmt)) { i = gimple_call_flags (stmt); if ((i & ECF_LOOPING_CONST_OR_PURE) || !(i & (ECF_CONST | ECF_PURE))) need_temp = true; } if (stmt_can_throw_internal (stmt)) need_temp = true; } } else { if (is_gimple_reg_type (TREE_TYPE (lhs))) need_temp = true; else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode) { if (is_gimple_call (stmt)) { tree fndecl = gimple_call_fndecl (stmt); if (!aggregate_value_p (TREE_TYPE (lhs), fndecl) && !(fndecl && DECL_RESULT (fndecl) && DECL_BY_REFERENCE (DECL_RESULT (fndecl)))) need_temp = true; } else need_temp = true; } } if (need_temp) { tree temp = create_tmp_reg (TREE_TYPE (lhs), NULL); if (gimple_in_ssa_p (cfun)) temp = make_ssa_name (temp, NULL); gimple_set_lhs (stmt, temp); post_stmt = gimple_build_assign (lhs, temp); } } break; } if (!gimple_seq_empty_p (pre)) gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT); if (post_stmt) gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT); pop_gimplify_context (NULL); }
static void lower_gimple_bind (gimple_stmt_iterator *gsi, struct lower_data *data) { tree old_block = data->block; gbind *stmt = as_a <gbind *> (gsi_stmt (*gsi)); tree new_block = gimple_bind_block (stmt); if (new_block) { if (new_block == old_block) { /* The outermost block of the original function may not be the outermost statement chain of the gimplified function. So we may see the outermost block just inside the function. */ gcc_assert (new_block == DECL_INITIAL (current_function_decl)); new_block = NULL; } else { /* We do not expect to handle duplicate blocks. */ gcc_assert (!TREE_ASM_WRITTEN (new_block)); TREE_ASM_WRITTEN (new_block) = 1; /* Block tree may get clobbered by inlining. Normally this would be fixed in rest_of_decl_compilation using block notes, but since we are not going to emit them, it is up to us. */ BLOCK_CHAIN (new_block) = BLOCK_SUBBLOCKS (old_block); BLOCK_SUBBLOCKS (old_block) = new_block; BLOCK_SUBBLOCKS (new_block) = NULL_TREE; BLOCK_SUPERCONTEXT (new_block) = old_block; data->block = new_block; } } record_vars (gimple_bind_vars (stmt)); /* Scrap DECL_CHAIN up to BLOCK_VARS to ease GC after we no longer need gimple_bind_vars. */ tree next; /* BLOCK_VARS and gimple_bind_vars share a common sub-chain. Find it by marking all BLOCK_VARS. */ if (gimple_bind_block (stmt)) for (tree t = BLOCK_VARS (gimple_bind_block (stmt)); t; t = DECL_CHAIN (t)) TREE_VISITED (t) = 1; for (tree var = gimple_bind_vars (stmt); var && ! TREE_VISITED (var); var = next) { next = DECL_CHAIN (var); DECL_CHAIN (var) = NULL_TREE; } /* Unmark BLOCK_VARS. */ if (gimple_bind_block (stmt)) for (tree t = BLOCK_VARS (gimple_bind_block (stmt)); t; t = DECL_CHAIN (t)) TREE_VISITED (t) = 0; lower_sequence (gimple_bind_body_ptr (stmt), data); if (new_block) { gcc_assert (data->block == new_block); BLOCK_SUBBLOCKS (new_block) = blocks_nreverse (BLOCK_SUBBLOCKS (new_block)); data->block = old_block; } /* The GIMPLE_BIND no longer carries any useful information -- kill it. */ gsi_insert_seq_before (gsi, gimple_bind_body (stmt), GSI_SAME_STMT); gsi_remove (gsi, false); }