From patchwork Sat Mar 30 17:11:45 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom de Vries X-Patchwork-Id: 232539 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 9F1CB2C009B for ; Sun, 31 Mar 2013 04:13:26 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:in-reply-to:subject:content-type:mime-version:message-id :date; q=dns; s=default; b=VUE5FzpyR/kWkJOczTLyQAu0vG5NrT9BhQFcT eMXllRMdDTVInoJfm4l9Ns/IOEyyBY4Z34YIF/fC6uqkSzBnvHJUH7RRWlbWanrQ wP0EwOVaZaVm7w4FU+fYqJmvwvl2ZDh8PusxUfoCp13JqDjSITCTyYsuqOtcb8vn da/25Y= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:in-reply-to:subject:content-type:mime-version:message-id :date; s=default; bh=omQkO4AoexRAaxnXaI/PvhXS1To=; b=T7VOkS1aHzw uQqPTPG8QHwq4yOUNPtrs591MrEo4saJ2prjmkcwLkfefyIYkcMZY+t1lGeXbZMj jPPUipYRCaM2bFYs8PF0SL/UBduqhhaQ/zPFW5V3vkhjPsCFPVi/MIE2Fxd149jN VJdDyFWd+Kr+BL4OwduY6jvCxd6wH+lo= Received: (qmail 9587 invoked by alias); 30 Mar 2013 17:12:00 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 9083 invoked by uid 89); 30 Mar 2013 17:11:52 -0000 X-Spam-SWARE-Status: No, score=-4.1 required=5.0 tests=AWL, BAYES_00, KHOP_RCVD_UNTRUST, KHOP_THREADED, RCVD_IN_HOSTKARMA_W, RCVD_IN_HOSTKARMA_WL, TW_TJ autolearn=ham version=3.3.1 Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Sat, 30 Mar 2013 17:11:48 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1ULzJi-00038a-Jb from Tom_deVries@mentor.com ; Sat, 30 Mar 2013 10:11:46 -0700 Received: from SVR-ORW-FEM-03.mgc.mentorg.com ([147.34.97.39]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Sat, 30 Mar 2013 10:11:45 -0700 Received: from build1-lucid-cs (147.34.91.1) by svr-orw-fem-03.mgc.mentorg.com (147.34.97.39) with Microsoft SMTP Server id 14.1.289.1; Sat, 30 Mar 2013 10:11:45 -0700 Received: by build1-lucid-cs (Postfix, from userid 49877) id 7F4EA421213; Sat, 30 Mar 2013 10:11:45 -0700 (PDT) From: Tom de Vries To: Paolo Bonzini CC: gcc-patches In-Reply-To: <51558EF4.1030106@mentor.com> Subject: [PATCH][07/10] -fuse-caller-save - Use collected register usage information MIME-Version: 1.0 Message-ID: <20130330171145.7F4EA421213@build1-lucid-cs> Date: Sat, 30 Mar 2013 10:11:45 -0700 X-Virus-Found: No Paolo, This patch series adds analysis of register usage of functions for usage by IRA. The original post is here ( http://gcc.gnu.org/ml/gcc-patches/2013-01/msg01234.html ). This patch uses the information of which registers are clobbered by a call in IRA and df-scan. Bootstrapped and reg-tested on x86_64, Ada inclusive. Build and reg-tested on mips, arm, ppc and sh. Can you approve the df-scan part for trunk? Thanks, -Tom 2013-03-30 Radovan Obradovic Tom de Vries * df-scan.c (df_get_call_refs): Use get_call_reg_set_usage. * caller-save.c (setup_save_areas, save_call_clobbered_regs): Use get_call_reg_set_usage. * resource.c (mark_set_resources, mark_target_live_regs): Use get_call_reg_set_usage. * ira-int.h (struct ira_allocno): Add crossed_calls_clobbered_regs field. (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS): Define. * ira-lives.c (process_bb_node_lives): Use get_call_reg_set_usage. Calculate ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. * ira-build.c (ira_create_allocno): Init ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. (create_cap_allocno, propagate_allocno_info) (propagate_some_info_from_allocno) (copy_info_to_removed_store_destinations): Handle ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. * ira-costs.c (ira_tune_allocno_costs): Use ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS to adjust costs. diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 5e65294..39d75ad 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -441,7 +441,7 @@ setup_save_areas (void) freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); REG_SET_TO_HARD_REG_SET (hard_regs_to_save, &chain->live_throughout); - COPY_HARD_REG_SET (used_regs, call_used_reg_set); + get_call_reg_set_usage (insn, &used_regs, call_used_reg_set); /* Record all registers set in this call insn. These don't need to be saved. N.B. the call insn might set a subreg @@ -525,7 +525,7 @@ setup_save_areas (void) REG_SET_TO_HARD_REG_SET (hard_regs_to_save, &chain->live_throughout); - COPY_HARD_REG_SET (used_regs, call_used_reg_set); + get_call_reg_set_usage (insn, &used_regs, call_used_reg_set); /* Record all registers set in this call insn. These don't need to be saved. N.B. the call insn might set a subreg @@ -804,6 +804,7 @@ save_call_clobbered_regs (void) { unsigned regno; HARD_REG_SET hard_regs_to_save; + HARD_REG_SET call_def_reg_set; reg_set_iterator rsi; rtx cheap; @@ -854,7 +855,9 @@ save_call_clobbered_regs (void) AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set); AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets); AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved); - AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set); + get_call_reg_set_usage (insn, &call_def_reg_set, + call_used_reg_set); + AND_HARD_REG_SET (hard_regs_to_save, call_def_reg_set); for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (TEST_HARD_REG_BIT (hard_regs_to_save, regno)) diff --git a/gcc/df-scan.c b/gcc/df-scan.c index fdfa931..898454c 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -3398,10 +3398,13 @@ df_get_call_refs (struct df_collection_rec *collection_rec, bool is_sibling_call; unsigned int i; HARD_REG_SET defs_generated; + HARD_REG_SET fn_reg_set_usage; CLEAR_HARD_REG_SET (defs_generated); df_find_hard_reg_defs (PATTERN (insn_info->insn), &defs_generated); is_sibling_call = SIBLING_CALL_P (insn_info->insn); + get_call_reg_set_usage (insn_info->insn, &fn_reg_set_usage, + regs_invalidated_by_call); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) { @@ -3425,7 +3428,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec, NULL, bb, insn_info, DF_REF_REG_DEF, flags); } } - else if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i) + else if (TEST_HARD_REG_BIT (fn_reg_set_usage, i) /* no clobbers for regs that are the result of the call */ && !TEST_HARD_REG_BIT (defs_generated, i) && (!is_sibling_call diff --git a/gcc/ira-build.c b/gcc/ira-build.c index b1e481b..054139a 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -507,6 +507,7 @@ ira_create_allocno (int regno, bool cap_p, ALLOCNO_CALL_FREQ (a) = 0; ALLOCNO_CALLS_CROSSED_NUM (a) = 0; ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a) = 0; + CLEAR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)); #ifdef STACK_REGS ALLOCNO_NO_STACK_REG_P (a) = false; ALLOCNO_TOTAL_NO_STACK_REG_P (a) = false; @@ -904,6 +905,8 @@ create_cap_allocno (ira_allocno_t a) ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a); ALLOCNO_CHEAP_CALLS_CROSSED_NUM (cap) = ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a); + IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (cap), + ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)); if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) { fprintf (ira_dump_file, " Creating cap "); @@ -1823,6 +1826,8 @@ propagate_allocno_info (void) += ALLOCNO_CALLS_CROSSED_NUM (a); ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a) += ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a); + IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a), + ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); aclass = ALLOCNO_CLASS (a); @@ -2203,6 +2208,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a) ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a); ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a) += ALLOCNO_CHEAP_CALLS_CROSSED_NUM (from_a); + IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a), + ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a)); + ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a); if (! ALLOCNO_BAD_SPILL_P (from_a)) @@ -2828,6 +2836,8 @@ copy_info_to_removed_store_destinations (int regno) += ALLOCNO_CALLS_CROSSED_NUM (a); ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a) += ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a); + IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a), + ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); merged_p = true; diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 1de0061..8dbef3f 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -2082,6 +2082,7 @@ ira_tune_allocno_costs (void) ira_allocno_object_iterator oi; ira_object_t obj; bool skip_p; + HARD_REG_SET *crossed_calls_clobber_regs; FOR_EACH_ALLOCNO (a, ai) { @@ -2116,17 +2117,24 @@ ira_tune_allocno_costs (void) continue; rclass = REGNO_REG_CLASS (regno); cost = 0; - if (ira_hard_reg_set_intersection_p (regno, mode, call_used_reg_set) - || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) - cost += (ALLOCNO_CALL_FREQ (a) - * (ira_memory_move_cost[mode][rclass][0] - + ira_memory_move_cost[mode][rclass][1])); + crossed_calls_clobber_regs + = &(ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a)); + if (ira_hard_reg_set_intersection_p (regno, mode, + *crossed_calls_clobber_regs)) + { + if (ira_hard_reg_set_intersection_p (regno, mode, + call_used_reg_set) + || HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)) + cost += (ALLOCNO_CALL_FREQ (a) + * (ira_memory_move_cost[mode][rclass][0] + + ira_memory_move_cost[mode][rclass][1])); #ifdef IRA_HARD_REGNO_ADD_COST_MULTIPLIER - cost += ((ira_memory_move_cost[mode][rclass][0] - + ira_memory_move_cost[mode][rclass][1]) - * ALLOCNO_FREQ (a) - * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2); + cost += ((ira_memory_move_cost[mode][rclass][0] + + ira_memory_move_cost[mode][rclass][1]) + * ALLOCNO_FREQ (a) + * IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2); #endif + } if (INT_MAX - cost < reg_costs[j]) reg_costs[j] = INT_MAX; else diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 096f330..3d0e5ec 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -371,6 +371,8 @@ struct ira_allocno /* The number of calls across which it is live, but which should not affect register preferences. */ int cheap_calls_crossed_num; + /* Registers clobbered by intersected calls. */ + HARD_REG_SET crossed_calls_clobbered_regs; /* Array of usage costs (accumulated and the one updated during coloring) for each hard register of the allocno class. The member value can be NULL if all costs are the same and equal to @@ -414,6 +416,8 @@ struct ira_allocno #define ALLOCNO_CALL_FREQ(A) ((A)->call_freq) #define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num) #define ALLOCNO_CHEAP_CALLS_CROSSED_NUM(A) ((A)->cheap_calls_crossed_num) +#define ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS(A) \ + ((A)->crossed_calls_clobbered_regs) #define ALLOCNO_MEM_OPTIMIZED_DEST(A) ((A)->mem_optimized_dest) #define ALLOCNO_MEM_OPTIMIZED_DEST_P(A) ((A)->mem_optimized_dest_p) #define ALLOCNO_SOMEWHERE_RENAMED_P(A) ((A)->somewhere_renamed_p) diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 31635dd..45a00c2 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -1273,6 +1273,10 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ira_object_t obj = ira_object_id_map[i]; ira_allocno_t a = OBJECT_ALLOCNO (obj); int num = ALLOCNO_NUM (a); + HARD_REG_SET this_call_used_reg_set; + + get_call_reg_set_usage (insn, &this_call_used_reg_set, + call_used_reg_set); /* Don't allocate allocnos that cross setjmps or any call, if this function receives a nonlocal @@ -1287,9 +1291,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) if (can_throw_internal (insn)) { IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), - call_used_reg_set); + this_call_used_reg_set); IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), - call_used_reg_set); + this_call_used_reg_set); } if (sparseset_bit_p (allocnos_processed, num)) @@ -1306,6 +1310,8 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) /* Mark it as saved at the next call. */ allocno_saved_at_call[num] = last_call_num + 1; ALLOCNO_CALLS_CROSSED_NUM (a)++; + IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a), + this_call_used_reg_set); if (cheap_reg != NULL_RTX && ALLOCNO_REGNO (a) == (int) REGNO (cheap_reg)) ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)++; diff --git a/gcc/resource.c b/gcc/resource.c index 333c28f..111708c 100644 --- a/gcc/resource.c +++ b/gcc/resource.c @@ -647,10 +647,12 @@ mark_set_resources (rtx x, struct resources *res, int in_dest, if (mark_type == MARK_SRC_DEST_CALL) { rtx link; + HARD_REG_SET regs; res->cc = res->memory = 1; - IOR_HARD_REG_SET (res->regs, regs_invalidated_by_call); + get_call_reg_set_usage (x, ®s, regs_invalidated_by_call); + IOR_HARD_REG_SET (res->regs, regs); for (link = CALL_INSN_FUNCTION_USAGE (x); link; link = XEXP (link, 1)) @@ -996,11 +998,15 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res) if (CALL_P (real_insn)) { + HARD_REG_SET regs_invalidated_by_this_call; /* CALL clobbers all call-used regs that aren't fixed except sp, ap, and fp. Do this before setting the result of the call live. */ - AND_COMPL_HARD_REG_SET (current_live_regs, + get_call_reg_set_usage (real_insn, + ®s_invalidated_by_this_call, regs_invalidated_by_call); + AND_COMPL_HARD_REG_SET (current_live_regs, + regs_invalidated_by_this_call); /* A CALL_INSN sets any global register live, since it may have been modified by the call. */