/* For bounds used in CI check if bounds are produced by intersection and we may use outer bounds instead. If transformation is possible then fix check statement and recompute its info. */ static void chkp_use_outer_bounds_if_possible (struct check_info *ci) { gimple *bnd_def; tree bnd1, bnd2, bnd_res = NULL; int check_res1, check_res2; if (TREE_CODE (ci->bounds) != SSA_NAME) return; bnd_def = SSA_NAME_DEF_STMT (ci->bounds); if (gimple_code (bnd_def) != GIMPLE_CALL || gimple_call_fndecl (bnd_def) != chkp_intersect_fndecl) return; if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Check if bounds intersection is redundant: \n"); fprintf (dump_file, " check: "); print_gimple_stmt (dump_file, ci->stmt, 0, 0); fprintf (dump_file, " intersection: "); print_gimple_stmt (dump_file, bnd_def, 0, 0); fprintf (dump_file, "\n"); } bnd1 = gimple_call_arg (bnd_def, 0); bnd2 = gimple_call_arg (bnd_def, 1); check_res1 = chkp_get_check_result (ci, bnd1); check_res2 = chkp_get_check_result (ci, bnd2); if (check_res1 == 1) bnd_res = bnd2; else if (check_res1 == -1) bnd_res = bnd1; else if (check_res2 == 1) bnd_res = bnd1; else if (check_res2 == -1) bnd_res = bnd2; if (bnd_res) { if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, " action: use "); print_generic_expr (dump_file, bnd2, 0); fprintf (dump_file, " instead of "); print_generic_expr (dump_file, ci->bounds, 0); fprintf (dump_file, "\n"); } ci->bounds = bnd_res; gimple_call_set_arg (ci->stmt, 1, bnd_res); update_stmt (ci->stmt); chkp_fill_check_info (ci->stmt, ci); } }
void backprop::optimize_builtin_call (gcall *call, tree lhs, const usage_info *info) { /* If we have an f such that -f(x) = f(-x), and if the sign of the result doesn't matter, strip any sign operations from the input. */ if (info->flags.ignore_sign && negate_mathfn_p (gimple_call_combined_fn (call))) { tree new_arg = strip_sign_op (gimple_call_arg (call, 0)); if (new_arg) { prepare_change (lhs); gimple_call_set_arg (call, 0, new_arg); complete_change (call); } } }
static void lower_builtin_posix_memalign (gimple_stmt_iterator *gsi) { gimple stmt, call = gsi_stmt (*gsi); tree pptr = gimple_call_arg (call, 0); tree align = gimple_call_arg (call, 1); tree res = gimple_call_lhs (call); tree ptr = create_tmp_reg (ptr_type_node, NULL); if (TREE_CODE (pptr) == ADDR_EXPR) { tree tem = create_tmp_var (ptr_type_node, NULL); TREE_ADDRESSABLE (tem) = 1; gimple_call_set_arg (call, 0, build_fold_addr_expr (tem)); stmt = gimple_build_assign (ptr, tem); } else stmt = gimple_build_assign (ptr, fold_build2 (MEM_REF, ptr_type_node, pptr, build_int_cst (ptr_type_node, 0))); if (res == NULL_TREE) { res = create_tmp_reg (integer_type_node, NULL); gimple_call_set_lhs (call, res); } tree align_label = create_artificial_label (UNKNOWN_LOCATION); tree noalign_label = create_artificial_label (UNKNOWN_LOCATION); gimple cond = gimple_build_cond (EQ_EXPR, res, integer_zero_node, align_label, noalign_label); gsi_insert_after (gsi, cond, GSI_NEW_STMT); gsi_insert_after (gsi, gimple_build_label (align_label), GSI_NEW_STMT); gsi_insert_after (gsi, stmt, GSI_NEW_STMT); stmt = gimple_build_call (builtin_decl_implicit (BUILT_IN_ASSUME_ALIGNED), 2, ptr, align); gimple_call_set_lhs (stmt, ptr); gsi_insert_after (gsi, stmt, GSI_NEW_STMT); stmt = gimple_build_assign (fold_build2 (MEM_REF, ptr_type_node, pptr, build_int_cst (ptr_type_node, 0)), ptr); gsi_insert_after (gsi, stmt, GSI_NEW_STMT); gsi_insert_after (gsi, gimple_build_label (noalign_label), GSI_NEW_STMT); }
static void change_orig_node(struct visited *visited, gimple stmt, const_tree orig_node, tree new_node, unsigned int num) { tree cast_lhs = cast_to_orig_type(visited, stmt, orig_node, new_node); switch (gimple_code(stmt)) { case GIMPLE_RETURN: gimple_return_set_retval(as_a_greturn(stmt), cast_lhs); break; case GIMPLE_CALL: gimple_call_set_arg(stmt, num - 1, cast_lhs); break; case GIMPLE_ASM: change_size_overflow_asm_input(as_a_gasm(stmt), cast_lhs); break; default: debug_gimple_stmt(stmt); gcc_unreachable(); } update_stmt(stmt); }