From 00e5241831c1227615a45b7bcba29c393671cb3f Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 27 Nov 2015 13:57:09 +0000 Subject: [PATCH] nvptx-protos.h (nvptx_record_needed_decl): Don't declaree. * 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. From-SVN: r231013 --- gcc/ChangeLog | 19 +++ gcc/config/nvptx/nvptx-protos.h | 1 - gcc/config/nvptx/nvptx.c | 270 ++++++++++++++++---------------- gcc/config/nvptx/nvptx.md | 2 - 4 files changed, 150 insertions(+), 142 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index baf76d5f19e..ca9635b7f22 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +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. + 2015-11-27 Richard Biener PR tree-optimization/68553 diff --git a/gcc/config/nvptx/nvptx-protos.h b/gcc/config/nvptx/nvptx-protos.h index e5355289b6e..a2d8f9763ef 100644 --- a/gcc/config/nvptx/nvptx-protos.h +++ b/gcc/config/nvptx/nvptx-protos.h @@ -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); diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 61030f2f40a..530ed7a0220 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -452,6 +452,55 @@ write_function_decl_and_comment (std::stringstream &s, const char *name, const_t 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 force = false) 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 address) 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 address) 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 address) 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 pm, unsigned rep, wcast_data_t *data) } /* 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 (rtx orig_op) 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, unsigned int size) 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, rtx result, rtx callee) 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) diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 0227b8e3c80..8d7535a622a 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -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" -- 2.30.2