From patchwork Thu Jul 15 17:13:30 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 58996 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]) by ozlabs.org (Postfix) with SMTP id 9B1B3B6F11 for ; Fri, 16 Jul 2010 03:14:03 +1000 (EST) Received: (qmail 20123 invoked by alias); 15 Jul 2010 17:14:01 -0000 Received: (qmail 20106 invoked by uid 22791); 15 Jul 2010 17:14:00 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 15 Jul 2010 17:13:53 +0000 Received: (qmail 15204 invoked from network); 15 Jul 2010 17:13:51 -0000 Received: from unknown (HELO ?84.152.221.24?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 15 Jul 2010 17:13:51 -0000 Message-ID: <4C3F41BA.7070905@codesourcery.com> Date: Thu, 15 Jul 2010 19:13:30 +0200 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.10) Gecko/20100625 Thunderbird/3.0.5 MIME-Version: 1.0 To: Jeff Law CC: GCC Patches Subject: Re: Emit more REG_EQUIV notes for function args (PR42235) References: <4C3D9C06.60901@codesourcery.com> <4C3E07EF.1030306@redhat.com> <4C3E2C62.40808@codesourcery.com> <4C3E39F0.7050208@redhat.com> In-Reply-To: <4C3E39F0.7050208@redhat.com> 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 On 07/15/2010 12:28 AM, Jeff Law wrote: > On 07/14/10 15:30, Bernd Schmidt wrote: >> If necessary I can try to test for a single insn with single_set and >> push it to the sequence otherwise. >> > For the mn103, the conversions were single insns... > > Ultimately, I think you have to peek at the insn(s) and see what > registers they set/clobber. How's this? Bootstrapped and tested on i686-linux. ARM tests in progress. Bernd PR target/42235 * function.c (record_hard_reg_sets): New static function. (assign_parm_setup_reg): If an optab for extending exists and the generated code clobbbers no hard regs, emit the insn directly and create a REG_EQUIV note. Index: gcc/function.c =================================================================== --- gcc.orig/function.c +++ gcc/function.c @@ -2854,6 +2854,21 @@ assign_parm_setup_block (struct assign_p SET_DECL_RTL (parm, stack_parm); } +/* A subroutine of assign_parm_setup_reg, called through note_stores. + This collects sets and clobbers of hard registers in a HARD_REG_SET, + which is pointed to by DATA. */ +static void +record_hard_reg_sets (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data) +{ + HARD_REG_SET *pset = (HARD_REG_SET *)data; + if (REG_P (x) && REGNO (x) < FIRST_PSEUDO_REGISTER) + { + int nregs = hard_regno_nregs[REGNO (x)][GET_MODE (x)]; + while (nregs-- > 0) + SET_HARD_REG_BIT (*pset, REGNO (x) + nregs); + } +} + /* A subroutine of assign_parms. Allocate a pseudo to hold the current parameter. Get it there. Perform all ABI specified conversions. */ @@ -2861,10 +2876,12 @@ static void assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, struct assign_parm_data_one *data) { - rtx parmreg; + rtx parmreg, validated_mem; + rtx equiv_stack_parm; enum machine_mode promoted_nominal_mode; int unsignedp = TYPE_UNSIGNED (TREE_TYPE (parm)); bool did_conversion = false; + bool need_conversion, moved; /* Store the parm in a pseudoregister during the function, but we may need to do it in a wider mode. Using 2 here makes the result @@ -2893,11 +2910,16 @@ assign_parm_setup_reg (struct assign_par /* Copy the value into the register, thus bridging between assign_parm_find_data_types and expand_expr_real_1. */ - if (data->nominal_mode != data->passed_mode - || promoted_nominal_mode != data->promoted_mode) - { - int save_tree_used; + equiv_stack_parm = data->stack_parm; + validated_mem = validize_mem (data->entry_parm); + + need_conversion = (data->nominal_mode != data->passed_mode + || promoted_nominal_mode != data->promoted_mode); + moved = false; + + if (need_conversion) + { /* ENTRY_PARM has been converted to PROMOTED_MODE, its mode, by the caller. We now have to convert it to NOMINAL_MODE, if different. However, PARMREG may be in @@ -2913,13 +2935,70 @@ assign_parm_setup_reg (struct assign_par In addition, the conversion may involve a call, which could clobber parameters which haven't been copied to pseudo - registers yet. Therefore, we must first copy the parm to - a pseudo reg here, and save the conversion until after all + registers yet. + + First, we try to emit an insn which performs the necessary + conversion. We verify that this insn does not clobber any + hard registers. */ + + enum insn_code icode; + rtx op0, op1; + + icode = can_extend_p (promoted_nominal_mode, data->passed_mode, + unsignedp); + + op0 = parmreg; + op1 = validated_mem; + if (icode != CODE_FOR_nothing + && insn_data[icode].operand[0].predicate (op0, promoted_nominal_mode) + && insn_data[icode].operand[1].predicate (op1, data->passed_mode)) + { + enum rtx_code code = unsignedp ? ZERO_EXTEND : SIGN_EXTEND; + rtx insn, insns; + HARD_REG_SET hardregs; + + start_sequence (); + insn = gen_extend_insn (op0, op1, promoted_nominal_mode, + data->passed_mode, unsignedp); + emit_insn (insn); + insns = get_insns (); + + moved = true; + CLEAR_HARD_REG_SET (hardregs); + for (insn = insns; insn && moved; insn = NEXT_INSN (insn)) + { + if (INSN_P (insn)) + note_stores (PATTERN (insn), record_hard_reg_sets, + &hardregs); + if (!hard_reg_set_empty_p (hardregs)) + moved = false; + } + + end_sequence (); + + if (moved) + { + emit_insn (insns); + equiv_stack_parm = gen_rtx_fmt_e (code, GET_MODE (parmreg), + equiv_stack_parm); + } + } + } + + if (moved) + /* Nothing to do. */ + ; + else if (need_conversion) + { + /* We did not have an insn to convert directly, or the sequence + generated appeared unsafe. We must first copy the parm to a + pseudo reg, and save the conversion until after all parameters have been moved. */ + int save_tree_used; rtx tempreg = gen_reg_rtx (GET_MODE (data->entry_parm)); - emit_move_insn (tempreg, validize_mem (data->entry_parm)); + emit_move_insn (tempreg, validated_mem); push_to_sequence2 (all->first_conversion_insn, all->last_conversion_insn); tempreg = convert_to_mode (data->nominal_mode, tempreg, unsignedp); @@ -2949,7 +3028,7 @@ assign_parm_setup_reg (struct assign_par did_conversion = true; } else - emit_move_insn (parmreg, validize_mem (data->entry_parm)); + emit_move_insn (parmreg, validated_mem); /* If we were passed a pointer but the actual value can safely live in a register, put it in one. */ @@ -3034,7 +3113,7 @@ assign_parm_setup_reg (struct assign_par } else if ((set = single_set (linsn)) != 0 && SET_DEST (set) == parmreg) - set_unique_reg_note (linsn, REG_EQUIV, data->stack_parm); + set_unique_reg_note (linsn, REG_EQUIV, equiv_stack_parm); } /* For pointer data type, suggest pointer register. */