From patchwork Fri Nov 27 14:02:36 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 549471 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 8A543140319 for ; Sat, 28 Nov 2015 01:02:53 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=hrJQ7OVd; 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=QtwfjF9OqHsmF8+KhVa/buxo9IEwZcHWG9H2OOdX+ZA2NRcpRD 4aczXpBHY9+/nlnNr/WtufjhWUr0lPGG2i+qgtLjb/KmcpJziCTJP1OXuoqU9VW+ 3zOfdsOavx/nBG2OH6Q27Ffm/ghJG3x4lzZu80lMMCVKHlJMqPwzBM6nY= 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=4VWijuUlz4oxnYBcCwdhJG4nTaQ=; b=hrJQ7OVdt0sWgTk6S0sm x/YsqsOijoscFhJWVm1z6AsWi3oj9UzS/Edg+Ctbj4nfuKMYHwA0LCWPeIdxPm3p PT7aRzu4thFD20xFLZVWbW2hcMQkzHZyEOsthrfGOwd/iOwb+bMt9bycs8g+RhW2 uanvLFGa4if2hvQnjcyXAMg= Received: (qmail 117543 invoked by alias); 27 Nov 2015 14:02: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 117531 invoked by uid 89); 27 Nov 2015 14:02:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.4 required=5.0 tests=BAYES_50, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-qg0-f48.google.com Received: from mail-qg0-f48.google.com (HELO mail-qg0-f48.google.com) (209.85.192.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Fri, 27 Nov 2015 14:02:40 +0000 Received: by qgea14 with SMTP id a14so73068740qge.0 for ; Fri, 27 Nov 2015 06:02:37 -0800 (PST) X-Received: by 10.140.145.216 with SMTP id 207mr56720517qhr.82.1448632957649; Fri, 27 Nov 2015 06:02:37 -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 86sm9445581qky.24.2015.11.27.06.02.36 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 27 Nov 2015 06:02:36 -0800 (PST) To: GCC Patches From: Nathan Sidwell Subject: [PTX] Another libcall patch Message-ID: <5658627C.4070300@acm.org> Date: Fri, 27 Nov 2015 09:02:36 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 I've committed this further cleanup of function decl recording. We were recording libcalls during call expansion, but recording other calls during call outputting. This moves all recording to the call outputting. The recording helpers were a little confusing -- for intsance 'record_fndecl', was really 'maybe_record_fndecl', and in some cases the caller checked preconditions (like being an actual fnddecl) whereas other cases the helper did the checking. I've moved things around so that the caller always does the prechecking. I broke the libcall hash manipulation out into a helper, in line with the other helpers, and added a helper to deal with looking through symbol refs. Finally expand_movdi had no need to register an fndecl itself -- it's already calling maybe_convert_symbolic_operand, which does that. nathan 2015-11-27 Nathan Sidwell * config/nvptx/nvptx-protos.h (nvptx_record_needed_decl): Don't declaree. * config/nvptx/nvptx.c (write_func_decl_from_insn): Move earlier. (nvptx_record_fndecl): Don't return value, remove force argyment. Require fndecl. (nvptx_record_libfunc): New. (nvptx_record_needed_decl): Deteermine how to record decl here. (nvptx_maybe_record_fnsym): New. (nvptx_expand_call): Don't record libfuncs here, (nvptx_maybe_convert_symbolic_operand): Use nvptx_maye_record_fnsym. (nvptx_assemble_integer): Reimplement with single switch. (nvptx_output_call_insn): Register libfuncs here. (nvptx_file_end): Adjust nvptx_record_fndecl call. * config/nvptx/nvptx.md (expand_movdi): Don't call nvptx_record_needed_decl. Index: config/nvptx/nvptx-protos.h =================================================================== --- config/nvptx/nvptx-protos.h (revision 231012) +++ config/nvptx/nvptx-protos.h (working copy) @@ -24,7 +24,6 @@ extern void nvptx_declare_function_name (FILE *, const char *, const_tree decl); extern void nvptx_declare_object_name (FILE *file, const char *name, const_tree decl); -extern void nvptx_record_needed_fndecl (tree decl); extern void nvptx_function_end (FILE *); extern void nvptx_output_skip (FILE *, unsigned HOST_WIDE_INT); extern void nvptx_output_ascii (FILE *, const char *, unsigned HOST_WIDE_INT); Index: config/nvptx/nvptx.c =================================================================== --- config/nvptx/nvptx.c (revision 231012) +++ config/nvptx/nvptx.c (working copy) @@ -452,6 +452,55 @@ write_function_decl_and_comment (std::st s << ";\n"; } +/* Construct a function declaration from a call insn. This can be + necessary for two reasons - either we have an indirect call which + requires a .callprototype declaration, or we have a libcall + generated by emit_library_call for which no decl exists. */ + +static void +write_func_decl_from_insn (std::stringstream &s, const char *name, + rtx result, rtx pat) +{ + if (!name) + { + s << "\t.callprototype "; + name = "_"; + } + else + { + s << "\n// BEGIN GLOBAL FUNCTION DECL: " << name << "\n"; + s << "\t.extern .func "; + } + + if (result != NULL_RTX) + s << "(.param" + << nvptx_ptx_type_from_mode (arg_promotion (GET_MODE (result)), false) + << " %rval) "; + + s << name; + + const char *sep = " ("; + int arg_end = XVECLEN (pat, 0); + for (int i = 1; i < arg_end; i++) + { + /* We don't have to deal with mode splitting here, as that was + already done when generating the call sequence. */ + machine_mode mode = GET_MODE (XEXP (XVECEXP (pat, 0, i), 0)); + + s << sep + << ".param" + << nvptx_ptx_type_from_mode (mode, false) + << " %arg" + << i; + if (mode == QImode || mode == HImode) + s << "[1]"; + sep = ", "; + } + if (arg_end != 1) + s << ")"; + s << ";\n"; +} + /* Check NAME for special function names and redirect them by returning a replacement. This applies to malloc, free and realloc, for which we want to use libgcc wrappers, and call, which triggers a bug in ptxas. */ @@ -470,20 +519,13 @@ nvptx_name_replacement (const char *name return name; } -/* If DECL is a FUNCTION_DECL, check the hash table to see if we - already encountered it, and if not, insert it and write a ptx - declarations that will be output at the end of compilation. */ +/* DECL is an external FUNCTION_DECL, make sure its in the fndecl hash + table and and write a ptx prototype. These are emitted at end of + compilation. */ -static bool -nvptx_record_fndecl (tree decl, bool force = false) +static void +nvptx_record_fndecl (tree decl) { - if (decl == NULL_TREE || TREE_CODE (decl) != FUNCTION_DECL - || !DECL_EXTERNAL (decl)) - return true; - - if (!force && TYPE_ARG_TYPES (TREE_TYPE (decl)) == NULL_TREE) - return false; - tree *slot = declared_fndecls_htab->find_slot (decl, INSERT); if (*slot == NULL) { @@ -492,22 +534,53 @@ nvptx_record_fndecl (tree decl, bool for name = nvptx_name_replacement (name); write_function_decl_and_comment (func_decls, name, decl); } - return true; } -/* Record that we need to emit a ptx decl for DECL. Either do it now, or - record it for later in case we have no argument information at this - point. */ +/* Record a libcall or unprototyped external function. CALLEE is the + SYMBOL_REF. Insert into the libfunc hash table and emit a ptx + declaration for it. */ + +static void +nvptx_record_libfunc (rtx callee, rtx retval, rtx pat) +{ + rtx *slot = declared_libfuncs_htab->find_slot (callee, INSERT); + if (*slot == NULL) + { + *slot = callee; + + const char *name = XSTR (callee, 0); + name = nvptx_name_replacement (name); + write_func_decl_from_insn (func_decls, name, retval, pat); + } +} + +/* DECL is an external FUNCTION_DECL, that we're referencing. If it + is prototyped, record it now. Otherwise record it as needed at end + of compilation, when we might have more information about it. */ void nvptx_record_needed_fndecl (tree decl) { - if (nvptx_record_fndecl (decl)) - return; + if (TYPE_ARG_TYPES (TREE_TYPE (decl)) == NULL_TREE) + { + tree *slot = needed_fndecls_htab->find_slot (decl, INSERT); + if (*slot == NULL) + *slot = decl; + } + else + nvptx_record_fndecl (decl); +} - tree *slot = needed_fndecls_htab->find_slot (decl, INSERT); - if (*slot == NULL) - *slot = decl; +/* SYM is a SYMBOL_REF. If it refers to an external function, record + it as needed. */ + +static void +nvptx_maybe_record_fnsym (rtx sym) +{ + tree decl = SYMBOL_REF_DECL (sym); + + if (decl && TREE_CODE (decl) == FUNCTION_DECL && DECL_EXTERNAL (decl)) + nvptx_record_needed_fndecl (decl); } /* Emit code to initialize the REGNO predicate register to indicate @@ -713,55 +786,6 @@ nvptx_output_return (void) return "ret;"; } -/* Construct a function declaration from a call insn. This can be - necessary for two reasons - either we have an indirect call which - requires a .callprototype declaration, or we have a libcall - generated by emit_library_call for which no decl exists. */ - -static void -write_func_decl_from_insn (std::stringstream &s, const char *name, - rtx result, rtx pat) -{ - if (!name) - { - s << "\t.callprototype "; - name = "_"; - } - else - { - s << "\n// BEGIN GLOBAL FUNCTION DECL: " << name << "\n"; - s << "\t.extern .func "; - } - - if (result != NULL_RTX) - s << "(.param" - << nvptx_ptx_type_from_mode (arg_promotion (GET_MODE (result)), false) - << " %rval) "; - - s << name; - - const char *sep = " ("; - int arg_end = XVECLEN (pat, 0); - for (int i = 1; i < arg_end; i++) - { - /* We don't have to deal with mode splitting here, as that was - already done when generating the call sequence. */ - machine_mode mode = GET_MODE (XEXP (XVECEXP (pat, 0, i), 0)); - - s << sep - << ".param" - << nvptx_ptx_type_from_mode (mode, false) - << " %arg" - << i; - if (mode == QImode || mode == HImode) - s << "[1]"; - sep = ", "; - } - if (arg_end != 1) - s << ")"; - s << ";\n"; -} - /* Terminate a function by writing a closing brace to FILE. */ void @@ -830,9 +854,7 @@ nvptx_expand_call (rtx retval, rtx addre rtx callee = XEXP (address, 0); rtx pat, t; rtvec vec; - bool external_decl = false; rtx varargs = NULL_RTX; - tree decl_type = NULL_TREE; unsigned parallel = 0; for (t = cfun->machine->call_args; t; t = XEXP (t, 1)) @@ -849,11 +871,9 @@ nvptx_expand_call (rtx retval, rtx addre tree decl = SYMBOL_REF_DECL (callee); if (decl != NULL_TREE) { - decl_type = TREE_TYPE (decl); if (DECL_STATIC_CHAIN (decl)) cfun->machine->has_call_with_sc = true; - if (DECL_EXTERNAL (decl)) - external_decl = true; + tree attr = get_oacc_fn_attrib (decl); if (attr) { @@ -913,26 +933,6 @@ nvptx_expand_call (rtx retval, rtx addre gcc_assert (vec_pos = XVECLEN (pat, 0)); - /* If this is a libcall, decl_type is NULL. For a call to a non-libcall - undeclared function, we'll have an external decl without arg types. - In either case we have to try to construct a ptx declaration from one of - the calls to the function. */ - if (!REG_P (callee) - && (decl_type == NULL_TREE - || (external_decl && TYPE_ARG_TYPES (decl_type) == NULL_TREE))) - { - rtx *slot = declared_libfuncs_htab->find_slot (callee, INSERT); - if (*slot == NULL) - { - *slot = callee; - - const char *name = XSTR (callee, 0); - if (decl_type) - name = nvptx_name_replacement (name); - write_func_decl_from_insn (func_decls, name, retval, pat); - } - } - nvptx_emit_forking (parallel, true); emit_call_insn (pat); nvptx_emit_joining (parallel, true); @@ -1354,10 +1354,9 @@ nvptx_gen_wcast (rtx reg, propagate_mask } /* When loading an operand ORIG_OP, verify whether an address space - conversion to generic is required, and if so, perform it. Also - check for SYMBOL_REFs for function decls and call - nvptx_record_needed_fndecl as needed. - Return either the original operand, or the converted one. */ + conversion to generic is required, and if so, perform it. Check + for SYMBOL_REFs and record them if needed. Return either the + original operand, or the converted one. */ rtx nvptx_maybe_convert_symbolic_operand (rtx orig_op) @@ -1371,13 +1370,8 @@ nvptx_maybe_convert_symbolic_operand (rt if (GET_CODE (op) != SYMBOL_REF) return orig_op; - tree decl = SYMBOL_REF_DECL (op); - if (decl && TREE_CODE (decl) == FUNCTION_DECL) - { - nvptx_record_needed_fndecl (decl); - return orig_op; - } - + nvptx_maybe_record_fnsym (op); + addr_space_t as = nvptx_addr_space_from_address (op); if (as == ADDR_SPACE_GENERIC) return orig_op; @@ -1570,48 +1564,43 @@ nvptx_assemble_value (HOST_WIDE_INT val, static bool nvptx_assemble_integer (rtx x, unsigned int size, int ARG_UNUSED (aligned_p)) { - if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == CONST) + HOST_WIDE_INT val = 0; + + switch (GET_CODE (x)) { + default: + gcc_unreachable (); + + case CONST_INT: + val = INTVAL (x); + nvptx_assemble_value (val, size); + break; + + case CONST: + x = XEXP (x, 0); + gcc_assert (GET_CODE (x) == PLUS); + val = INTVAL (XEXP (x, 1)); + x = XEXP (x, 0); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + /* FALLTHROUGH */ + + case SYMBOL_REF: gcc_assert (size = decl_chunk_size); if (decl_offset % decl_chunk_size != 0) sorry ("cannot emit unaligned pointers in ptx assembly"); decl_offset += size; begin_decl_field (); - HOST_WIDE_INT off = 0; - if (GET_CODE (x) == CONST) - x = XEXP (x, 0); - if (GET_CODE (x) == PLUS) - { - off = INTVAL (XEXP (x, 1)); - x = XEXP (x, 0); - } - if (GET_CODE (x) == SYMBOL_REF) - { - nvptx_record_needed_fndecl (SYMBOL_REF_DECL (x)); - fprintf (asm_out_file, "generic("); - output_address (VOIDmode, x); - fprintf (asm_out_file, ")"); - } - if (off != 0) - fprintf (asm_out_file, " + " HOST_WIDE_INT_PRINT_DEC, off); - return true; - } + nvptx_maybe_record_fnsym (x); + fprintf (asm_out_file, "generic("); + output_address (VOIDmode, x); + fprintf (asm_out_file, ")"); - HOST_WIDE_INT val; - switch (GET_CODE (x)) - { - case CONST_INT: - val = INTVAL (x); - break; - case CONST_DOUBLE: - gcc_unreachable (); + if (val) + fprintf (asm_out_file, " + " HOST_WIDE_INT_PRINT_DEC, val); break; - default: - gcc_unreachable (); } - nvptx_assemble_value (val, size); return true; } @@ -1793,7 +1782,10 @@ nvptx_output_call_insn (rtx_insn *insn, if (GET_CODE (callee) == SYMBOL_REF) { decl = SYMBOL_REF_DECL (callee); - if (decl && DECL_EXTERNAL (decl)) + if (!decl + || (DECL_EXTERNAL (decl) && !TYPE_ARG_TYPES (TREE_TYPE (decl)))) + nvptx_record_libfunc (callee, result, pat); + else if (DECL_EXTERNAL (decl)) nvptx_record_fndecl (decl); } @@ -3889,7 +3881,7 @@ nvptx_file_end (void) hash_table::iterator iter; tree decl; FOR_EACH_HASH_TABLE_ELEMENT (*needed_fndecls_htab, decl, tree, iter) - nvptx_record_fndecl (decl, true); + nvptx_record_fndecl (decl); fputs (func_decls.str().c_str(), asm_out_file); if (worker_bcast_size) Index: config/nvptx/nvptx.md =================================================================== --- config/nvptx/nvptx.md (revision 231012) +++ config/nvptx/nvptx.md (working copy) @@ -391,8 +391,6 @@ emit_move_insn (operands[0], tmp); DONE; } - if (GET_CODE (operands[1]) == SYMBOL_REF) - nvptx_record_needed_fndecl (SYMBOL_REF_DECL (operands[1])); }) (define_insn "highpartscsf2"