From patchwork Thu Dec 10 20:16:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 555318 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.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 92C82140BEE for ; Fri, 11 Dec 2015 07:16:57 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=ivMl0FpV; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=RnXNI2mMzNyL1fVaItFWD1NdugAcq8Huprn/36xHu2ncbVoQBn 5dqjIE33GpTaFEJ3fB2ewVbVU6zh+EJVGeVyv4B5pBViq1X7vCHRoseiQMFjvdzY FYflm/UTSIxDDdIdMLQlkZFfvFIjH7o2Z5djLmJGLWnqfWbhJOjTQ6U0M= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=aRlxqDh9ti+4306JwaIx3UkxlxM=; b=ivMl0FpVOtnvhdDpWF3u ongzMFKj9ylWMNLOX+ERYqWS/KGhEcQSxg4gBc7GedWkTznkWPsT7N233egO+eAE ETdwHfj3PRVySQ0BZY9bK4rC8l1ip+oBYeEH+3IQcCwEoDt9nKIfkDzOqa/JM8yT gQMk//Sic1hsF7fE8qnQvF8= Received: (qmail 112640 invoked by alias); 10 Dec 2015 20:16:45 -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 112621 invoked by uid 89); 10 Dec 2015 20:16:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.2 required=5.0 tests=BAYES_05, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-qg0-f42.google.com Received: from mail-qg0-f42.google.com (HELO mail-qg0-f42.google.com) (209.85.192.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 10 Dec 2015 20:16:42 +0000 Received: by qgcc31 with SMTP id c31so161605700qgc.3 for ; Thu, 10 Dec 2015 12:16:40 -0800 (PST) X-Received: by 10.140.217.211 with SMTP id n202mr9531625qhb.26.1449778599946; Thu, 10 Dec 2015 12:16:39 -0800 (PST) Received: from ?IPv6:2601:181:c000:c497:a2a8:cdff:fe3e:b48? ([2601:181:c000:c497:a2a8:cdff:fe3e:b48]) by smtp.googlemail.com with ESMTPSA id w39sm6732333qgd.4.2015.12.10.12.16.39 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 10 Dec 2015 12:16:39 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: [PTX] reorder function calling hooks Message-ID: <5669DDA6.4020805@acm.org> Date: Thu, 10 Dec 2015 15:16:38 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 This patch reorders the function calling hooks so they come before write_one_arg. There's no change to their functionality, but it will allow them to be called from write_one_arg and write_result, rather than have those functions continue to independently perform essentially the same calculation. Also, I split write_one_arg into a write_one_arg helper, (which does write one arg), and a write_arg main entry point (which writes one or more PTX args). nathan 2015-12-10 Nathan Sidwell * config/nvptx/nvptx.c (nvptx_function_arg, nvptx_function_incoming_arg, nvptx_function_arg_advance, nvptx_strict_argument_naming, nvptx_function_arg_boundary, nvptx_libcall_value, nvptx_function_value, nvptx_function_value_regno_p, nvptx_pass_by_reference, nvptx_return_in_memory, nvptx_promote_function_mode, nvptx_static_chain): Move earlier. (write_one_arg): Break out as helper fn for ... (write_arg): ... this new function. Adjust all callers. Index: config/nvptx/nvptx.c =================================================================== --- config/nvptx/nvptx.c (revision 231542) +++ config/nvptx/nvptx.c (working copy) @@ -389,69 +389,270 @@ arg_promotion (machine_mode mode) return mode; } -/* Process function parameter TYPE, either emitting in a prototype - argument, or as a copy a in a function prologue. ARGNO is the - index of this argument in the PTX function. FOR_REG is negative, - if we're emitting the PTX prototype. It is zero if we're copying - to an argument register and it is greater than zero if we're - copying to a specific hard register. PROTOTYPED is true, if this - is a prototyped function, rather than an old-style C declaration. +/* Implement TARGET_FUNCTION_ARG. */ - The behaviour here must match the regular GCC function parameter - marshalling machinery. */ +static rtx +nvptx_function_arg (cumulative_args_t, machine_mode mode, + const_tree, bool named) +{ + if (mode == VOIDmode) + return NULL_RTX; -static int -write_one_arg (std::stringstream &s, int for_reg, int argno, - tree type, bool prototyped) + if (named) + return gen_reg_rtx (mode); + return NULL_RTX; +} + +/* Implement TARGET_FUNCTION_INCOMING_ARG. */ + +static rtx +nvptx_function_incoming_arg (cumulative_args_t cum_v, machine_mode mode, + const_tree, bool named) { - machine_mode mode = TYPE_MODE (type); + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + if (mode == VOIDmode) + return NULL_RTX; - if (!PASS_IN_REG_P (mode, type)) - mode = Pmode; + if (!named) + return NULL_RTX; - machine_mode split = maybe_split_mode (mode); - if (split != VOIDmode) + /* No need to deal with split modes here, the only case that can + happen is complex modes and those are dealt with by + TARGET_SPLIT_COMPLEX_ARG. */ + return gen_rtx_UNSPEC (mode, + gen_rtvec (1, GEN_INT (cum->count)), + UNSPEC_ARG_REG); +} + +/* Implement TARGET_FUNCTION_ARG_ADVANCE. */ + +static void +nvptx_function_arg_advance (cumulative_args_t cum_v, + machine_mode ARG_UNUSED (mode), + const_tree ARG_UNUSED (type), + bool ARG_UNUSED (named)) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + cum->count++; +} + +/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. + + For nvptx, we know how to handle functions declared as stdarg: by + passing an extra pointer to the unnamed arguments. However, the + Fortran frontend can produce a different situation, where a + function pointer is declared with no arguments, but the actual + function and calls to it take more arguments. In that case, we + want to ensure the call matches the definition of the function. */ + +static bool +nvptx_strict_argument_naming (cumulative_args_t cum_v) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + return cum->fntype == NULL_TREE || stdarg_p (cum->fntype); +} + +/* Implement TARGET_FUNCTION_ARG_BOUNDARY. */ + +static unsigned int +nvptx_function_arg_boundary (machine_mode mode, const_tree type) +{ + unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode); + + if (boundary > BITS_PER_WORD) + return 2 * BITS_PER_WORD; + + if (mode == BLKmode) { - mode = split; - argno = write_one_arg (s, for_reg, argno, - TREE_TYPE (type), prototyped); + HOST_WIDE_INT size = int_size_in_bytes (type); + if (size > 4) + return 2 * BITS_PER_WORD; + if (boundary < BITS_PER_WORD) + { + if (size >= 3) + return BITS_PER_WORD; + if (size >= 2) + return 2 * BITS_PER_UNIT; + } } + return boundary; +} - if (!prototyped && !AGGREGATE_TYPE_P (type)) +/* Implement TARGET_LIBCALL_VALUE. */ + +static rtx +nvptx_libcall_value (machine_mode mode, const_rtx) +{ + if (cfun->machine->start_call == NULL_RTX) + /* Pretend to return in a hard reg for early uses before pseudos can be + generated. */ + return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); + return gen_reg_rtx (mode); +} + +/* TARGET_FUNCTION_VALUE implementation. Returns an RTX representing the place + where function FUNC returns or receives a value of data type TYPE. */ + +static rtx +nvptx_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED, + bool outgoing) +{ + int unsignedp = TYPE_UNSIGNED (type); + machine_mode orig_mode = TYPE_MODE (type); + machine_mode mode = promote_function_mode (type, orig_mode, + &unsignedp, NULL_TREE, 1); + if (outgoing) + return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); + if (cfun->machine->start_call == NULL_RTX) + /* Pretend to return in a hard reg for early uses before pseudos can be + generated. */ + return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); + return gen_reg_rtx (mode); +} + +/* Implement TARGET_FUNCTION_VALUE_REGNO_P. */ + +static bool +nvptx_function_value_regno_p (const unsigned int regno) +{ + return regno == NVPTX_RETURN_REGNUM; +} + +/* Types with a mode other than those supported by the machine are passed by + reference in memory. */ + +static bool +nvptx_pass_by_reference (cumulative_args_t, machine_mode mode, + const_tree type, bool) +{ + return !PASS_IN_REG_P (mode, type); +} + +/* Implement TARGET_RETURN_IN_MEMORY. */ + +static bool +nvptx_return_in_memory (const_tree type, const_tree) +{ + machine_mode mode = TYPE_MODE (type); + if (!RETURN_IN_REG_P (mode)) + return true; + return false; +} + +/* Implement TARGET_PROMOTE_FUNCTION_MODE. */ + +static machine_mode +nvptx_promote_function_mode (const_tree type, machine_mode mode, + int *punsignedp, + const_tree funtype, int for_return) +{ + if (type == NULL_TREE) + return mode; + if (for_return) + return promote_mode (type, mode, punsignedp); + /* For K&R-style functions, try to match the language promotion rules to + minimize type mismatches at assembly time. */ + if (TYPE_ARG_TYPES (funtype) == NULL_TREE + && type != NULL_TREE + && !AGGREGATE_TYPE_P (type)) { if (mode == SFmode) mode = DFmode; mode = arg_promotion (mode); } + return mode; +} + +/* Implement TARGET_STATIC_CHAIN. */ + +static rtx +nvptx_static_chain (const_tree fndecl, bool incoming_p) +{ + if (!DECL_STATIC_CHAIN (fndecl)) + return NULL; + + if (incoming_p) + return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); + else + return gen_rtx_REG (Pmode, OUTGOING_STATIC_CHAIN_REGNUM); +} + +/* Helper for write_arg. Emit a single PTX argument of MODE, either + in a prototype, or as copy in a function prologue. ARGNO is the + index of this argument in the PTX function. FOR_REG is negative, + if we're emitting the PTX prototype. It is zero if we're copying + to an argument register and it is greater than zero if we're + copying to a specific hard register. */ + +static int +write_one_arg (std::stringstream &s, int for_reg, int argno, machine_mode mode) +{ + const char *ptx_type = nvptx_ptx_type_from_mode (mode, false); + if (for_reg < 0) { /* Writing PTX prototype. */ s << (argno ? ", " : " ("); - s << ".param" << nvptx_ptx_type_from_mode (mode, false) - << " %in_ar" << argno; + s << ".param" << ptx_type << " %in_ar" << argno; if (mode == QImode || mode == HImode) s << "[1]"; } else { - mode = arg_promotion (mode); - s << "\t.reg" << nvptx_ptx_type_from_mode (mode, false) << " "; + s << "\t.reg" << ptx_type << " "; if (for_reg) s << reg_names[for_reg]; else s << "%ar" << argno; s << ";\n"; - s << "\tld.param" << nvptx_ptx_type_from_mode (mode, false) << " "; + s << "\tld.param" << ptx_type << " "; if (for_reg) s << reg_names[for_reg]; else s << "%ar" << argno; - s<< ", [%in_ar" << argno << "];\n"; + s << ", [%in_ar" << argno << "];\n"; } return argno + 1; } +/* Process function parameter TYPE to emit one or more PTX + arguments. PROTOTYPED is true, if this is a prototyped function, + rather than an old-style C declaration. + + The promotion behaviour here must match the regular GCC function + parameter marshalling machinery. */ + +static int +write_arg (std::stringstream &s, int for_reg, int argno, + tree type, bool prototyped) +{ + machine_mode mode = TYPE_MODE (type); + + if (mode == VOIDmode) + return argno; + + if (!PASS_IN_REG_P (mode, type)) + mode = Pmode; + + machine_mode split = maybe_split_mode (mode); + if (split != VOIDmode) + mode = split; + + if (!prototyped && !AGGREGATE_TYPE_P (type)) + { + if (mode == SFmode) + mode = DFmode; + mode = arg_promotion (mode); + } + else if (for_reg >= 0) + mode = arg_promotion (mode); + + if (split != VOIDmode) + argno = write_one_arg (s, for_reg, argno, mode); + return write_one_arg (s, for_reg, argno, mode); +} + static bool write_return (std::stringstream &s, bool for_proto, tree type, machine_mode ret_mode) @@ -555,7 +756,7 @@ write_fn_proto (std::stringstream &s, bo /* Emit argument list. */ if (return_in_mem) - argno = write_one_arg (s, -1, argno, ptr_type_node, true); + argno = write_arg (s, -1, argno, ptr_type_node, true); /* We get: NULL in TYPE_ARG_TYPES, for old-style functions @@ -574,20 +775,19 @@ write_fn_proto (std::stringstream &s, bo { tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args); - if (type != void_type_node) - argno = write_one_arg (s, -1, argno, type, prototyped); + argno = write_arg (s, -1, argno, type, prototyped); } if (stdarg_p (fntype)) - argno = write_one_arg (s, -1, argno, ptr_type_node, true); + argno = write_arg (s, -1, argno, ptr_type_node, true); if (DECL_STATIC_CHAIN (decl)) - argno = write_one_arg (s, -1, argno, ptr_type_node, true); + argno = write_arg (s, -1, argno, ptr_type_node, true); if (!argno && strcmp (name, "main") == 0) { - argno = write_one_arg (s, -1, argno, integer_type_node, true); - argno = write_one_arg (s, -1, argno, ptr_type_node, true); + argno = write_arg (s, -1, argno, integer_type_node, true); + argno = write_arg (s, -1, argno, ptr_type_node, true); } if (argno) @@ -743,7 +943,7 @@ nvptx_declare_function_name (FILE *file, bool return_in_mem = write_return (s, false, result_type, (machine_mode)cfun->machine->ret_reg_mode); if (return_in_mem) - argno = write_one_arg (s, 0, argno, ptr_type_node, true); + argno = write_arg (s, 0, argno, ptr_type_node, true); /* Declare and initialize incoming arguments. */ tree args = TYPE_ARG_TYPES (fntype); @@ -758,15 +958,14 @@ nvptx_declare_function_name (FILE *file, { tree type = prototyped ? TREE_VALUE (args) : TREE_TYPE (args); - if (type != void_type_node) - argno = write_one_arg (s, 0, argno, type, prototyped); + argno = write_arg (s, 0, argno, type, prototyped); } if (stdarg_p (fntype)) - argno = write_one_arg (s, ARG_POINTER_REGNUM, argno, ptr_type_node, true); + argno = write_arg (s, ARG_POINTER_REGNUM, argno, ptr_type_node, true); if (DECL_STATIC_CHAIN (decl)) - argno = write_one_arg (s, STATIC_CHAIN_REGNUM, argno, ptr_type_node, true); + argno = write_arg (s, STATIC_CHAIN_REGNUM, argno, ptr_type_node, true); fprintf (file, "%s", s.str().c_str()); @@ -1001,196 +1200,6 @@ nvptx_expand_call (rtx retval, rtx addre if (tmp_retval != retval) emit_move_insn (retval, tmp_retval); } - -/* Implement TARGET_FUNCTION_ARG. */ - -static rtx -nvptx_function_arg (cumulative_args_t, machine_mode mode, - const_tree, bool named) -{ - if (mode == VOIDmode) - return NULL_RTX; - - if (named) - return gen_reg_rtx (mode); - return NULL_RTX; -} - -/* Implement TARGET_FUNCTION_INCOMING_ARG. */ - -static rtx -nvptx_function_incoming_arg (cumulative_args_t cum_v, machine_mode mode, - const_tree, bool named) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - if (mode == VOIDmode) - return NULL_RTX; - - if (!named) - return NULL_RTX; - - /* No need to deal with split modes here, the only case that can - happen is complex modes and those are dealt with by - TARGET_SPLIT_COMPLEX_ARG. */ - return gen_rtx_UNSPEC (mode, - gen_rtvec (1, GEN_INT (cum->count)), - UNSPEC_ARG_REG); -} - -/* Implement TARGET_FUNCTION_ARG_ADVANCE. */ - -static void -nvptx_function_arg_advance (cumulative_args_t cum_v, - machine_mode ARG_UNUSED (mode), - const_tree ARG_UNUSED (type), - bool ARG_UNUSED (named)) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - cum->count++; -} - -/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. - - For nvptx, we know how to handle functions declared as stdarg: by - passing an extra pointer to the unnamed arguments. However, the - Fortran frontend can produce a different situation, where a - function pointer is declared with no arguments, but the actual - function and calls to it take more arguments. In that case, we - want to ensure the call matches the definition of the function. */ - -static bool -nvptx_strict_argument_naming (cumulative_args_t cum_v) -{ - CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); - return cum->fntype == NULL_TREE || stdarg_p (cum->fntype); -} - -/* Implement TARGET_FUNCTION_ARG_BOUNDARY. */ - -static unsigned int -nvptx_function_arg_boundary (machine_mode mode, const_tree type) -{ - unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode); - - if (boundary > BITS_PER_WORD) - return 2 * BITS_PER_WORD; - - if (mode == BLKmode) - { - HOST_WIDE_INT size = int_size_in_bytes (type); - if (size > 4) - return 2 * BITS_PER_WORD; - if (boundary < BITS_PER_WORD) - { - if (size >= 3) - return BITS_PER_WORD; - if (size >= 2) - return 2 * BITS_PER_UNIT; - } - } - return boundary; -} - -/* TARGET_FUNCTION_VALUE implementation. Returns an RTX representing the place - where function FUNC returns or receives a value of data type TYPE. */ - -static rtx -nvptx_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED, - bool outgoing) -{ - int unsignedp = TYPE_UNSIGNED (type); - machine_mode orig_mode = TYPE_MODE (type); - machine_mode mode = promote_function_mode (type, orig_mode, - &unsignedp, NULL_TREE, 1); - if (outgoing) - return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); - if (cfun->machine->start_call == NULL_RTX) - /* Pretend to return in a hard reg for early uses before pseudos can be - generated. */ - return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); - return gen_reg_rtx (mode); -} - -/* Implement TARGET_LIBCALL_VALUE. */ - -static rtx -nvptx_libcall_value (machine_mode mode, const_rtx) -{ - if (cfun->machine->start_call == NULL_RTX) - /* Pretend to return in a hard reg for early uses before pseudos can be - generated. */ - return gen_rtx_REG (mode, NVPTX_RETURN_REGNUM); - return gen_reg_rtx (mode); -} - -/* Implement TARGET_FUNCTION_VALUE_REGNO_P. */ - -static bool -nvptx_function_value_regno_p (const unsigned int regno) -{ - return regno == NVPTX_RETURN_REGNUM; -} - -/* Types with a mode other than those supported by the machine are passed by - reference in memory. */ - -static bool -nvptx_pass_by_reference (cumulative_args_t, machine_mode mode, - const_tree type, bool) -{ - return !PASS_IN_REG_P (mode, type); -} - -/* Implement TARGET_RETURN_IN_MEMORY. */ - -static bool -nvptx_return_in_memory (const_tree type, const_tree) -{ - machine_mode mode = TYPE_MODE (type); - if (!RETURN_IN_REG_P (mode)) - return true; - return false; -} - -/* Implement TARGET_PROMOTE_FUNCTION_MODE. */ - -static machine_mode -nvptx_promote_function_mode (const_tree type, machine_mode mode, - int *punsignedp, - const_tree funtype, int for_return) -{ - if (type == NULL_TREE) - return mode; - if (for_return) - return promote_mode (type, mode, punsignedp); - /* For K&R-style functions, try to match the language promotion rules to - minimize type mismatches at assembly time. */ - if (TYPE_ARG_TYPES (funtype) == NULL_TREE - && type != NULL_TREE - && !AGGREGATE_TYPE_P (type)) - { - if (mode == SFmode) - mode = DFmode; - mode = arg_promotion (mode); - } - - return mode; -} - -/* Implement TARGET_STATIC_CHAIN. */ - -static rtx -nvptx_static_chain (const_tree fndecl, bool incoming_p) -{ - if (!DECL_STATIC_CHAIN (fndecl)) - return NULL; - - if (incoming_p) - return gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM); - else - return gen_rtx_REG (Pmode, OUTGOING_STATIC_CHAIN_REGNUM); -} - /* Emit a comparison COMPARE, and return the new test to be used in the jump. */