From patchwork Tue Mar 29 17:10:56 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: "H.J. Lu" X-Patchwork-Id: 88818 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 A084CB6F01 for ; Wed, 30 Mar 2011 04:11:12 +1100 (EST) Received: (qmail 9009 invoked by alias); 29 Mar 2011 17:11:07 -0000 Received: (qmail 8974 invoked by uid 22791); 29 Mar 2011 17:11:03 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, TW_FN X-Spam-Check-By: sourceware.org Received: from mail-ww0-f51.google.com (HELO mail-ww0-f51.google.com) (74.125.82.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 29 Mar 2011 17:10:58 +0000 Received: by wwf26 with SMTP id 26so440109wwf.8 for ; Tue, 29 Mar 2011 10:10:56 -0700 (PDT) MIME-Version: 1.0 Received: by 10.227.140.80 with SMTP id h16mr17567wbu.127.1301418656674; Tue, 29 Mar 2011 10:10:56 -0700 (PDT) Received: by 10.216.50.66 with HTTP; Tue, 29 Mar 2011 10:10:56 -0700 (PDT) In-Reply-To: <201103241651.28202.ebotcazou@adacore.com> References: <20110214185738.GA13004@intel.com> <201103230922.34330.ebotcazou@adacore.com> <201103241651.28202.ebotcazou@adacore.com> Date: Tue, 29 Mar 2011 10:10:56 -0700 Message-ID: Subject: Re: [x32] PATCH: PR middle-end/47725: [x32] error: unable to find a register to spill in class DIREG From: "H.J. Lu" To: Eric Botcazou Cc: Bernd Schmidt , Richard Henderson , Uros Bizjak , gcc-patches@gcc.gnu.org, Jeff Law X-IsSubscribed: yes 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 Thu, Mar 24, 2011 at 8:51 AM, Eric Botcazou wrote: >> Pointer is promoted to Pmode from ptr_mode. > > Indeed.  However the problem is the 2 in assign_parm_setup_reg: > >  /* 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 >     consistent with promote_decl_mode and thus expand_expr_real_1.  */ >  promoted_nominal_mode >   = promote_function_mode (data->nominal_type, data->nominal_mode, &unsignedp, >                             TREE_TYPE (current_function_decl), 2); > > which is supposed to match the 2 in promote_decl_mode: > >  if (TREE_CODE (decl) == RESULT_DECL >      || TREE_CODE (decl) == PARM_DECL) >    pmode = promote_function_mode (type, mode, &unsignedp, >                                   TREE_TYPE (current_function_decl), 2); >  else >    pmode = promote_mode (type, mode, &unsignedp); > > but doesn't match the 0 in assign_parm_find_data_types: > >  promoted_mode = promote_function_mode (passed_type, passed_mode, &unsignedp, >                                         TREE_TYPE (current_function_decl), 0); > > so you get the redundant extension in the callee.  The solution is to define > the promote_function_mode hook for x86 to something like: > > static enum machine_mode > ix86_promote_function_mode (const_tree type, >                            enum machine_mode mode, >                            int *punsignedp, >                            const_tree fntype ATTRIBUTE_UNUSED, >                            int for_return ATTRIBUTE_UNUSED) > { >  if (POINTER_TYPE_P (type)) >    { >      *punsignedp = POINTERS_EXTEND_UNSIGNED; >      return Pmode; >    } > >  return mode; > } > Here is the patch. precompute_register_parameters change is needed for --- extern __thread int ttt; extern void bar (void *); void foo1 () { bar (&ttt); } --- I used /* Pointer function arguments and return values are promoted to Pmode. */ static enum machine_mode ix86_promote_function_mode (const_tree type, enum machine_mode mode, int *punsignedp, const_tree fntype, int for_return) { if (for_return != 1 && POINTER_TYPE_P (type)) { *punsignedp = POINTERS_EXTEND_UNSIGNED; return Pmode; } return default_promote_function_mode (type, mode, punsignedp, fntype, for_return); } since for_return == 1 has to match function_value, which I want to keep as is. default_promote_function_mode handles i386 PROMOTE_MODE. Tested it on Linux/ia32 and Linux/x86-64. OK for trunk? Thanks. diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32 index 303acd8..a7ff7e3 100644 --- a/gcc/ChangeLog.x32 +++ b/gcc/ChangeLog.x32 @@ -1,6 +1,16 @@ 2011-03-29 H.J. Lu PR middle-end/47725 + PR target/48085 + * calls.c (precompute_register_parameters): Convert pointer to + TLS symbol if needed. + + * config/i386/i386.c (ix86_promote_function_mode): New. + (TARGET_PROMOTE_FUNCTION_MODE): Likewise. + +2011-03-29 H.J. Lu + + PR middle-end/47725 * combine.c (cant_combine_insn_p): Don't check zero/sign extended hard registers. diff --git a/gcc/calls.c b/gcc/calls.c index 2e79777..7357241 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -691,7 +691,13 @@ precompute_register_parameters (int num_actuals, struct arg_data *args, pseudo now. TLS symbols sometimes need a call to resolve. */ if (CONSTANT_P (args[i].value) && !LEGITIMATE_CONSTANT_P (args[i].value)) - args[i].value = force_reg (args[i].mode, args[i].value); + { + if (GET_MODE (args[i].value) != args[i].mode) + args[i].value = convert_to_mode (args[i].mode, + args[i].value, + args[i].unsignedp); + args[i].value = force_reg (args[i].mode, args[i].value); + } /* If we are to promote the function arg to a wider mode, do it now. */ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index d7a5c02..6cffab2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -7636,6 +7636,23 @@ ix86_function_value (const_tree valtype, const_tree fntype_or_decl, return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode); } +/* Pointer function arguments and return values are promoted to + Pmode. */ + +static enum machine_mode +ix86_promote_function_mode (const_tree type, enum machine_mode mode, + int *punsignedp, const_tree fntype, + int for_return) +{ + if (for_return != 1 && POINTER_TYPE_P (type)) + { + *punsignedp = POINTERS_EXTEND_UNSIGNED; + return Pmode; + } + return default_promote_function_mode (type, mode, punsignedp, fntype, + for_return); +} + rtx ix86_libcall_value (enum machine_mode mode) { @@ -35577,6 +35594,9 @@ ix86_autovectorize_vector_sizes (void) #undef TARGET_FUNCTION_VALUE_REGNO_P #define TARGET_FUNCTION_VALUE_REGNO_P ix86_function_value_regno_p +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE ix86_promote_function_mode + #undef TARGET_SECONDARY_RELOAD #define TARGET_SECONDARY_RELOAD ix86_secondary_reload