-220677
-Last Changed Date: 2015-02-13 08:56:14 +0100 (Fri, 13 Feb 2015)
+220871
+Last Changed Date: 2015-02-20 15:40:00 +0100 (Fri, 20 Feb 2015)
&& TREE_CODE (cur_type) == INTEGER_TYPE
&& warn_format_signedness
&& TYPE_UNSIGNED (wanted_type)
+ && cur_param != NULL_TREE
&& TREE_CODE (cur_param) == NOP_EXPR)
{
tree t = TREE_TYPE (TREE_OPERAND (cur_param, 0));
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
{
- error_at (loc, "array type has incomplete element type");
+ error_at (loc, "array type has incomplete element type %qT",
+ type);
type = error_mark_node;
}
else
error_at (loc, "unnamed field has incomplete type");
type = error_mark_node;
}
+ else if (TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type) == NULL_TREE)
+ {
+ /* We have a flexible array member through a typedef.
+ Set suitable range. Whether this is a correct position
+ for a flexible array member will be determined elsewhere. */
+ if (!in_system_header_at (input_location))
+ pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not "
+ "support flexible array members");
+ type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+ TYPE_DOMAIN (type) = build_range_type (sizetype, size_zero_node,
+ NULL_TREE);
+ }
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
FIELD_DECL, declarator->u.id, type);
if (callback (this, data))
return true;
+ FOR_EACH_ALIAS (this, ref)
+ {
+ cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ if (include_overwritable
+ || alias->get_availability () > AVAIL_INTERPOSABLE)
+ if (alias->call_for_symbol_thunks_and_aliases (callback, data,
+ include_overwritable,
+ exclude_virtual_thunks))
+ return true;
+ }
for (e = callers; e; e = e->next_caller)
if (e->caller->thunk.thunk_p
&& (include_overwritable
exclude_virtual_thunks))
return true;
- FOR_EACH_ALIAS (this, ref)
- {
- cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- if (include_overwritable
- || alias->get_availability () > AVAIL_INTERPOSABLE)
- if (alias->call_for_symbol_thunks_and_aliases (callback, data,
- include_overwritable,
- exclude_virtual_thunks))
- return true;
- }
- return false;
-}
-
-/* Call callback on function and aliases associated to the function.
- When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
- skipped. */
-
-bool
-cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
- void *),
- void *data,
- bool include_overwritable)
-{
- ipa_ref *ref;
-
- if (callback (this, data))
- return true;
-
- FOR_EACH_ALIAS (this, ref)
- {
- cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- if (include_overwritable
- || alias->get_availability () > AVAIL_INTERPOSABLE)
- if (alias->call_for_symbol_and_aliases (callback, data,
- include_overwritable))
- return true;
- }
return false;
}
return true;
}
-/* Return true when function can be removed from callgraph
- if all direct calls are eliminated. */
-
-bool
-cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
-{
- gcc_assert (!global.inlined_to);
- /* Instrumentation clones should not be removed before
- instrumentation happens. New callers may appear after
- instrumentation. */
- if (instrumentation_clone
- && !chkp_function_instrumented_p (decl))
- return false;
- /* Extern inlines can always go, we will use the external definition. */
- if (DECL_EXTERNAL (decl))
- return true;
- /* When function is needed, we can not remove it. */
- if (force_output || used_from_other_partition)
- return false;
- if (DECL_STATIC_CONSTRUCTOR (decl)
- || DECL_STATIC_DESTRUCTOR (decl))
- return false;
- /* Only COMDAT functions can be removed if externally visible. */
- if (externally_visible
- && (!DECL_COMDAT (decl)
- || forced_by_abi
- || used_from_object_file_p ()))
- return false;
- return true;
-}
-
/* Worker for cgraph_can_remove_if_no_direct_calls_p. */
static bool
version_info_node = NULL;
}
+/* A wroker for call_for_symbol_and_aliases. */
+
+bool
+cgraph_node::call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (this, ref)
+ {
+ cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ if (include_overwritable
+ || alias->get_availability () > AVAIL_INTERPOSABLE)
+ if (alias->call_for_symbol_and_aliases (callback, data,
+ include_overwritable))
+ return true;
+ }
+ return false;
+}
#include "gt-cgraph.h"
/* Verify symbol table for internal consistency. */
static DEBUG_FUNCTION void verify_symtab_nodes (void);
- /* Return true when NODE is known to be used from other (non-LTO)
- object file. Known only when doing LTO via linker plugin. */
- static bool used_from_object_file_p_worker (symtab_node *node);
-
/* Type of the symbol. */
ENUM_BITFIELD (symtab_type) type : 8;
allocated structure is returned. */
struct symbol_priority_map *priority_info (void);
+ /* Worker for call_for_symbol_and_aliases_1. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *, void *),
+ void *data,
+ bool include_overwrite);
private:
/* Worker for set_section. */
static bool set_section (symtab_node *n, void *s);
/* Worker searching noninterposable alias. */
static bool noninterposable_alias (symtab_node *node, void *data);
+
+ /* Worker for ultimate_alias_target. */
+ symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL);
};
/* Walk all aliases for NODE. */
unsigned nonfreeing_fn : 1;
/* True if there was multiple COMDAT bodies merged by lto-symtab. */
unsigned merged : 1;
+
+private:
+ /* Worker for call_for_symbol_and_aliases. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (cgraph_node *,
+ void *),
+ void *data, bool include_overwritable);
};
/* A cgraph node set is a collection of cgraph nodes. A cgraph node
/* Call calback on varpool symbol and aliases associated to varpool symbol.
When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
skipped. */
- bool call_for_node_and_aliases (bool (*callback) (varpool_node *, void *),
- void *data,
- bool include_overwritable);
+ bool call_for_symbol_and_aliases (bool (*callback) (varpool_node *, void *),
+ void *data,
+ bool include_overwritable);
/* Return true when variable should be considered externally visible. */
bool externally_visible_p (void);
private:
/* Assemble thunks and aliases associated to varpool node. */
void assemble_aliases (void);
+
+ /* Worker for call_for_node_and_aliases. */
+ bool call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *, void *),
+ void *data,
+ bool include_overwritable);
};
/* Every top level asm statement is put into a asm_node. */
const char* cgraph_inline_failed_string (cgraph_inline_failed_t);
cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t);
-bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution);
extern bool gimple_check_call_matching_types (gimple, tree, bool);
/* In cgraphunit.c */
/* In cgraphclones.c */
+tree clone_function_name_1 (const char *, const char *);
tree clone_function_name (tree decl, const char *);
void tree_function_versioning (tree, tree, vec<ipa_replace_map *, va_gc> *,
/* In varpool.c */
tree ctor_for_folding (tree);
+/* In tree-chkp.c */
+extern bool chkp_function_instrumented_p (tree fndecl);
+
/* Return true when the symbol is real symbol, i.e. it is not inline clone
or abstract function kept for debug info purposes only. */
inline bool
}
/* Return next reachable static symbol with initializer after the node. */
+
inline symtab_node *
symtab_node::next_defined_symbol (void)
{
return NULL;
}
+/* Iterates I-th reference in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
+{
+ vec_safe_iterate (ref_list.references, i, &ref);
+
+ return ref;
+}
+
+/* Iterates I-th referring item in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
+{
+ ref_list.referring.iterate (i, &ref);
+
+ return ref;
+}
+
+/* Iterates I-th referring alias item in the list, REF is also set. */
+
+inline ipa_ref *
+symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
+{
+ ref_list.referring.iterate (i, &ref);
+
+ if (ref && ref->use != IPA_REF_ALIAS)
+ return NULL;
+
+ return ref;
+}
+
+/* Return true if list contains an alias. */
+
+inline bool
+symtab_node::has_aliases_p (void)
+{
+ ipa_ref *ref = NULL;
+
+ return (iterate_direct_aliases (0, ref) != NULL);
+}
+
+/* Return true when RESOLUTION indicate that linker will use
+ the symbol from non-LTO object files. */
+
+inline bool
+resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
+{
+ return (resolution == LDPR_PREVAILING_DEF
+ || resolution == LDPR_PREEMPTED_REG
+ || resolution == LDPR_RESOLVED_EXEC
+ || resolution == LDPR_RESOLVED_DYN);
+}
+
+/* Return true when symtab_node is known to be used from other (non-LTO)
+ object file. Known only when doing LTO via linker plugin. */
+
+inline bool
+symtab_node::used_from_object_file_p (void)
+{
+ if (!TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ return false;
+ if (resolution_used_from_other_file_p (resolution))
+ return true;
+ return false;
+}
+
/* Return varpool node for given symbol and check it is a function. */
inline varpool_node *
&& !externally_visible);
}
+/* Return true when function can be removed from callgraph
+ if all direct calls are eliminated. */
+
+inline bool
+cgraph_node::can_remove_if_no_direct_calls_and_refs_p (void)
+{
+ gcc_checking_assert (!global.inlined_to);
+ /* Instrumentation clones should not be removed before
+ instrumentation happens. New callers may appear after
+ instrumentation. */
+ if (instrumentation_clone
+ && !chkp_function_instrumented_p (decl))
+ return false;
+ /* Extern inlines can always go, we will use the external definition. */
+ if (DECL_EXTERNAL (decl))
+ return true;
+ /* When function is needed, we can not remove it. */
+ if (force_output || used_from_other_partition)
+ return false;
+ if (DECL_STATIC_CONSTRUCTOR (decl)
+ || DECL_STATIC_DESTRUCTOR (decl))
+ return false;
+ /* Only COMDAT functions can be removed if externally visible. */
+ if (externally_visible
+ && (!DECL_COMDAT (decl)
+ || forced_by_abi
+ || used_from_object_file_p ()))
+ return false;
+ return true;
+}
+
/* Return true when variable can be removed from variable pool
if all direct calls are eliminated. */
return dyn_cast <varpool_node *> (symtab_node::get_alias_target ());
}
+/* Walk the alias chain to return the symbol NODE is alias of.
+ If NODE is not an alias, return NODE.
+ When AVAILABILITY is non-NULL, get minimal availability in the chain. */
+
+inline symtab_node *
+symtab_node::ultimate_alias_target (enum availability *availability)
+{
+ if (!alias)
+ {
+ if (availability)
+ *availability = get_availability ();
+ return this;
+ }
+
+ return ultimate_alias_target_1 (availability);
+}
+
/* Given function symbol, walk the alias chain to return the function node
is alias of. Do not walk through thunks.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */
inline cgraph_node *
cgraph_node::ultimate_alias_target (enum availability *availability)
{
- cgraph_node *n = dyn_cast <cgraph_node *> (symtab_node::ultimate_alias_target
- (availability));
+ cgraph_node *n = dyn_cast <cgraph_node *>
+ (symtab_node::ultimate_alias_target (availability));
if (!n && availability)
*availability = AVAIL_NOT_AVAILABLE;
return n;
}
/* Return true when the edge represents a direct recursion. */
+
inline bool
cgraph_edge::recursive_p (void)
{
return false;
}
-inline symtab_node * symtab_node::get_create (tree node)
+/* Return symtab_node for NODE or create one if it is not present
+ in symtab. */
+
+inline symtab_node *
+symtab_node::get_create (tree node)
{
if (TREE_CODE (node) == VAR_DECL)
return varpool_node::get_create (node);
return cgraph_node::get_create (node);
}
+/* Return availability of NODE. */
+
+inline enum availability
+symtab_node::get_availability (void)
+{
+ if (is_a <cgraph_node *> (this))
+ return dyn_cast <cgraph_node *> (this)->get_availability ();
+ else
+ return dyn_cast <varpool_node *> (this)->get_availability ();;
+}
+
+/* Call calback on symtab node and aliases associated to this node.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+
+inline bool
+symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (callback (this, data))
+ return true;
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
+/* Call callback on function and aliases associated to the function.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+
+inline bool
+cgraph_node::call_for_symbol_and_aliases (bool (*callback) (cgraph_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (callback (this, data))
+ return true;
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
+/* Call calback on varpool symbol and aliases associated to varpool symbol.
+ When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
+ skipped. */
+
+inline bool
+varpool_node::call_for_symbol_and_aliases (bool (*callback) (varpool_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ if (callback (this, data))
+ return true;
+ if (has_aliases_p ())
+ return call_for_symbol_and_aliases_1 (callback, data, include_overwritable);
+ return false;
+}
+
/* Build polymorphic call context for indirect call E. */
inline
return new_node;
}
-/* Return a new assembler name for a clone of DECL with SUFFIX. */
-
static GTY(()) unsigned int clone_fn_id_num;
+/* Return a new assembler name for a clone with SUFFIX of a decl named
+ NAME. */
+
tree
-clone_function_name (tree decl, const char *suffix)
+clone_function_name_1 (const char *name, const char *suffix)
{
- tree name = DECL_ASSEMBLER_NAME (decl);
- size_t len = IDENTIFIER_LENGTH (name);
+ size_t len = strlen (name);
char *tmp_name, *prefix;
prefix = XALLOCAVEC (char, len + strlen (suffix) + 2);
- memcpy (prefix, IDENTIFIER_POINTER (name), len);
+ memcpy (prefix, name, len);
strcpy (prefix + len + 1, suffix);
#ifndef NO_DOT_IN_LABEL
prefix[len] = '.';
return get_identifier (tmp_name);
}
+/* Return a new assembler name for a clone of DECL with SUFFIX. */
+
+tree
+clone_function_name (tree decl, const char *suffix)
+{
+ tree name = DECL_ASSEMBLER_NAME (decl);
+ return clone_function_name_1 (IDENTIFIER_POINTER (name), suffix);
+}
+
+
/* Create callgraph node clone with new declaration. The actual body will
be copied later at compilation stage.
char *name;
if (!in_lto_p)
- gcc_checking_assert (tree_versionable_function_p (old_decl));
+ gcc_checking_assert (tree_versionable_function_p (old_decl));
gcc_assert (local.can_change_signature || !args_to_skip);
ABI support for this. */
set_new_clone_decl_and_node_flags (new_node);
new_node->clone.tree_map = tree_map;
+ if (!implicit_section)
+ new_node->set_section (get_section ());
/* Clones of global symbols or symbols with unique names are unique. */
if ((TREE_PUBLIC (old_decl)
new_version_node->externally_visible = 0;
new_version_node->local.local = 1;
new_version_node->lowered = true;
+ if (!implicit_section)
+ new_version_node->set_section (get_section ());
/* Clones of global symbols or symbols with unique names are unique. */
if ((TREE_PUBLIC (old_decl)
&& !DECL_EXTERNAL (old_decl)
Common Report Var(flag_ipa_cp_clone) Optimization
Perform cloning to make Interprocedural constant propagation stronger
+fipa-cp-alignment
+Common Report Var(flag_ipa_cp_alignment) Optimization
+Perform alignment discovery and propagation to make Interprocedural constant propagation stronger
+
fipa-profile
Common Report Var(flag_ipa_profile) Init(0) Optimization
Perform interprocedural profile propagation
Common Report Var(flag_ssa_phiopt) Optimization
Optimize conditional patterns using SSA PHI nodes
+fstdarg-opt
+Common Report Var(flag_stdarg_opt) Init(1) Optimization
+Optimize amount of stdarg registers saved to stack at start of function
+
fvariable-expansion-in-unroller
Common Report Var(flag_variable_expansion_in_unroller) Optimization
Apply variable expansion when loops are unrolled
difference in top-level cv-qualification is subsumed by the
initialization itself and does not constitute a conversion. */
+ /* [dcl.init.ref]
+
+ Otherwise, the reference shall be an lvalue reference to a
+ non-volatile const type, or the reference shall be an rvalue
+ reference.
+
+ We try below to treat this as a bad conversion to improve diagnostics,
+ but if TO is an incomplete class, we need to reject this conversion
+ now to avoid unnecessary instantiation. */
+ if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !TYPE_REF_IS_RVALUE (rto)
+ && !COMPLETE_TYPE_P (to))
+ return NULL;
+
/* We're generating a temporary now, but don't bind any more in the
conversion (specifically, don't slice the temporary returned by a
conversion operator). */
for (tree var = BIND_EXPR_VARS (t); var; var = DECL_CHAIN (var))
if (TREE_CODE (var) == TYPE_DECL
- && DECL_IMPLICIT_TYPEDEF_P (var))
+ && DECL_IMPLICIT_TYPEDEF_P (var)
+ && !LAMBDA_TYPE_P (TREE_TYPE (var)))
return false;
return true;
}
r = cxx_eval_outermost_constant_expr (t, true, true, decl);
#ifdef ENABLE_CHECKING
- /* cp_tree_equal looks through NOPs, so allow them. */
gcc_assert (r == t
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == VIEW_CONVERT_EXPR
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
NULL_TREE, context,
/*entering_scope=*/0,
- tf_warning_or_error | tf_user);
+ complain | tf_user);
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
/* First try ordinary name lookup, ignoring hidden class name
injected via friend declaration. */
decl = lookup_name_prefer_type (name, 2);
+ decl = strip_using_decl (decl);
/* If that fails, the name will be placed in the smallest
non-class, non-function-prototype scope according to 3.3.1/5.
We may already have a hidden name declared as friend in this
&& targetm.cxx.cdtor_returns_this ()))
{
cdtor_label = build_decl (input_location,
- LABEL_DECL, NULL_TREE, NULL_TREE);
+ LABEL_DECL, NULL_TREE, void_type_node);
DECL_CONTEXT (cdtor_label) = current_function_decl;
}
case PRAGMA_IVDEP:
{
+ if (context == pragma_external)
+ {
+ error_at (pragma_tok->location,
+ "%<#pragma GCC ivdep%> must be inside a function");
+ break;
+ }
cp_parser_skip_to_pragma_eol (parser, pragma_tok);
cp_token *tok;
tok = cp_lexer_peek_token (the_parser->lexer);
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
return 0;
else
- return cp_tree_equal (ot, nt);
+ {
+ /* Try to treat a template non-type argument that has been converted
+ to the parameter type as equivalent to one that hasn't yet. */
+ for (enum tree_code code1 = TREE_CODE (ot);
+ CONVERT_EXPR_CODE_P (code1)
+ || code1 == NON_LVALUE_EXPR;
+ code1 = TREE_CODE (ot))
+ ot = TREE_OPERAND (ot, 0);
+ for (enum tree_code code2 = TREE_CODE (nt);
+ CONVERT_EXPR_CODE_P (code2)
+ || code2 == NON_LVALUE_EXPR;
+ code2 = TREE_CODE (nt))
+ nt = TREE_OPERAND (nt, 0);
+
+ return cp_tree_equal (ot, nt);
+ }
}
/* Returns 1 iff the OLDARGS and NEWARGS are in fact identical sets of
if (!t1 || !t2)
return false;
- for (code1 = TREE_CODE (t1);
- CONVERT_EXPR_CODE_P (code1)
- || code1 == NON_LVALUE_EXPR;
- code1 = TREE_CODE (t1))
- t1 = TREE_OPERAND (t1, 0);
- for (code2 = TREE_CODE (t2);
- CONVERT_EXPR_CODE_P (code2)
- || code2 == NON_LVALUE_EXPR;
- code2 = TREE_CODE (t2))
- t2 = TREE_OPERAND (t2, 0);
-
- /* They might have become equal now. */
- if (t1 == t2)
- return true;
+ code1 = TREE_CODE (t1);
+ code2 = TREE_CODE (t2);
if (code1 != code2)
return false;
case DYNAMIC_CAST_EXPR:
case IMPLICIT_CONV_EXPR:
case NEW_EXPR:
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
return false;
/* Now compare operands as usual. */
@end itemize
@node Bug Reporting
-@section How and where to Report Bugs
+@section How and Where to Report Bugs
@cindex compiler bugs, reporting
Bugs should be reported to the bug database at @value{BUGURL}.
effects of recomputing it.
@node __int128
-@section 128-bit integers
+@section 128-bit Integers
@cindex @code{__int128} data types
As an extension the integer scalar type @code{__int128} is supported for
@end smallexample
@node Empty Structures
-@section Structures With No Members
+@section Structures with No Members
@cindex empty structures
@cindex zero-size structures
are used.
@node Pointers to Arrays
-@section Pointers to arrays with qualifiers work as expected
+@section Pointers to Arrays with Qualifiers Work as Expected
@cindex pointers to arrays
@cindex const qualifier
signedness without a cast.
@node Offsetof
-@section Offsetof
+@section Support for @code{offsetof}
@findex __builtin_offsetof
GCC implements for both C and C++ a syntactic extension to implement
identifier, or a sequence of member accesses and array references.
@node __sync Builtins
-@section Legacy __sync Built-in Functions for Atomic Memory Access
+@section Legacy @code{__sync} Built-in Functions for Atomic Memory Access
The following built-in functions
are intended to be compatible with those described
@end table
@node __atomic Builtins
-@section Built-in functions for memory model aware atomic operations
+@section Built-in Functions for Memory Model Aware Atomic Operations
The following built-in functions approximately match the requirements for
C++11 memory model. Many are similar to the @samp{__sync} prefixed built-in
@end deftypefn
@node Integer Overflow Builtins
-@section Built-in functions to perform arithmetics and arithmetic overflow checking.
+@section Built-in Functions to Perform Arithmetic with Overflow Checking
The following built-in functions allow performing simple arithmetic operations
together with checking whether the operations overflowed.
@end deftypefn
@node x86 specific memory model extensions for transactional memory
-@section x86 specific memory model extensions for transactional memory
+@section x86-Specific Memory Model Extensions for Transactional Memory
The x86 architecture supports additional memory ordering flags
to mark lock critical sections for hardware lock elision.
@end deftypefn
@node Cilk Plus Builtins
-@section Cilk Plus C/C++ language extension Built-in Functions.
+@section Cilk Plus C/C++ Language Extension Built-in Functions
GCC provides support for the following built-in reduction funtions if Cilk Plus
is enabled. Cilk Plus can be enabled using the @option{-fcilkplus} flag.
for more details.
@node Directly-mapped Integer Functions
-@subsubsection Directly-mapped Integer Functions
+@subsubsection Directly-Mapped Integer Functions
The functions listed below map directly to FR-V I-type instructions.
@end multitable
@node Directly-mapped Media Functions
-@subsubsection Directly-mapped Media Functions
+@subsubsection Directly-Mapped Media Functions
The functions listed below map directly to FR-V M-type instructions.
@end multitable
@node Raw read/write Functions
-@subsubsection Raw read/write Functions
+@subsubsection Raw Read/Write Functions
This sections describes built-in functions related to read and write
instructions to access memory. These functions generate
@end smallexample
@node x86 transactional memory intrinsics
-@subsection x86 transaction memory intrinsics
+@subsection x86 Transactional Memory Intrinsics
-Hardware transactional memory intrinsics for x86. These allow to use
+These hardware transactional memory intrinsics for x86 allow you to use
memory transactions with RTM (Restricted Transactional Memory).
-For using HLE (Hardware Lock Elision) see @ref{x86 specific memory model extensions for transactional memory} instead.
This support is enabled with the @option{-mrtm} option.
+For using HLE (Hardware Lock Elision) see
+@ref{x86 specific memory model extensions for transactional memory} instead.
A memory transaction commits all changes to memory in an atomic way,
as visible to other threads. If the transaction fails it is rolled back
@deftypefn {RTM Function} {unsigned} _xbegin ()
Start a RTM (Restricted Transactional Memory) transaction.
-Returns _XBEGIN_STARTED when the transaction
+Returns @code{_XBEGIN_STARTED} when the transaction
started successfully (note this is not 0, so the constant has to be
-explicitely tested). When the transaction aborts all side effects
+explicitly tested). If the transaction aborts, all side-effects
are undone and an abort code is returned. There is no guarantee
any transaction ever succeeds, so there always needs to be a valid
-tested fallback path.
+fallback path.
@end deftypefn
@smallexample
@}
@end smallexample
-Valid abort status bits (when the value is not @code{_XBEGIN_STARTED}) are:
+If the transaction aborts, the return value is one of:
@table @code
@item _XABORT_EXPLICIT
-Transaction explicitely aborted with @code{_xabort}. The parameter passed
-to @code{_xabort} is available with @code{_XABORT_CODE(status)}
+Transaction was explicitly aborted with @code{_xabort}. The parameter passed
+to @code{_xabort} is available with @code{_XABORT_CODE(status)}.
@item _XABORT_RETRY
Transaction retry is possible.
@item _XABORT_CONFLICT
-Transaction abort due to a memory conflict with another thread
+Transaction abort due to a memory conflict with another thread.
@item _XABORT_CAPACITY
-Transaction abort due to the transaction using too much memory
+Transaction abort due to the transaction using too much memory.
@item _XABORT_DEBUG
-Transaction abort due to a debug trap
+Transaction abort due to a debug trap.
@item _XABORT_NESTED
-Transaction abort in a inner nested transaction
+Transaction abort in an inner nested transaction.
@end table
@deftypefn {RTM Function} {void} _xend ()
-Commit the current transaction. When no transaction is active this will
-fault. All memory side effects of the transactions will become visible
-to other threads in an atomic matter.
+Commit the current transaction. When no transaction is active this faults.
+All memory side-effects of the transaction become visible
+to other threads in an atomic manner.
@end deftypefn
@deftypefn {RTM Function} {int} _xtest ()
-Return a value not zero when a transaction is currently active, otherwise 0.
+Return a nonzero value if a transaction is currently active, otherwise 0.
@end deftypefn
@deftypefn {RTM Function} {void} _xabort (status)
Abort the current transaction. When no transaction is active this is a no-op.
-status must be a 8bit constant, that is included in the status code returned
-by @code{_xbegin}
+The @var{status} is an 8-bit constant; its value is encoded in the return
+value from @code{_xbegin}.
@end deftypefn
@node Target Format Checks
@node Unnamed Fields
-@section Unnamed struct/union fields within structs/unions
+@section Unnamed Structure and Union Fields
@cindex @code{struct}
@cindex @code{union}
@end itemize
@node Binary constants
-@section Binary constants using the @samp{0b} prefix
+@section Binary Constants using the @samp{0b} Prefix
@cindex Binary constants using the @samp{0b} prefix
Integer constants can be written as binary constants, consisting of a
another way to control placement of these constructs.
@node C++ Interface
-@section #pragma interface and implementation
+@section C++ Interface and Implementation Pragmas
@cindex interface and implementation headers, C++
@cindex C++ interface and implementation headers
@end enumerate
@node Bound member functions
-@section Extracting the function pointer from a bound pointer to member function
+@section Extracting the Function Pointer from a Bound Pointer to Member Function
@cindex pmf
@cindex pointer to member function
@cindex bound pointer to member function
@c man end
@node Gcov Data Files
-@section Brief description of @command{gcov} data files
+@section Brief Description of @command{gcov} Data Files
@command{gcov} uses two files for profiling. The names of these files
are derived from the original @emph{object} file by substituting the
coverage files.
@node Cross-profiling
-@section Data file relocation to support cross-profiling
+@section Data File Relocation to Support Cross-Profiling
Running the program will cause profile output to be generated. For each
source file compiled with @option{-fprofile-arcs}, an accompanying @file{.gcda}
@c For copying conditions, see the file gcc.texi.
@node C Implementation
-@chapter C Implementation-defined behavior
+@chapter C Implementation-Defined Behavior
@cindex implementation-defined behavior, C language
A conforming implementation of ISO C is required to document its
@end itemize
@node Floating point implementation
-@section Floating point
+@section Floating Point
@itemize @bullet
@item
@end itemize
@node Arrays and pointers implementation
-@section Arrays and pointers
+@section Arrays and Pointers
@itemize @bullet
@item
@end itemize
@node Structures unions enumerations and bit-fields implementation
-@section Structures, unions, enumerations, and bit-fields
+@section Structures, Unions, Enumerations, and Bit-Fields
@itemize @bullet
@item
@end itemize
@node Preprocessing directives implementation
-@section Preprocessing directives
+@section Preprocessing Directives
@xref{Implementation-defined behavior, , Implementation-defined
behavior, cpp, The C Preprocessor}, for details of these aspects of
@end itemize
@node Library functions implementation
-@section Library functions
+@section Library Functions
The behavior of most of these points are dependent on the implementation
of the C library, and are not defined by GCC itself.
@end itemize
@node Locale-specific behavior implementation
-@section Locale-specific behavior
+@section Locale-Specific Behavior
The behavior of these points are dependent on the implementation
of the C library, and are not defined by GCC itself.
@c For copying conditions, see the file gcc.texi.
@node C++ Implementation
-@chapter C++ Implementation-defined behavior
+@chapter C++ Implementation-Defined Behavior
@cindex implementation-defined behavior, C++ language
A conforming implementation of ISO C++ is required to document its
@end menu
@node Conditionally-supported behavior
-@section Conditionally-supported behavior
+@section Conditionally-Supported Behavior
@cite{Each implementation shall include documentation that identifies
all conditionally-supported constructs that it does not support (C++0x
@end itemize
@node Exception handling
-@section Exception handling
+@section Exception Handling
@itemize @bullet
@item
-fgcse-sm -fhoist-adjacent-loads -fif-conversion @gol
-fif-conversion2 -findirect-inlining @gol
-finline-functions -finline-functions-called-once -finline-limit=@var{n} @gol
--finline-small-functions -fipa-cp -fipa-cp-clone @gol
+-finline-small-functions -fipa-cp -fipa-cp-clone -fipa-cp-alignment @gol
-fipa-pta -fipa-profile -fipa-pure-const -fipa-reference -fipa-icf @gol
-fira-algorithm=@var{algorithm} @gol
-fira-region=@var{region} -fira-hoist-pressure @gol
-fshrink-wrap -fsignaling-nans -fsingle-precision-constant @gol
-fsplit-ivs-in-unroller -fsplit-wide-types -fssa-phiopt @gol
-fstack-protector -fstack-protector-all -fstack-protector-strong @gol
--fstack-protector-explicit -fstrict-aliasing @gol
+-fstack-protector-explicit -fstdarg-opt -fstrict-aliasing @gol
-fstrict-overflow -fthread-jumps -ftracer -ftree-bit-ccp @gol
-ftree-builtin-call-dce -ftree-ccp -ftree-ch @gol
-ftree-coalesce-inline-vars -ftree-coalesce-vars -ftree-copy-prop @gol
-mcustom-fpu-cfg=@var{name} @gol
-mhal -msmallc -msys-crt0=@var{name} -msys-lib=@var{name}}
+@emph{Nvidia PTX Options}
+@gccoptlist{-m32 -m64 -mmainkernel}
+
@emph{PDP-11 Options}
@gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol
-mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol
-maccumulate-outgoing-args -minvalid-symbols @gol
-matomic-model=@var{atomic-model} @gol
-mbranch-cost=@var{num} -mzdcbranch -mno-zdcbranch @gol
+-mcbranch-force-delay-slot @gol
-mfused-madd -mno-fused-madd -mfsca -mno-fsca -mfsrra -mno-fsrra @gol
-mpretend-cmove -mtas}
-finline-small-functions @gol
-findirect-inlining @gol
-fipa-cp @gol
+-fipa-cp-alignment @gol
-fipa-sra @gol
-fipa-icf @gol
-fisolate-erroneous-paths-dereference @gol
(see @option{--param ipcp-unit-growth=@var{value}}).
This flag is enabled by default at @option{-O3}.
+@item -fipa-cp-alignment
+@opindex -fipa-cp-alignment
+When enabled, this optimization propagates alignment of function
+parameters to support better vectorization and string operations.
+
+This flag is enabled by default at @option{-O2} and @option{-Os}. It
+requires that @option{-fipa-cp} is enabled.
+
@item -fipa-icf
@opindex fipa-icf
Perform Identical Code Folding for functions and read-only variables.
Like @option{-fstack-protector} but only protects those functions which
have the @code{stack_protect} attribute
+@item -fstdarg-opt
+@opindex fstdarg-opt
+Optimize the prologue of variadic argument functions with respect to usage of
+those arguments.
+
@item -fsection-anchors
@opindex fsection-anchors
Try to reduce the number of symbolic address calculations by using
@c man end
@node Spec Files
-@section Specifying subprocesses and the switches to pass to them
+@section Specifying Subprocesses and the Switches to Pass to Them
@cindex Spec Files
@command{gcc} is a driver program. It performs its job by invoking a
* MSP430 Options::
* NDS32 Options::
* Nios II Options::
+* Nvidia PTX Options::
* PDP-11 Options::
* picoChip Options::
* PowerPC Options::
over the appropriate part of this option.
@end table
-@subsubsection @option{-march} and @option{-mcpu} feature modifiers
+@subsubsection @option{-march} and @option{-mcpu} Feature Modifiers
@cindex @option{-march} feature modifiers
@cindex @option{-mcpu} feature modifiers
Feature modifiers used with @option{-march} and @option{-mcpu} can be one
resulting address space is not contained in the incoming address space.
@end table
-@subsubsection @code{EIND} and Devices with more than 128 Ki Bytes of Flash
+@subsubsection @code{EIND} and Devices with More Than 128 Ki Bytes of Flash
@cindex @code{EIND}
Pointers in the implementation are 16@tie{}bits wide.
The address of a function or label is represented as word address so
@end table
+@node Nvidia PTX Options
+@subsection Nvidia PTX Options
+@cindex Nvidia PTX options
+@cindex nvptx options
+
+These options are defined for Nvidia PTX:
+
+@table @gcctabopt
+
+@item -m32
+@itemx -m64
+@opindex m32
+@opindex m64
+Generate code for 32-bit or 64-bit ABI.
+
+@item -mmainkernel
+@opindex mmainkernel
+Link in code for a __main kernel. This is for stand-alone instead of
+offloading execution.
+
+@end table
+
@node PDP-11 Options
@subsection PDP-11 Options
@cindex PDP-11 Options
enabled by default when generating code for SH4 and SH4A. It can be explicitly
disabled by specifying @option{-mno-zdcbranch}.
+@item -mcbranch-force-delay-slot
+@opindex mcbranch-force-delay-slot
+Force the usage of delay slots for conditional branches, which stuffs the delay
+slot with a @code{nop} if a suitable instruction can't be found. By default
+this option is disabled. It can be enabled to work around hardware bugs as
+found in the original SH7055.
+
@item -mfused-madd
@itemx -mno-fused-madd
@opindex mfused-madd
@node Objective-C
@comment node-name, next, previous, up
-@chapter GNU Objective-C features
+@chapter GNU Objective-C Features
This document is meant to describe some of the GNU Objective-C
features. It is not intended to teach you Objective-C. There are
@c =========================================================================
@node GNU Objective-C runtime API
-@section GNU Objective-C runtime API
+@section GNU Objective-C Runtime API
This section is specific for the GNU Objective-C runtime. If you are
using a different runtime, you can skip it.
@c =========================================================================
@node Modern GNU Objective-C runtime API
-@subsection Modern GNU Objective-C runtime API
+@subsection Modern GNU Objective-C Runtime API
The GNU Objective-C runtime provides an API which is similar to the
one provided by the ``Objective-C 2.0'' Apple/NeXT Objective-C
@c =========================================================================
@node Traditional GNU Objective-C runtime API
-@subsection Traditional GNU Objective-C runtime API
+@subsection Traditional GNU Objective-C Runtime API
The GNU Objective-C runtime used to provide a different API, which we
call the ``traditional'' GNU Objective-C runtime API. Functions
@c =========================================================================
@node Executing code before main
-@section @code{+load}: Executing code before main
+@section @code{+load}: Executing Code before @code{main}
This section is specific for the GNU Objective-C runtime. If you are
using a different runtime, you can skip it.
@node What you can and what you cannot do in +load
-@subsection What you can and what you cannot do in @code{+load}
+@subsection What You Can and Cannot Do in @code{+load}
@code{+load} is to be used only as a last resort. Because it is
executed very early, most of the Objective-C runtime machinery will
@node Type encoding
-@section Type encoding
+@section Type Encoding
This is an advanced section. Type encodings are used extensively by
the compiler and by the runtime, but you generally do not need to know
@end menu
@node Legacy type encoding
-@subsection Legacy type encoding
+@subsection Legacy Type Encoding
Unfortunately, historically GCC used to have a number of bugs in its
encoding code. The NeXT runtime expects GCC to emit type encodings in
a bit offset or the underlying field type.
@node @@encode
-@subsection @@encode
+@subsection @code{@@encode}
GNU Objective-C supports the @code{@@encode} syntax that allows you to
create a type encoding from a C/Objective-C type. For example,
invalid and will cause a compilation error.
@node Method signatures
-@subsection Method signatures
+@subsection Method Signatures
This section documents the encoding of method types, which is rarely
needed to use Objective-C. You should skip it at a first reading; the
@c =========================================================================
@node Constant string objects
-@section Constant string objects
+@section Constant String Objects
GNU Objective-C provides constant string objects that are generated
directly by the compiler. You declare a constant string object by
@c =========================================================================
@node compatibility_alias
-@section compatibility_alias
+@section @code{compatibility_alias}
The keyword @code{@@compatibility_alias} allows you to define a class name
as equivalent to another class name. For example:
@c =========================================================================
@node Fast enumeration
-@section Fast enumeration
+@section Fast Enumeration
@menu
* Using fast enumeration::
@c ================================
@node Using fast enumeration
-@subsection Using fast enumeration
+@subsection Using Fast Enumeration
GNU Objective-C provides support for the fast enumeration syntax:
@c ================================
@node c99-like fast enumeration syntax
-@subsection c99-like fast enumeration syntax
+@subsection C99-Like Fast Enumeration Syntax
A c99-like declaration syntax is also allowed:
@c ================================
@node Fast enumeration details
-@subsection Fast enumeration details
+@subsection Fast Enumeration Details
Here is a more technical description with the gory details. Consider the code
@c ================================
@node Fast enumeration protocol
-@subsection Fast enumeration protocol
+@subsection Fast Enumeration Protocol
If you want your own collection object to be usable with fast
enumeration, you need to have it implement the method
@c =========================================================================
@node Messaging with the GNU Objective-C runtime
-@section Messaging with the GNU Objective-C runtime
+@section Messaging with the GNU Objective-C Runtime
This section is specific for the GNU Objective-C runtime. If you are
using a different runtime, you can skip it.
@c =========================================================================
@node Dynamically registering methods
-@subsection Dynamically registering methods
+@subsection Dynamically Registering Methods
If @code{objc_msg_lookup()} does not find a suitable method
implementation, because the receiver does not implement the required
@c =========================================================================
@node Forwarding hook
-@subsection Forwarding hook
+@subsection Forwarding Hook
The GNU Objective-C runtime provides a hook, called
@code{__objc_msg_forward2}, which is called by
attempts to follow one or more versions of that standard, possibly
with some exceptions, and possibly with some extensions.
-@section C language
+@section C Language
@cindex C standard
@cindex C standards
@cindex ANSI C standard
information concerning the history of C that is available online, see
@uref{http://gcc.gnu.org/readings.html}
-@section C++ language
+@section C++ Language
GCC supports the original ISO C++ standard (1998) and contains
experimental support for the second ISO C++ standard (2011).
@option{-std=gnu++11} (for C++11 with GNU extensions). The default, if
no C++ language dialect options are given, is @option{-std=gnu++98}.
-@section Objective-C and Objective-C++ languages
+@section Objective-C and Objective-C++ Languages
@cindex Objective-C
@cindex Objective-C++
For more information concerning the history of Objective-C that is
available online, see @uref{http://gcc.gnu.org/readings.html}
-@section Go language
+@section Go Language
As of the GCC 4.7.1 release, GCC supports the Go 1 language standard,
described at @uref{http://golang.org/doc/go1.html}.
-@section References for other languages
+@section References for Other Languages
@xref{Top, GNAT Reference Manual, About This Guide, gnat_rm,
GNAT Reference Manual}, for information on standard
@node Name lookup
-@subsection Name lookup, templates, and accessing members of base classes
+@subsection Name Lookup, Templates, and Accessing Members of Base Classes
@cindex base class members
@cindex two-stage name lookup
gen_remaining_tmpl_value_param_die_attribute ();
/* Add the name for the main input file now. We delayed this from
- dwarf2out_init to avoid complications with PCH. */
- add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+ dwarf2out_init to avoid complications with PCH.
+ For LTO produced units use a fixed artificial name to avoid
+ leaking tempfile names into the dwarf. */
+ if (!in_lto_p)
+ add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
+ else
+ add_name_attribute (comp_unit_die (), "<artificial>");
if (!IS_ABSOLUTE_PATH (filename) || targetm.force_at_comp_dir)
add_comp_dir_attribute (comp_unit_die ());
else if (get_AT (comp_unit_die (), DW_AT_comp_dir) == NULL)
if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
return HARD_DEP;
+ /* If NEXT is intended to sit adjacent to this instruction, we don't
+ want to try to break any dependencies. Treat it as a HARD_DEP. */
+ if (SCHED_GROUP_P (next))
+ return HARD_DEP;
+
/* Now we've got NEXT with speculative deps only.
1. Look at the deps to see what we have to do.
2. Check if we can do 'todo'. */
/* Enum of rank_for_schedule heuristic decisions. */
enum rfs_decision {
- RFS_DEBUG, RFS_LIVE_RANGE_SHRINK1, RFS_LIVE_RANGE_SHRINK2,
+ RFS_LIVE_RANGE_SHRINK1, RFS_LIVE_RANGE_SHRINK2,
RFS_SCHED_GROUP, RFS_PRESSURE_DELAY, RFS_PRESSURE_TICK,
RFS_FEEDS_BACKTRACK_INSN, RFS_PRIORITY, RFS_SPECULATION,
RFS_SCHED_RANK, RFS_LAST_INSN, RFS_PRESSURE_INDEX,
/* Corresponding strings for print outs. */
static const char *rfs_str[RFS_N] = {
- "RFS_DEBUG", "RFS_LIVE_RANGE_SHRINK1", "RFS_LIVE_RANGE_SHRINK2",
+ "RFS_LIVE_RANGE_SHRINK1", "RFS_LIVE_RANGE_SHRINK2",
"RFS_SCHED_GROUP", "RFS_PRESSURE_DELAY", "RFS_PRESSURE_TICK",
"RFS_FEEDS_BACKTRACK_INSN", "RFS_PRIORITY", "RFS_SPECULATION",
"RFS_SCHED_RANK", "RFS_LAST_INSN", "RFS_PRESSURE_INDEX",
/* Schedule debug insns as early as possible. */
if (DEBUG_INSN_P (tmp) && !DEBUG_INSN_P (tmp2))
- return rfs_result (RFS_DEBUG, -1, tmp, tmp2);
+ return -1;
else if (!DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
- return rfs_result (RFS_DEBUG, 1, tmp, tmp2);
+ return 1;
else if (DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
- return rfs_result (RFS_DEBUG, INSN_LUID (tmp) - INSN_LUID (tmp2),
- tmp, tmp2);
+ return INSN_LUID (tmp) - INSN_LUID (tmp2);
else
return INSN_RFS_DEBUG_ORIG_ORDER (tmp2) - INSN_RFS_DEBUG_ORIG_ORDER (tmp);
}
}
}
-/* Sort the ready list READY by ascending priority, using the SCHED_SORT
- macro. */
-
-void
-ready_sort (struct ready_list *ready)
+/* Separate DEBUG_INSNS from normal insns. DEBUG_INSNs go to the end
+ of array. */
+static void
+ready_sort_debug (struct ready_list *ready)
{
int i;
rtx_insn **first = ready_lastpos (ready);
- int n_ready_non_debug = ready->n_ready;
for (i = 0; i < ready->n_ready; ++i)
- {
- if (DEBUG_INSN_P (first[i]))
- --n_ready_non_debug;
- else
- {
- INSN_RFS_DEBUG_ORIG_ORDER (first[i]) = i;
+ if (!DEBUG_INSN_P (first[i]))
+ INSN_RFS_DEBUG_ORIG_ORDER (first[i]) = i;
- if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
- setup_insn_reg_pressure_info (first[i]);
- }
- }
+ qsort (first, ready->n_ready, sizeof (rtx), rank_for_schedule_debug);
+}
- if (sched_pressure == SCHED_PRESSURE_MODEL
- && model_curr_point < model_num_insns)
- model_set_excess_costs (first, ready->n_ready);
+/* Sort non-debug insns in the ready list READY by ascending priority.
+ Assumes that all debug insns are separated from the real insns. */
+static void
+ready_sort_real (struct ready_list *ready)
+{
+ int i;
+ rtx_insn **first = ready_lastpos (ready);
+ int n_ready_real = ready->n_ready - ready->n_debug;
+
+ if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
+ for (i = 0; i < n_ready_real; ++i)
+ setup_insn_reg_pressure_info (first[i]);
+ else if (sched_pressure == SCHED_PRESSURE_MODEL
+ && model_curr_point < model_num_insns)
+ model_set_excess_costs (first, n_ready_real);
rank_for_schedule_stats_t stats1;
if (sched_verbose >= 4)
stats1 = rank_for_schedule_stats;
- if (n_ready_non_debug < ready->n_ready)
- /* Separate DEBUG_INSNS from normal insns. DEBUG_INSNs go to the end
- of array. */
- qsort (first, ready->n_ready, sizeof (rtx), rank_for_schedule_debug);
- else
- {
- if (n_ready_non_debug == 2)
- swap_sort (first, n_ready_non_debug);
- else if (n_ready_non_debug > 2)
- qsort (first, n_ready_non_debug, sizeof (rtx), rank_for_schedule);
- }
+ if (n_ready_real == 2)
+ swap_sort (first, n_ready_real);
+ else if (n_ready_real > 2)
+ qsort (first, n_ready_real, sizeof (rtx), rank_for_schedule);
if (sched_verbose >= 4)
{
}
}
+/* Sort the ready list READY by ascending priority. */
+static void
+ready_sort (struct ready_list *ready)
+{
+ if (ready->n_debug > 0)
+ ready_sort_debug (ready);
+ else
+ ready_sort_real (ready);
+}
+
/* PREV is an insn that is ready to execute. Adjust its priority if that
will help shorten or lengthen register lifetimes as appropriate. Also
provide a hook for the target to tweak itself. */
if (!reload_completed
&& ready.n_ready - ready.n_debug > MAX_SCHED_READY_INSNS)
{
- ready_sort (&ready);
+ ready_sort_debug (&ready);
+ ready_sort_real (&ready);
/* Find first free-standing insn past MAX_SCHED_READY_INSNS.
If there are debug insns, we know they're first. */
if (sched_verbose >= 2)
{
fprintf (sched_dump,
- ";;\t\tReady list on entry: %d insns\n", ready.n_ready);
+ ";;\t\tReady list on entry: %d insns: ", ready.n_ready);
+ debug_ready_list (&ready);
fprintf (sched_dump,
";;\t\t before reload => truncated to %d insns\n", i);
}
symtab->call_cgraph_insertion_hooks (clone);
/* Clone all aliases. */
- for (i = 0; node->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
- struct cgraph_node *chkp_alias
- = chkp_maybe_create_clone (alias->decl);
- chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
- }
+ for (i = 0; node->iterate_direct_aliases (i, ref); i++)
+ {
+ struct cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
+ struct cgraph_node *chkp_alias
+ = chkp_maybe_create_clone (alias->decl);
+ chkp_alias->create_reference (clone, IPA_REF_ALIAS, NULL);
+ }
/* Clone all thunks. */
for (e = node->callers; e; e = e->next_caller)
FOR_EACH_DEFINED_SYMBOL (symbol)
{
+ struct cgraph_node *fun;
symbol->aux = NULL;
if (!symbol->get_comdat_group ()
&& !symbol->alias
+ /* Thunks to external functions do not need to be categorized. */
+ && (!(fun = dyn_cast <cgraph_node *> (symbol))
+ || !fun->thunk.thunk_p
+ || fun->function_symbol ()->definition)
&& symbol->real_symbol_p ())
{
tree *val = map.get (symbol);
if (op != NOP_EXPR)
{
if (op != POINTER_PLUS_EXPR
- && op != PLUS_EXPR
- && op != MINUS_EXPR)
+ && op != PLUS_EXPR)
goto prop_fail;
tree operand = ipa_get_jf_pass_through_operand (jfunc);
if (!tree_fits_shwi_p (operand))
else
{
src_idx = ipa_get_jf_ancestor_formal_id (jfunc);
- offset = ipa_get_jf_ancestor_offset (jfunc);
+ offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT;;
}
src_lats = ipa_get_parm_lattices (caller_info, src_idx);
bool dumped_sth = false;
bool found_useful_result = false;
+ if (!opt_for_fn (node->decl, flag_ipa_cp_alignment))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Not considering %s for alignment discovery "
+ "and propagate; -fipa-cp-alignment: disabled.\n",
+ node->name ());
+ continue;
+ }
+
if (info->ipcp_orig_node)
info = IPA_NODE_REF (info->ipcp_orig_node);
/* Compare T2 and T2 based on name or structure. */
static bool
-odr_subtypes_equivalent_p (tree t1, tree t2, hash_set<type_pair,pair_traits> *visited)
+odr_subtypes_equivalent_p (tree t1, tree t2,
+ hash_set<type_pair,pair_traits> *visited)
{
bool an1, an2;
prevailing = vtable;
vtable = tmp;
}
- if (warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
OPT_Wodr,
"virtual table of type %qD violates one definition rule",
DECL_CONTEXT (vtable->decl)))
{
struct ipa_ref *ref1, *ref2;
bool end1, end2;
+
end1 = !prevailing->iterate_reference (n1, ref1);
end2 = !vtable->iterate_reference (n2, ref2);
- if (end1 && end2)
- return;
- if (!end1 && !end2
- && DECL_ASSEMBLER_NAME (ref1->referred->decl)
- != DECL_ASSEMBLER_NAME (ref2->referred->decl)
- && !n2
- && !DECL_VIRTUAL_P (ref2->referred->decl)
- && DECL_VIRTUAL_P (ref1->referred->decl))
+
+ /* !DECL_VIRTUAL_P means RTTI entry;
+ We warn when RTTI is lost because non-RTTI previals; we silently
+ accept the other case. */
+ while (!end2
+ && (end1
+ || (DECL_ASSEMBLER_NAME (ref1->referred->decl)
+ != DECL_ASSEMBLER_NAME (ref2->referred->decl)
+ && DECL_VIRTUAL_P (ref1->referred->decl)))
+ && !DECL_VIRTUAL_P (ref2->referred->decl))
{
- if (warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
"virtual table of type %qD contains RTTI information",
DECL_CONTEXT (vtable->decl)))
{
- inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "but is prevailed by one without from other translation unit");
- inform (DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "but is prevailed by one without from other translation "
+ "unit");
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
"RTTI will not work on this type");
}
n2++;
end2 = !vtable->iterate_reference (n2, ref2);
}
- if (!end1 && !end2
- && DECL_ASSEMBLER_NAME (ref1->referred->decl)
- != DECL_ASSEMBLER_NAME (ref2->referred->decl)
- && !n1
- && !DECL_VIRTUAL_P (ref1->referred->decl)
- && DECL_VIRTUAL_P (ref2->referred->decl))
+ while (!end1
+ && (end2
+ || (DECL_ASSEMBLER_NAME (ref2->referred->decl)
+ != DECL_ASSEMBLER_NAME (ref1->referred->decl)
+ && DECL_VIRTUAL_P (ref2->referred->decl)))
+ && !DECL_VIRTUAL_P (ref1->referred->decl))
{
n1++;
end1 = !vtable->iterate_reference (n1, ref1);
}
+
+ /* Finished? */
+ if (end1 && end2)
+ {
+ /* Extra paranoia; compare the sizes. We do not have information
+ about virtual inheritance offsets, so just be sure that these
+ match.
+ Do this as very last check so the not very informative error
+ is not output too often. */
+ if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl))
+ {
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+ "virtual table of type %qD violates "
+ "one definition rule ",
+ DECL_CONTEXT (vtable->decl)))
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "the conflicting type defined in another translation "
+ "unit has virtual table of different size");
+ }
+ }
+ return;
+ }
+
+ if (!end1 && !end2)
+ {
+ if (DECL_ASSEMBLER_NAME (ref1->referred->decl)
+ == DECL_ASSEMBLER_NAME (ref2->referred->decl))
+ continue;
+
+ /* If the loops above stopped on non-virtual pointer, we have
+ mismatch in RTTI information mangling. */
+ if (!DECL_VIRTUAL_P (ref1->referred->decl)
+ && !DECL_VIRTUAL_P (ref2->referred->decl))
+ {
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+ "virtual table of type %qD violates "
+ "one definition rule ",
+ DECL_CONTEXT (vtable->decl)))
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "the conflicting type defined in another translation "
+ "unit virtual table with different RTTI information");
+ }
+ return;
+ }
+ /* At this point both REF1 and REF2 points either to virtual table
+ or virtual method. If one points to virtual table and other to
+ method we can complain the same way as if one table was shorter
+ than other pointing out the extra method. */
+ gcc_assert (DECL_VIRTUAL_P (ref1->referred->decl)
+ && (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL
+ || TREE_CODE (ref1->referred->decl) == VAR_DECL));
+ gcc_assert (DECL_VIRTUAL_P (ref2->referred->decl)
+ && (TREE_CODE (ref2->referred->decl) == FUNCTION_DECL
+ || TREE_CODE (ref2->referred->decl) == VAR_DECL));
+ if (TREE_CODE (ref1->referred->decl)
+ != TREE_CODE (ref2->referred->decl))
+ {
+ if (TREE_CODE (ref1->referred->decl) == VAR_DECL)
+ end1 = true;
+ else if (TREE_CODE (ref2->referred->decl) == VAR_DECL)
+ end2 = true;
+ }
+ }
+
+ /* Complain about size mismatch. Either we have too many virutal
+ functions or too many virtual table pointers. */
if (end1 || end2)
{
if (end1)
"one definition rule",
DECL_CONTEXT (vtable->decl)))
{
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
- "the conflicting type defined in another translation "
- "unit");
- inform (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (ref1->referring->decl))),
- "contains additional virtual method %qD",
- ref1->referred->decl);
+ if (TREE_CODE (ref1->referring->decl) == FUNCTION_DECL)
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "the conflicting type defined in another translation "
+ "unit");
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (ref1->referring->decl))),
+ "contains additional virtual method %qD",
+ ref1->referred->decl);
+ }
+ else
+ {
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "the conflicting type defined in another translation "
+ "unit has virtual table table with more entries");
+ }
}
return;
}
- if (DECL_ASSEMBLER_NAME (ref1->referred->decl)
- != DECL_ASSEMBLER_NAME (ref2->referred->decl))
+
+ /* And in the last case we have either mistmatch in between two virtual
+ methods or two virtual table pointers. */
+ if (warning_at (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
+ "virtual table of type %qD violates "
+ "one definition rule ",
+ DECL_CONTEXT (vtable->decl)))
{
- if (warning_at (DECL_SOURCE_LOCATION
- (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 0,
- "virtual table of type %qD violates "
- "one definition rule ",
- DECL_CONTEXT (vtable->decl)))
+ if (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)
{
inform (DECL_SOURCE_LOCATION
(TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
"the conflicting type defined in another translation "
"unit");
+ gcc_assert (TREE_CODE (ref2->referred->decl)
+ == FUNCTION_DECL);
inform (DECL_SOURCE_LOCATION (ref1->referred->decl),
"virtual method %qD", ref1->referred->decl);
inform (DECL_SOURCE_LOCATION (ref2->referred->decl),
"ought to match virtual method %qD but does not",
ref2->referred->decl);
- return;
}
+ else
+ inform (DECL_SOURCE_LOCATION
+ (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
+ "the conflicting type defined in another translation "
+ "unit has virtual table table with different contents");
+ return;
}
}
}
bool warn, bool *warned, const char *reason)
{
tree decl2 = TYPE_NAME (t2);
+ if (warned)
+ *warned = false;
if (!warn)
return;
return false;
}
- if (TREE_CODE (t1) == ENUMERAL_TYPE)
+ if (TREE_CODE (t1) == ENUMERAL_TYPE
+ && TYPE_VALUES (t1) && TYPE_VALUES (t2))
{
tree v1, v2;
for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
f2 = TREE_CHAIN (f2);
if (!f1 || !f2)
break;
+ if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2))
+ {
+ warn_odr (t1, t2, NULL, NULL, warn, warned,
+ G_("a type with different virtual table pointers"
+ " is defined in another translation unit"));
+ return false;
+ }
if (DECL_ARTIFICIAL (f1) != DECL_ARTIFICIAL (f2))
- break;
+ {
+ warn_odr (t1, t2, NULL, NULL, warn, warned,
+ G_("a type with different bases is defined "
+ "in another translation unit"));
+ return false;
+ }
if (DECL_NAME (f1) != DECL_NAME (f2)
&& !DECL_ARTIFICIAL (f1))
{
"in another translation unit"));
return false;
}
- if (!odr_subtypes_equivalent_p (TREE_TYPE (f1), TREE_TYPE (f2), visited))
+ if (!odr_subtypes_equivalent_p (TREE_TYPE (f1),
+ TREE_TYPE (f2), visited))
{
- /* Do not warn about artificial fields and just go into generic
- field mismatch warning. */
+ /* Do not warn about artificial fields and just go into
+ generic field mismatch warning. */
if (DECL_ARTIFICIAL (f1))
break;
}
if (!gimple_compare_field_offset (f1, f2))
{
- /* Do not warn about artificial fields and just go into generic
- field mismatch warning. */
+ /* Do not warn about artificial fields and just go into
+ generic field mismatch warning. */
if (DECL_ARTIFICIAL (f1))
break;
- warn_odr (t1, t2, t1, t2, warn, warned,
+ warn_odr (t1, t2, f1, f2, warn, warned,
G_("fields has different layout "
"in another translation unit"));
return false;
are not the same. */
if (f1 || f2)
{
- if (f1 && DECL_ARTIFICIAL (f1))
- f1 = NULL;
- if (f2 && DECL_ARTIFICIAL (f2))
- f2 = NULL;
- if (f1 || f2)
- warn_odr (t1, t2, f1, f2, warn, warned,
- G_("a type with different number of fields "
- "is defined in another translation unit"));
- /* Ideally we should never get this generic message. */
+ if ((f1 && DECL_VIRTUAL_P (f1)) || (f2 && DECL_VIRTUAL_P (f2)))
+ warn_odr (t1, t2, NULL, NULL, warn, warned,
+ G_("a type with different virtual table pointers"
+ " is defined in another translation unit"));
+ if ((f1 && DECL_ARTIFICIAL (f1))
+ || (f2 && DECL_ARTIFICIAL (f2)))
+ warn_odr (t1, t2, NULL, NULL, warn, warned,
+ G_("a type with different bases is defined "
+ "in another translation unit"));
else
warn_odr (t1, t2, f1, f2, warn, warned,
- G_("a type with different memory representation "
+ G_("a type with different number of fields "
"is defined in another translation unit"));
return false;
val->types_set = new hash_set<tree>;
/* Always prefer complete type to be the leader. */
- if ((!COMPLETE_TYPE_P (val->type) || !TYPE_BINFO (val->type))
- && (COMPLETE_TYPE_P (type) && TYPE_BINFO (val->type)))
+
+ if (!COMPLETE_TYPE_P (val->type) && COMPLETE_TYPE_P (type))
+ build_bases = true;
+ else if (COMPLETE_TYPE_P (val->type) && !COMPLETE_TYPE_P (type))
+ ;
+ else if (TREE_CODE (val->type) == ENUMERAL_TYPE
+ && TREE_CODE (type) == ENUMERAL_TYPE
+ && !TYPE_VALUES (val->type) && TYPE_VALUES (type))
+ build_bases = true;
+ else if (TREE_CODE (val->type) == RECORD_TYPE
+ && TREE_CODE (type) == RECORD_TYPE
+ && TYPE_BINFO (type) && !TYPE_BINFO (val->type))
+ build_bases = true;
+
+ if (build_bases)
{
tree tmp = type;
- build_bases = true;
type = val->type;
val->type = tmp;
}
if (base_mismatch)
{
if (!warned && !val->odr_violated)
- warn_odr (type, val->type, NULL, NULL,
- !warned, &warned,
- "a type with the same name but different base "
- "type is defined in another translation unit");
- warn_types_mismatch (type1, type2);
+ {
+ warn_odr (type, val->type, NULL, NULL,
+ !warned, &warned,
+ "a type with the same name but different base "
+ "type is defined in another translation unit");
+ if (warned)
+ warn_types_mismatch (type1, type2);
+ }
break;
}
if (BINFO_OFFSET (base1) != BINFO_OFFSET (base2))
"layout is defined in another translation unit");
break;
}
+ /* One base is polymorphic and the other not.
+ This ought to be diagnosed earlier, but do not ICE in the
+ checking bellow. */
+ if (!TYPE_BINFO (type1) != !TYPE_BINFO (type2)
+ || (TYPE_BINFO (type1)
+ && polymorphic_type_binfo_p (TYPE_BINFO (type1))
+ != polymorphic_type_binfo_p (TYPE_BINFO (type2))))
+ {
+ gcc_assert (val->odr_violated);
+ base_mismatch = true;
+ break;
+ }
}
#ifdef ENABLE_CHECKING
/* Sanity check that all bases will be build same way again. */
val->anonymous_namespace = type_in_anonymous_namespace_p (type);
build_bases = COMPLETE_TYPE_P (val->type);
insert_to_odr_array = true;
+ *slot = val;
}
if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type);
val->all_derivations_known = type_all_derivations_known_p (type);
- *slot = val;
for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++)
/* For now record only polymorphic types. other are
pointless for devirtualization and we can not precisely
fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "",
DECL_SOURCE_FILE (TYPE_NAME (t->type)),
DECL_SOURCE_LINE (TYPE_NAME (t->type)));
+ if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type)))
+ fprintf (f, "%*s mangled name: %s\n", indent * 2, "",
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (TYPE_NAME (t->type))));
}
if (t->bases.length ())
{
return true;
for (i = 0; node->iterate_referring (i, ref); i++)
-
if ((ref->use == IPA_REF_ALIAS
&& referenced_from_vtable_p (dyn_cast<cgraph_node *> (ref->referring)))
|| (ref->use == IPA_REF_ADDR
if (e1->flags != e2->flags)
return return_false_with_msg ("flags comparison returns false");
- if (!bb_dict_test (bb_dict, e1->src->index, e2->src->index))
+ if (!bb_dict_test (&bb_dict, e1->src->index, e2->src->index))
return return_false_with_msg ("edge comparison returns false");
- if (!bb_dict_test (bb_dict, e1->dest->index, e2->dest->index))
+ if (!bb_dict_test (&bb_dict, e1->dest->index, e2->dest->index))
return return_false_with_msg ("BB comparison returns false");
if (!m_checker->compare_edge (e1, e2))
corresponds to TARGET. */
bool
-sem_function::bb_dict_test (auto_vec<int> bb_dict, int source, int target)
+sem_function::bb_dict_test (vec<int> *bb_dict, int source, int target)
{
source++;
target++;
- if (bb_dict.length () <= (unsigned)source)
- bb_dict.safe_grow_cleared (source + 1);
+ if (bb_dict->length () <= (unsigned)source)
+ bb_dict->safe_grow_cleared (source + 1);
- if (bb_dict[source] == 0)
+ if ((*bb_dict)[source] == 0)
{
- bb_dict[source] = target;
+ (*bb_dict)[source] = target;
return true;
}
else
- return bb_dict[source] == target;
+ return (*bb_dict)[source] == target;
}
/* Iterates all tree types in T1 and T2 and returns true if all types
/* Basic blocks dictionary BB_DICT returns true if SOURCE index BB
corresponds to TARGET. */
- bool bb_dict_test (auto_vec<int> bb_dict, int source, int target);
+ bool bb_dict_test (vec<int> *bb_dict, int source, int target);
/* Iterates all tree types in T1 and T2 and returns true if all types
are compatible. If COMPARE_POLYMORPHIC is set to true,
{
struct cgraph_node *node;
bool self_recursive;
+ bool uninlinable;
int growth;
};
{
gcc_checking_assert (e->inline_failed);
+ if (cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+ {
+ d->uninlinable = true;
+ continue;
+ }
+
if (e->caller == d->node
|| (e->caller->global.inlined_to
&& e->caller->global.inlined_to == d->node))
int
estimate_growth (struct cgraph_node *node)
{
- struct growth_data d = { node, 0, false };
+ struct growth_data d = { node, false, false, 0 };
struct inline_summary *info = inline_summaries->get (node);
- node->call_for_symbol_thunks_and_aliases (do_estimate_growth_1, &d, true);
+ node->call_for_symbol_and_aliases (do_estimate_growth_1, &d, true);
/* For self recursive functions the growth estimation really should be
infinity. We don't want to return very large values because the growth
return zero or negative growths. */
if (d.self_recursive)
d.growth = d.growth < info->size ? info->size : d.growth;
- else if (DECL_EXTERNAL (node->decl))
+ else if (DECL_EXTERNAL (node->decl) || d.uninlinable)
;
else
{
return d.growth;
}
+/* Verify if there are fewer than MAX_CALLERS. */
+
+static bool
+check_callers (cgraph_node *node, int *max_callers)
+{
+ ipa_ref *ref;
+
+ for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+ {
+ (*max_callers)--;
+ if (!*max_callers
+ || cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
+ return true;
+ }
+
+ FOR_EACH_ALIAS (node, ref)
+ if (check_callers (dyn_cast <cgraph_node *> (ref->referring), max_callers))
+ return true;
+
+ return false;
+}
+
/* Make cheap estimation if growth of NODE is likely positive knowing
EDGE_GROWTH of one particular edge.
and skip computation if there are too many callers. */
bool
-growth_likely_positive (struct cgraph_node *node, int edge_growth ATTRIBUTE_UNUSED)
+growth_likely_positive (struct cgraph_node *node,
+ int edge_growth)
{
int max_callers;
struct cgraph_edge *e;
for (e = node->callers; e; e = e->next_caller)
{
max_callers--;
- if (!max_callers)
+ if (!max_callers
+ || cgraph_inline_failed_type (e->inline_failed) == CIF_FINAL_ERROR)
return true;
}
+
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (node, ref)
+ if (check_callers (dyn_cast <cgraph_node *> (ref->referring), &max_callers))
+ return true;
+
return estimate_growth (node) > 0;
}
}
}
+/* Mark all call graph edges coming out of NODE and all nodes that have been
+ inlined to it as in_polymorphic_cdtor. */
+
+static void
+mark_all_inlined_calls_cdtor (cgraph_node *node)
+{
+ for (cgraph_edge *cs = node->callees; cs; cs = cs->next_callee)
+ {
+ cs->in_polymorphic_cdtor = true;
+ if (!cs->inline_failed)
+ mark_all_inlined_calls_cdtor (cs->callee);
+ }
+ for (cgraph_edge *cs = node->indirect_calls; cs; cs = cs->next_callee)
+ cs->in_polymorphic_cdtor = true;
+}
+
/* Mark edge E as inlined and update callgraph accordingly. UPDATE_ORIGINAL
specify whether profile of original function should be updated. If any new
old_size = inline_summaries->get (to)->size;
inline_merge_summary (e);
+ if (e->in_polymorphic_cdtor)
+ mark_all_inlined_calls_cdtor (e->callee);
if (opt_for_fn (e->caller->decl, optimize))
new_edges_found = ipa_propagate_indirect_call_infos (curr, new_edges);
if (update_overall_summary)
if (node->global.inlined_to)
return false;
/* Does it have callers? */
- if (!node->call_for_symbol_thunks_and_aliases (has_caller_p, NULL, true))
+ if (!node->call_for_symbol_and_aliases (has_caller_p, NULL, true))
return false;
/* Inlining into all callers would increase size? */
if (estimate_growth (node) > 0)
return false;
/* All inlines must be possible. */
- if (node->call_for_symbol_thunks_and_aliases (check_callers, &has_hot_call,
- true))
+ if (node->call_for_symbol_and_aliases (check_callers, &has_hot_call,
+ true))
return false;
if (!cold && !has_hot_call)
return false;
if (want_inline_function_to_all_callers_p (node, cold))
{
int num_calls = 0;
- node->call_for_symbol_thunks_and_aliases (sum_callers, &num_calls,
- true);
- while (node->call_for_symbol_thunks_and_aliases
+ node->call_for_symbol_and_aliases (sum_callers, &num_calls,
+ true);
+ while (node->call_for_symbol_and_aliases
(inline_to_all_callers, &num_calls, true))
;
remove_functions = true;
struct ipa_propagate_frequency_data
{
+ cgraph_node *function_symbol;
bool maybe_unlikely_executed;
bool maybe_executed_once;
bool only_called_at_startup;
|| d->only_called_at_startup || d->only_called_at_exit);
edge = edge->next_caller)
{
- if (edge->caller != node)
+ if (edge->caller != d->function_symbol)
{
d->only_called_at_startup &= edge->caller->only_called_at_startup;
/* It makes sense to put main() together with the static constructors.
errors can make us to push function into unlikely section even when
it is executed by the train run. Transfer the function only if all
callers are unlikely executed. */
- if (profile_info && flag_branch_probabilities
+ if (profile_info
+ && opt_for_fn (d->function_symbol->decl, flag_branch_probabilities)
+ /* Thunks are not profiled. This is more or less implementation
+ bug. */
+ && !d->function_symbol->thunk.thunk_p
&& (edge->caller->frequency != NODE_FREQUENCY_UNLIKELY_EXECUTED
|| (edge->caller->global.inlined_to
&& edge->caller->global.inlined_to->frequency
bool
ipa_propagate_frequency (struct cgraph_node *node)
{
- struct ipa_propagate_frequency_data d = {true, true, true, true};
+ struct ipa_propagate_frequency_data d = {node, true, true, true, true};
bool changed = false;
/* We can not propagate anything useful about externally visible functions
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Processing frequency %s\n", node->name ());
- node->call_for_symbol_thunks_and_aliases (ipa_propagate_frequency_1, &d,
- true);
+ node->call_for_symbol_and_aliases (ipa_propagate_frequency_1, &d,
+ true);
if ((d.only_called_at_startup && !d.only_called_at_exit)
&& !node->only_called_at_startup)
{
bool update = false;
+ if (!opt_for_fn (n->decl, flag_ipa_profile))
+ continue;
+
for (e = n->indirect_calls; e; e = e->next_callee)
{
if (n->count)
order_pos = ipa_reverse_postorder (order);
for (i = order_pos - 1; i >= 0; i--)
{
- if (order[i]->local.local && ipa_propagate_frequency (order[i]))
+ if (order[i]->local.local
+ && opt_for_fn (order[i]->decl, flag_ipa_profile)
+ && ipa_propagate_frequency (order[i]))
{
for (e = order[i]->callees; e; e = e->next_callee)
if (e->callee->local.local && !e->callee->aux)
something_changed = false;
for (i = order_pos - 1; i >= 0; i--)
{
- if (order[i]->aux && ipa_propagate_frequency (order[i]))
+ if (order[i]->aux
+ && opt_for_fn (order[i]->decl, flag_ipa_profile)
+ && ipa_propagate_frequency (order[i]))
{
for (e = order[i]->callees; e; e = e->next_callee)
if (e->callee->local.local && !e->callee->aux)
if (jfunc->type == IPA_JF_PASS_THROUGH
&& ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
{
- if ((ici->agg_contents
- && !ipa_get_jf_pass_through_agg_preserved (jfunc))
- || (ici->polymorphic
- && !ipa_get_jf_pass_through_type_preserved (jfunc)))
+ if (ici->agg_contents
+ && !ipa_get_jf_pass_through_agg_preserved (jfunc)
+ && !ici->polymorphic)
ici->param_index = -1;
else
- ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
+ {
+ ici->param_index = ipa_get_jf_pass_through_formal_id (jfunc);
+ if (ici->polymorphic
+ && !ipa_get_jf_pass_through_type_preserved (jfunc))
+ ici->vptr_changed = true;
+ }
}
else if (jfunc->type == IPA_JF_ANCESTOR)
{
- if ((ici->agg_contents
- && !ipa_get_jf_ancestor_agg_preserved (jfunc))
- || (ici->polymorphic
- && !ipa_get_jf_ancestor_type_preserved (jfunc)))
+ if (ici->agg_contents
+ && !ipa_get_jf_ancestor_agg_preserved (jfunc)
+ && !ici->polymorphic)
ici->param_index = -1;
else
{
ici->param_index = ipa_get_jf_ancestor_formal_id (jfunc);
ici->offset += ipa_get_jf_ancestor_offset (jfunc);
+ if (ici->polymorphic
+ && !ipa_get_jf_ancestor_type_preserved (jfunc))
+ ici->vptr_changed = true;
}
}
else
}
FOR_EACH_DEFINED_FUNCTION (node)
{
- node->local.local |= node->local_p ();
+ if (!node->local.local)
+ node->local.local |= node->local_p ();
/* If we know that function can not be overwritten by a different semantics
and moreover its section can not be discarded, replace all direct calls
if (node->address_taken
&& !node->used_from_other_partition)
{
- if (!node->call_for_symbol_thunks_and_aliases
+ if (!node->call_for_symbol_and_aliases
(has_addr_references_p, NULL, true)
&& (!node->instrumentation_clone
|| !node->instrumented_version
{
if (TREE_ADDRESSABLE (vnode->decl) && dump_file)
fprintf (dump_file, " %s (non-addressable)", vnode->name ());
- vnode->call_for_node_and_aliases (clear_addressable_bit, NULL,
- true);
+ vnode->call_for_symbol_and_aliases (clear_addressable_bit, NULL,
+ true);
}
if (!address_taken && !written
/* Making variable in explicit section readonly can cause section
{
if (!TREE_READONLY (vnode->decl) && dump_file)
fprintf (dump_file, " %s (read-only)", vnode->name ());
- vnode->call_for_node_and_aliases (set_readonly_bit, NULL, true);
+ vnode->call_for_symbol_and_aliases (set_readonly_bit, NULL, true);
}
if (!vnode->writeonly && !read && !address_taken && written)
{
if (dump_file)
fprintf (dump_file, " %s (write-only)", vnode->name ());
- vnode->call_for_node_and_aliases (set_writeonly_bit, &remove_p,
- true);
+ vnode->call_for_symbol_and_aliases (set_writeonly_bit, &remove_p,
+ true);
}
}
if (dump_file)
single_user_map.put (var, user);
/* Enqueue all aliases for re-processing. */
- for (i = 0; var->iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS
- && !ref->referring->aux)
+ for (i = 0; var->iterate_direct_aliases (i, ref); i++)
+ if (!ref->referring->aux)
{
ref->referring->aux = first;
first = dyn_cast <varpool_node *> (ref->referring);
lto_symtab_encoder_t encoder)
{
bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node);
+ bool encode_initializer_p
+ = (node->definition
+ && lto_symtab_encoder_encode_initializer_p (encoder, node));
struct bitpack_d bp;
int ref;
const char *comdat;
const char *section;
tree group;
+ gcc_assert (!encode_initializer_p || node->definition);
+ gcc_assert (boundary_p || encode_initializer_p);
+
streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag,
LTO_symtab_variable);
streamer_write_hwi_stream (ob->main_stream, node->order);
bp_pack_value (&bp, node->force_output, 1);
bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1);
- bp_pack_value (&bp, node->body_removed
- || !lto_symtab_encoder_encode_initializer_p (encoder, node), 1);
+ bp_pack_value (&bp,
+ node->body_removed
+ || (!encode_initializer_p && !node->alias && node->definition),
+ 1);
bp_pack_value (&bp, node->implicit_section, 1);
bp_pack_value (&bp, node->writeonly, 1);
- bp_pack_value (&bp, node->definition, 1);
+ bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
+ 1);
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->weakref, 1);
bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
void
lto_streamer_init (void)
{
+#ifdef ENABLE_CHECKING
/* Check that all the TS_* handled by the reader and writer routines
match exactly the structures defined in treestruct.def. When a
new TS_* astructure is added, the streamer should be updated to
handle it. */
streamer_check_handled_ts_structures ();
+#endif
#ifdef LTO_STREAMER_DEBUG
tree_htab = new hash_table<tree_hash_entry> (31);
#include "ipa-inline.h"
#include "ipa-utils.h"
#include "lto-partition.h"
+#include "stringpool.h"
vec<ltrans_partition> ltrans_partitions;
free (order);
}
-/* Mangle NODE symbol name into a local name.
- This is necessary to do
- 1) if two or more static vars of same assembler name
- are merged into single ltrans unit.
- 2) if prevoiusly static var was promoted hidden to avoid possible conflict
- with symbols defined out of the LTO world.
-*/
+/* Return true if we must not change the name of the NODE. The name as
+ extracted from the corresponding decl should be passed in NAME. */
static bool
-privatize_symbol_name (symtab_node *node)
+must_not_rename (symtab_node *node, const char *name)
{
- tree decl = node->decl;
- cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
- const char *name;
-
- /* If we want to privatize instrumentation clone
- then we need to change original function name
- which is used via transparent alias chain. */
- if (cnode && cnode->instrumentation_clone)
- decl = cnode->orig_decl;
-
- name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-
/* Our renaming machinery do not handle more than one change of assembler name.
We should not need more than one anyway. */
if (node->lto_file_data
{
if (symtab->dump_file)
fprintf (symtab->dump_file,
- "Not privatizing symbol name: %s. It privatized already.\n",
- name);
- return false;
+ "Not privatizing symbol name: %s. It privatized already.\n",
+ name);
+ return true;
}
/* Avoid mangling of already mangled clones.
??? should have a flag whether a symbol has a 'private' name already,
{
if (symtab->dump_file)
fprintf (symtab->dump_file,
- "Not privatizing symbol name: %s. Has unique name.\n",
- name);
- return false;
+ "Not privatizing symbol name: %s. Has unique name.\n",
+ name);
+ return true;
}
+ return false;
+}
+
+/* If we are an offload compiler, we may have to rewrite symbols to be
+ valid on this target. Return either PTR or a modified version of it. */
+
+static const char *
+maybe_rewrite_identifier (const char *ptr)
+{
+#if defined ACCEL_COMPILER && (defined NO_DOT_IN_LABEL || defined NO_DOLLAR_IN_LABEL)
+#ifndef NO_DOT_IN_LABEL
+ char valid = '.';
+ const char reject[] = "$";
+#elif !defined NO_DOLLAR_IN_LABEL
+ char valid = '$';
+ const char reject[] = ".";
+#else
+ char valid = '_';
+ const char reject[] = ".$";
+#endif
+
+ char *copy = NULL;
+ const char *match = ptr;
+ for (;;)
+ {
+ size_t off = strcspn (match, reject);
+ if (match[off] == '\0')
+ break;
+ if (copy == NULL)
+ {
+ copy = xstrdup (ptr);
+ match = copy;
+ }
+ copy[off] = valid;
+ }
+ return match;
+#else
+ return ptr;
+#endif
+}
+
+/* Ensure that the symbol in NODE is valid for the target, and if not,
+ rewrite it. */
+
+static void
+validize_symbol_for_target (symtab_node *node)
+{
+ tree decl = node->decl;
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ if (must_not_rename (node, name))
+ return;
+
+ const char *name2 = maybe_rewrite_identifier (name);
+ if (name2 != name)
+ {
+ symtab->change_decl_assembler_name (decl, get_identifier (name2));
+ if (node->lto_file_data)
+ lto_record_renamed_decl (node->lto_file_data, name,
+ IDENTIFIER_POINTER
+ (DECL_ASSEMBLER_NAME (decl)));
+ }
+}
+
+/* Mangle NODE symbol name into a local name.
+ This is necessary to do
+ 1) if two or more static vars of same assembler name
+ are merged into single ltrans unit.
+ 2) if previously static var was promoted hidden to avoid possible conflict
+ with symbols defined out of the LTO world. */
+
+static bool
+privatize_symbol_name (symtab_node *node)
+{
+ tree decl = node->decl;
+ const char *name;
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+
+ /* If we want to privatize instrumentation clone
+ then we need to change original function name
+ which is used via transparent alias chain. */
+ if (cnode && cnode->instrumentation_clone)
+ decl = cnode->orig_decl;
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ if (must_not_rename (node, name))
+ return false;
+
+ name = maybe_rewrite_identifier (name);
symtab->change_decl_assembler_name (decl,
- clone_function_name (decl, "lto_priv"));
+ clone_function_name_1 (name,
+ "lto_priv"));
if (node->lto_file_data)
lto_record_renamed_decl (node->lto_file_data, name,
IDENTIFIER_POINTER
if (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN
&& DECL_VISIBILITY_SPECIFIED (node->decl)
&& TREE_PUBLIC (node->decl))
- return;
+ {
+ validize_symbol_for_target (node);
+ return;
+ }
gcc_checking_assert (!TREE_PUBLIC (node->decl)
&& !DECL_EXTERNAL (node->decl));
/* ... or if we do not partition it. This mean that it will
appear in every partition refernecing it. */
|| node->get_partitioning_class () != SYMBOL_PARTITION)
- continue;
+ {
+ validize_symbol_for_target (node);
+ continue;
+ }
promote_symbol (node);
}
{
symtab_node *node;
FOR_EACH_SYMBOL (node)
- rename_statics (NULL, node);
+ {
+ rename_statics (NULL, node);
+ validize_symbol_for_target (node);
+ }
}
(logs (pows @0 @1))
(mult @1 (logs @0)))))
+/* Narrowing of arithmetic and logical operations.
+
+ These are conceptually similar to the transformations performed for
+ the C/C++ front-ends by shorten_binary_op and shorten_compare. Long
+ term we want to move all that code out of the front-ends into here. */
+
+/* If we have a narrowing conversion of an arithmetic operation where
+ both operands are widening conversions from the same type as the outer
+ narrowing conversion. Then convert the innermost operands to a suitable
+ unsigned type (to avoid introducing undefined behaviour), perform the
+ operation and convert the result to the desired type. */
+(for op (plus minus)
+ (simplify
+ (convert (op (convert@2 @0) (convert@3 @1)))
+ (if (INTEGRAL_TYPE_P (type)
+ /* We check for type compatibility between @0 and @1 below,
+ so there's no need to check that @1/@3 are integral types. */
+ && INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@2))
+ /* The precision of the type of each operand must match the
+ precision of the mode of each operand, similarly for the
+ result. */
+ && (TYPE_PRECISION (TREE_TYPE (@0))
+ == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0))))
+ && (TYPE_PRECISION (TREE_TYPE (@1))
+ == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@1))))
+ && TYPE_PRECISION (type) == GET_MODE_PRECISION (TYPE_MODE (type))
+ /* The inner conversion must be a widening conversion. */
+ && TYPE_PRECISION (TREE_TYPE (@2)) > TYPE_PRECISION (TREE_TYPE (@0))
+ && ((GENERIC
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (@0))
+ == TYPE_MAIN_VARIANT (TREE_TYPE (@1)))
+ && (TYPE_MAIN_VARIANT (TREE_TYPE (@0))
+ == TYPE_MAIN_VARIANT (type)))
+ || (GIMPLE
+ && types_compatible_p (TREE_TYPE (@0), TREE_TYPE (@1))
+ && types_compatible_p (TREE_TYPE (@0), type))))
+ (if (TYPE_OVERFLOW_WRAPS (TREE_TYPE (@0)))
+ (convert (op @0 @1)))
+ (with { tree utype = unsigned_type_for (TREE_TYPE (@0)); }
+ (convert (op (convert:utype @0) (convert:utype @1)))))))
{ OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 },
+ { OPT_LEVELS_2_PLUS, OPT_fipa_cp_alignment, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 },
{ OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 },
if (!opts_set->x_flag_ipa_cp_clone
&& value && opts->x_flag_ipa_cp)
opts->x_flag_ipa_cp_clone = value;
+ if (!opts_set->x_flag_ipa_cp_alignment
+ && value && opts->x_flag_ipa_cp)
+ opts->x_flag_ipa_cp_alignment = value;
if (!opts_set->x_flag_predictive_commoning)
opts->x_flag_predictive_commoning = value;
if (!opts_set->x_flag_unswitch_loops)
extern int autopref_multipass_dfa_lookahead_guard (rtx_insn *, int);
-extern void ready_sort (struct ready_list *);
extern rtx_insn *ready_element (struct ready_list *, int);
extern rtx_insn **ready_lastpos (struct ready_list *);
tree test_label
= build_decl (curr_insn_location (),
- LABEL_DECL, NULL_TREE, NULL_TREE);
+ LABEL_DECL, NULL_TREE, void_type_node);
/* The default label could be reached either through the right
subtree or the left subtree. Divide the probability
Branch to a label where we will handle it later. */
test_label = build_decl (curr_insn_location (),
- LABEL_DECL, NULL_TREE, NULL_TREE);
+ LABEL_DECL, NULL_TREE, void_type_node);
probability = conditional_probability (
node->right->subtree_prob + default_prob/2,
subtree_prob + default_prob);
}
}
-/* Return true when RESOLUTION indicate that linker will use
- the symbol from non-LTO object files. */
-
-bool
-resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution)
-{
- return (resolution == LDPR_PREVAILING_DEF
- || resolution == LDPR_PREEMPTED_REG
- || resolution == LDPR_RESOLVED_EXEC
- || resolution == LDPR_RESOLVED_DYN);
-}
-
/* Hash sections by their names. */
hashval_t
/* IPA_REF_ALIAS is always inserted at the beginning of the list. */
if(use_type == IPA_REF_ALIAS)
- {
- list2->referring.safe_insert (0, ref);
- ref->referred_index = 0;
+ {
+ list2->referring.safe_insert (0, ref);
+ ref->referred_index = 0;
- for (unsigned int i = 1; i < list2->referring.length (); i++)
- list2->referring[i]->referred_index = i;
- }
+ for (unsigned int i = 1; i < list2->referring.length (); i++)
+ list2->referring[i]->referred_index = i;
+ }
else
- {
- list2->referring.safe_push (ref);
- ref->referred_index = list2->referring.length () - 1;
- }
+ {
+ list2->referring.safe_push (ref);
+ ref->referred_index = list2->referring.length () - 1;
+ }
ref->referring = this;
ref->referred = referred_node;
fprintf (file, "\n");
}
-/* Return true if list contains an alias. */
-bool
-symtab_node::has_aliases_p (void)
-{
- ipa_ref *ref = NULL;
- int i;
-
- for (i = 0; iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- return true;
- return false;
-}
-
-/* Iterates I-th reference in the list, REF is also set. */
-
-ipa_ref *
-symtab_node::iterate_reference (unsigned i, ipa_ref *&ref)
-{
- vec_safe_iterate (ref_list.references, i, &ref);
-
- return ref;
-}
-
-/* Iterates I-th referring item in the list, REF is also set. */
-
-ipa_ref *
-symtab_node::iterate_referring (unsigned i, ipa_ref *&ref)
-{
- ref_list.referring.iterate (i, &ref);
-
- return ref;
-}
-
-/* Iterates I-th referring alias item in the list, REF is also set. */
-
-ipa_ref *
-symtab_node::iterate_direct_aliases (unsigned i, ipa_ref *&ref)
-{
- ref_list.referring.iterate (i, &ref);
-
- if (ref && ref->use != IPA_REF_ALIAS)
- return NULL;
-
- return ref;
-}
-
static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
/* Dump base fields of symtab nodes to F. Not to be used directly. */
error ("double linked list of assembler names corrupted");
error_found = true;
}
+ if (body_removed && definition)
+ {
+ error ("node has body_removed but is definition");
+ error_found = true;
+ }
if (analyzed && !definition)
{
error ("node is analyzed byt it is not a definition");
}
}
-/* Return true when NODE is known to be used from other (non-LTO)
- object file. Known only when doing LTO via linker plugin. */
-
-bool
-symtab_node::used_from_object_file_p_worker (symtab_node *node)
-{
- if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl))
- return false;
- if (resolution_used_from_other_file_p (node->resolution))
- return true;
- return false;
-}
-
-
-/* Return true when symtab_node is known to be used from other (non-LTO)
- object file. Known only when doing LTO via linker plugin. */
-
-bool
-symtab_node::used_from_object_file_p (void)
-{
- return symtab_node::used_from_object_file_p_worker (this);
-}
-
/* Make DECL local. FIXME: We shouldn't need to mess with rtl this early,
but other code such as notice_global_symbol generates rtl. */
/* Walk the alias chain to return the symbol NODE is alias of.
If NODE is not an alias, return NODE.
- When AVAILABILITY is non-NULL, get minimal availability in the chain. */
+ Assumes NODE is known to be alias. */
symtab_node *
-symtab_node::ultimate_alias_target (enum availability *availability)
+symtab_node::ultimate_alias_target_1 (enum availability *availability)
{
bool weakref_p = false;
- if (!alias)
- {
- if (availability)
- *availability = get_availability ();
- return this;
- }
-
/* To determine visibility of the target, we follow ELF semantic of aliases.
Here alias is an alternative assembler name of a given definition. Its
availability prevails the availability of its target (i.e. static alias of
return h ? h->init : DEFAULT_INIT_PRIORITY;
}
-/* Return availability of NODE. */
-enum availability symtab_node::get_availability (void)
-{
- if (is_a <cgraph_node *> (this))
- return dyn_cast <cgraph_node *> (this)->get_availability ();
- else
- return dyn_cast <varpool_node *> (this)->get_availability ();;
-}
-
-
/* Return the finalization priority. */
priority_type
return true;
}
-/* Call calback on symtab node and aliases associated to this node.
- When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
- skipped. */
-
-bool
-symtab_node::call_for_symbol_and_aliases (bool (*callback) (symtab_node *,
- void *),
- void *data, bool include_overwritable)
-{
- int i;
- ipa_ref *ref;
-
- if (callback (this, data))
- return true;
- for (i = 0; iterate_referring (i, ref); i++)
- if (ref->use == IPA_REF_ALIAS)
- {
- symtab_node *alias = ref->referring;
- if (include_overwritable
- || alias->get_availability () > AVAIL_INTERPOSABLE)
- if (alias->call_for_symbol_and_aliases (callback, data,
- include_overwritable))
- return true;
- }
- return false;
-}
-
/* Worker searching noninterposable alias. */
bool
return 2;
}
+
+/* Worker for call_for_symbol_and_aliases. */
+
+bool
+symtab_node::call_for_symbol_and_aliases_1 (bool (*callback) (symtab_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
+{
+ ipa_ref *ref;
+ FOR_EACH_ALIAS (this, ref)
+ {
+ symtab_node *alias = ref->referring;
+ if (include_overwritable
+ || alias->get_availability () > AVAIL_INTERPOSABLE)
+ if (alias->call_for_symbol_and_aliases (callback, data,
+ include_overwritable))
+ return true;
+ }
+ return false;
+}
new_node->externally_visible = old_node->externally_visible;
new_node->lowered = true;
new_node->tm_clone = 1;
+ if (!old_node->implicit_section)
+ new_node->set_section (old_node->get_section ());
get_cg_data (&old_node, true)->clone = new_node;
if (old_node->get_availability () >= AVAIL_INTERPOSABLE)
PROP_cfg, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
- TODO_update_ssa_only_virtuals, /* todo_flags_start */
+ 0, /* todo_flags_start */
0, /* todo_flags_finish */
};
/* We want to transform
try { body; } catch { stuff; }
to
- normal_seqence:
+ normal_sequence:
body;
over:
- eh_seqence:
+ eh_sequence:
landing_pad:
stuff;
goto over;
this_state.cur_region = state->cur_region;
this_state.ehp_region = try_region;
+ /* Add eh_seq from lowering EH in the cleanup sequence after the cleanup
+ itself, so that e.g. for coverage purposes the nested cleanups don't
+ appear before the cleanup body. See PR64634 for details. */
+ gimple_seq old_eh_seq = eh_seq;
+ eh_seq = NULL;
+
out_label = NULL;
cleanup = gimple_try_cleanup (tp);
for (gsi = gsi_start (cleanup);
gimple_try_set_cleanup (tp, new_seq);
- return frob_into_branch_around (tp, try_region, out_label);
+ gimple_seq new_eh_seq = eh_seq;
+ eh_seq = old_eh_seq;
+ gimple_seq ret_seq = frob_into_branch_around (tp, try_region, out_label);
+ gimple_seq_add_seq (&eh_seq, new_eh_seq);
+ return ret_seq;
}
/* A subroutine of lower_eh_constructs_1. Lower a GIMPLE_TRY with a
if (var->alias && !var->analyzed)
any_aliases = true;
else if (!var->alias)
- var->call_for_node_and_aliases (create_emultls_var, &ctor_body, true);
+ var->call_for_symbol_and_aliases (create_emultls_var, &ctor_body, true);
}
/* If there were any aliases, then frob the alias_pairs vector. */
if (chain->combined)
{
/* For combined chains, just remove the statements that are used to
- compute the values of the expression (except for the root one). */
- for (i = 1; chain->refs.iterate (i, &a); i++)
- remove_stmt (a->stmt);
+ compute the values of the expression (except for the root one).
+ We delay this until after all chains are processed. */
}
else
{
FOR_EACH_VEC_ELT (chains, i, chain)
{
- if (chain->type == CT_INVARIANT || chain->combined)
+ if (chain->type == CT_INVARIANT)
continue;
+ if (chain->combined)
+ {
+ /* For combined chains, we can't handle unrolling if we replace
+ looparound PHIs. */
+ dref a;
+ unsigned j;
+ for (j = 1; chain->refs.iterate (j, &a); j++)
+ if (gimple_code (a->stmt) == GIMPLE_PHI)
+ return 1;
+ continue;
+ }
+
/* The best unroll factor for this chain is equal to the number of
temporary variables that we create for it. */
af = chain->length;
execute_pred_commoning_chain (loop, chain, tmp_vars);
}
+ FOR_EACH_VEC_ELT (chains, i, chain)
+ {
+ if (chain->type == CT_INVARIANT)
+ ;
+ else if (chain->combined)
+ {
+ /* For combined chains, just remove the statements that are used to
+ compute the values of the expression (except for the root one). */
+ dref a;
+ unsigned j;
+ for (j = 1; chain->refs.iterate (j, &a); j++)
+ remove_stmt (a->stmt);
+ }
+ }
+
update_ssa (TODO_update_ssa_only_virtuals);
}
return false;
}
+/* Return false if all callers have vuse attached to a call statement. */
+
+static bool
+some_callers_have_no_vuse_p (struct cgraph_node *node,
+ void *data ATTRIBUTE_UNUSED)
+{
+ struct cgraph_edge *cs;
+ for (cs = node->callers; cs; cs = cs->next_caller)
+ if (!cs->call_stmt || !gimple_vuse (cs->call_stmt))
+ return true;
+
+ return false;
+}
+
/* Convert all callers of NODE. */
static bool
goto simple_out;
}
+ if (node->call_for_symbol_thunks_and_aliases
+ (some_callers_have_no_vuse_p, NULL, true))
+ {
+ if (dump_file)
+ fprintf (dump_file, "There are callers with no VUSE attached "
+ "to a call stmt.\n");
+ goto simple_out;
+ }
+
bb_dereferences = XCNEWVEC (HOST_WIDE_INT,
func_param_count
* last_basic_block_for_fn (cfun));
if (!may_propagate_copy (op, val))
return;
- /* Do not propagate copies into simple IV increment statements.
- See PR23821 for how this can disturb IV analysis. */
- if (TREE_CODE (val) != INTEGER_CST
- && simple_iv_increment_p (stmt))
- return;
+ /* Do not propagate copies into BIVs.
+ See PR23821 and PR62217 for how this can disturb IV and
+ number of iteration analysis. */
+ if (TREE_CODE (val) != INTEGER_CST)
+ {
+ gimple def = SSA_NAME_DEF_STMT (op);
+ if (gimple_code (def) == GIMPLE_PHI
+ && gimple_bb (def)->loop_father->header == gimple_bb (def))
+ return;
+ }
/* Dump details. */
if (dump_file && (dump_flags & TDF_DETAILS))
&& absorbing_element_p (code_def, cond_rhs))))
{
gsi = gsi_for_stmt (cond);
+ if (INTEGRAL_TYPE_P (TREE_TYPE (lhs)))
+ {
+ /* Moving ASSIGN might change VR of lhs, e.g. when moving u_6
+ def-stmt in:
+ if (n_5 != 0)
+ goto <bb 3>;
+ else
+ goto <bb 4>;
+
+ <bb 3>:
+ # RANGE [0, 4294967294]
+ u_6 = n_5 + 4294967295;
+
+ <bb 4>:
+ # u_3 = PHI <u_6(3), 4294967295(2)> */
+ SSA_NAME_RANGE_INFO (lhs) = NULL;
+ SSA_NAME_ANTI_RANGE_P (lhs) = 0;
+ /* If available, we can use VR of phi result at least. */
+ tree phires = gimple_phi_result (phi);
+ struct range_info_def *phires_range_info
+ = SSA_NAME_RANGE_INFO (phires);
+ if (phires_range_info)
+ duplicate_ssa_name_range_info (lhs, SSA_NAME_RANGE_TYPE (phires),
+ phires_range_info);
+ }
gimple_stmt_iterator gsi_from = gsi_for_stmt (assign);
gsi_move_before (&gsi_from, &gsi);
replace_phi_edge_with_variable (cond_bb, e1, phi, lhs);
tem = fold_convert_loc (loc, optype, tem);
gsi = gsi_for_stmt (stmt);
+ unsigned int uid = gimple_uid (stmt);
/* In rare cases range->exp can be equal to lhs of stmt.
In that case we have to insert after the stmt rather then before
- it. */
- if (op == range->exp)
+ it. If stmt is a PHI, insert it at the start of the basic block. */
+ if (op != range->exp)
+ {
+ gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
+ tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
+ GSI_SAME_STMT);
+ gsi_prev (&gsi);
+ }
+ else if (gimple_code (stmt) != GIMPLE_PHI)
{
gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING);
tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, false,
}
else
{
+ gsi = gsi_after_labels (gimple_bb (stmt));
+ if (!gsi_end_p (gsi))
+ uid = gimple_uid (gsi_stmt (gsi));
+ else
+ {
+ gsi = gsi_start_bb (gimple_bb (stmt));
+ uid = 1;
+ while (!gsi_end_p (gsi))
+ {
+ uid = gimple_uid (gsi_stmt (gsi));
+ gsi_next (&gsi);
+ }
+ }
gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true,
GSI_SAME_STMT);
- gsi_prev (&gsi);
+ if (gsi_end_p (gsi))
+ gsi = gsi_last_bb (gimple_bb (stmt));
+ else
+ gsi_prev (&gsi);
}
for (; !gsi_end_p (gsi); gsi_prev (&gsi))
if (gimple_uid (gsi_stmt (gsi)))
break;
else
- gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt));
+ gimple_set_uid (gsi_stmt (gsi), uid);
oe->op = tem;
range->exp = exp;
case ARRAY_REF:
case ARRAY_RANGE_REF:
case COMPONENT_REF:
+ case IMAGPART_EXPR:
+ case REALPART_EXPR:
+ case BIT_FIELD_REF:
get_constraint_for_component_ref (t, results, address_p, lhs_p);
return;
case VIEW_CONVERT_EXPR:
get_constraint_for (lhsop, &lhsc);
- if (FLOAT_TYPE_P (TREE_TYPE (lhsop)))
- /* If the operation produces a floating point result then
- assume the value is not produced to transfer a pointer. */
- ;
- else if (code == POINTER_PLUS_EXPR)
+ if (code == POINTER_PLUS_EXPR)
get_constraint_for_ptr_offset (gimple_assign_rhs1 (t),
gimple_assign_rhs2 (t), &rhsc);
else if (code == BIT_AND_EXPR
{
gimple_stmt_iterator gsi;
+ /* Special case. We can get blocks that are forwarders, but are
+ not optimized away because they forward from outside a loop
+ to the loop header. We want to thread through them as we can
+ sometimes thread to the loop exit, which is obviously profitable.
+ the interesting case here is when the block has PHIs. */
+ if (gsi_end_p (gsi_start_nondebug_bb (bb))
+ && !gsi_end_p (gsi_start_phis (bb)))
+ return true;
+
/* If BB has a single successor or a single predecessor, then
there is no threading opportunity. */
if (single_succ_p (bb) || single_pred_p (bb))
= record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify,
*backedge_seen_p);
- /* If we didn't look at all the statements, the most likely reason is
- there were too many and thus duplicating this block is not profitable.
+ /* There's two reasons STMT might be null, and distinguishing
+ between them is important.
- Also note if we do not look at all the statements, then we may not
- have invalidated equivalences that are no longer valid if we threaded
- around a loop. Thus we must signal to our caller that this block
- is not suitable for use as a joiner in a threading path. */
+ First the block may not have had any statements. For example, it
+ might have some PHIs and unconditionally transfer control elsewhere.
+ Such blocks are suitable for jump threading, particularly as a
+ joiner block.
+
+ The second reason would be if we did not process all the statements
+ in the block (because there were too many to make duplicating the
+ block profitable. If we did not look at all the statements, then
+ we may not have invalidated everything needing invalidation. Thus
+ we must signal to our caller that this block is not suitable for
+ use as a joiner in a threading path. */
if (!stmt)
- return -1;
+ {
+ /* First case. The statement simply doesn't have any instructions, but
+ does have PHIs. */
+ if (gsi_end_p (gsi_start_nondebug_bb (e->dest))
+ && !gsi_end_p (gsi_start_phis (e->dest)))
+ return 0;
+ /* Second case. */
+ return -1;
+ }
+
/* If we stopped at a COND_EXPR or SWITCH_EXPR, see if we know which arm
will be taken. */
if (gimple_code (stmt) == GIMPLE_COND
/* opt_pass methods: */
virtual bool gate (function *fun)
{
- /* This optimization is only for stdarg functions. */
- return fun->stdarg != 0;
+ return (flag_stdarg_opt
+#ifdef ACCEL_COMPILER
+ /* Disable for GCC5 in the offloading compilers, as
+ va_list and gpr/fpr counter fields are not merged.
+ In GCC6 when stdarg is lowered late this shouldn't be
+ an issue. */
+ && !in_lto_p
+#endif
+ /* This optimization is only for stdarg functions. */
+ && fun->stdarg != 0);
}
virtual unsigned int execute (function *);
&& i != TI_TARGET_OPTION_DEFAULT
&& i != TI_TARGET_OPTION_CURRENT
&& i != TI_CURRENT_TARGET_PRAGMA
- && i != TI_CURRENT_OPTIMIZE_PRAGMA)
+ && i != TI_CURRENT_OPTIMIZE_PRAGMA
+ /* Skip va_list* related nodes if offloading. For native LTO
+ we want them to be merged for the stdarg pass, for offloading
+ they might not be identical between host and offloading target. */
+ && (!lto_stream_offload_p
+ || (i != TI_VA_LIST_TYPE
+ && i != TI_VA_LIST_GPR_COUNTER_FIELD
+ && i != TI_VA_LIST_FPR_COUNTER_FIELD)))
record_common_node (cache, global_trees[i]);
}
if (! potentially_threadable_block (bb))
continue;
- /* We only care about blocks ending in a COND_EXPR. While there
- may be some value in handling SWITCH_EXPR here, I doubt it's
- terribly important. */
- last = gsi_stmt (gsi_last_bb (bb));
+ last = last_stmt (bb);
/* We're basically looking for a switch or any kind of conditional with
integral or pointer type arguments. Note the type of the second
argument will be the same as the first argument, so no need to
- check it explicitly. */
- if (gimple_code (last) == GIMPLE_SWITCH
+ check it explicitly.
+
+ We also handle the case where there are no statements in the
+ block. This come up with forwarder blocks that are not
+ optimized away because they lead to a loop header. But we do
+ want to thread through them as we can sometimes thread to the
+ loop exit which is obviously profitable. */
+ if (!last
+ || gimple_code (last) == GIMPLE_SWITCH
|| (gimple_code (last) == GIMPLE_COND
&& TREE_CODE (gimple_cond_lhs (last)) == SSA_NAME
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (last)))
/* Lookup sub-BINFO of BINFO of TYPE at offset POS. */
-tree
+static tree
lookup_binfo_at_offset (tree binfo, tree type, HOST_WIDE_INT pos)
{
unsigned int i;
else if (offset != 0)
{
tree found_binfo = NULL, base_binfo;
- int offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
- / BITS_PER_UNIT);
+ /* Offsets in BINFO are in bytes relative to the whole structure
+ while POS is in bits relative to the containing field. */
+ int binfo_offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
+ / BITS_PER_UNIT);
for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == offset
+ if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == binfo_offset
&& types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
{
found_binfo = base_binfo;
if (found_binfo)
binfo = found_binfo;
else
- binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld), offset);
+ binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld),
+ binfo_offset);
}
type = TREE_TYPE (fld);
return false;
}
+#define OBJSZ_MAX_OFFSET (1024 * 16)
+
/* Expand UBSAN_OBJECT_SIZE internal call. */
bool
|| integer_all_onesp (size))
/* Yes, __builtin_object_size couldn't determine the
object size. */;
+ else if (TREE_CODE (offset) == INTEGER_CST
+ && wi::ges_p (wi::to_widest (offset), -OBJSZ_MAX_OFFSET)
+ && wi::les_p (wi::to_widest (offset), -1))
+ /* The offset is in range [-16K, -1]. */;
else
{
/* if (offset > objsize) */
gimple_set_location (g, loc);
gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
+ /* If the offset is small enough, we don't need the second
+ run-time check. */
+ if (TREE_CODE (offset) == INTEGER_CST
+ && wi::ges_p (wi::to_widest (offset), 0)
+ && wi::les_p (wi::to_widest (offset), OBJSZ_MAX_OFFSET))
+ *gsi = gsi_after_labels (then_bb);
+ else
+ {
+ /* Don't issue run-time error if (ptr > ptr + offset). That
+ may happen when computing a POINTER_PLUS_EXPR. */
+ basic_block then2_bb, fallthru2_bb;
+
+ gimple_stmt_iterator gsi2 = gsi_after_labels (then_bb);
+ cond_insert_point = create_cond_insert_point (&gsi2, false, false,
+ true, &then2_bb,
+ &fallthru2_bb);
+ /* Convert the pointer to an integer type. */
+ tree p = make_ssa_name (pointer_sized_int_node);
+ g = gimple_build_assign (p, NOP_EXPR, ptr);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&cond_insert_point, g, GSI_NEW_STMT);
+ p = gimple_assign_lhs (g);
+ /* Compute ptr + offset. */
+ g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
+ PLUS_EXPR, p, offset);
+ gimple_set_location (g, loc);
+ gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
+ /* Now build the conditional and put it into the IR. */
+ g = gimple_build_cond (LE_EXPR, p, gimple_assign_lhs (g),
+ NULL_TREE, NULL_TREE);
+ gimple_set_location (g, loc);
+ gsi_insert_after (&cond_insert_point, g, GSI_NEW_STMT);
+ *gsi = gsi_after_labels (then2_bb);
+ }
+
/* Generate __ubsan_handle_type_mismatch call. */
- *gsi = gsi_after_labels (then_bb);
if (flag_sanitize_undefined_trap_on_error)
g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TRAP), 0);
else
because dynamic linking might overwrite symbols
in shared libraries. */
bool resolved_locally = false;
- bool defined_locally = false;
+ bool defined_locally = !DECL_EXTERNAL (exp);
if (symtab_node *node = symtab_node::get (exp))
{
- if (node->definition || node->in_other_partition)
- {
- defined_locally = true;
- resolved_locally = (weak_dominate && !shlib);
- }
+ if (node->in_other_partition)
+ defined_locally = true;
if (resolution_to_local_definition_p (node->resolution))
defined_locally = resolved_locally = true;
else if (resolution_local_p (node->resolution))
resolved_locally = true;
}
+ if (defined_locally && weak_dominate && !shlib)
+ resolved_locally = true;
/* Undefined weak symbols are never defined locally. */
if (DECL_WEAK (exp) && !defined_locally)
fputs (ASM_APP_OFF, asm_out_file);
if (targetm.asm_file_start_file_directive)
- output_file_directive (asm_out_file, main_input_filename);
+ {
+ /* LTO produced units have no meaningful main_input_filename. */
+ if (in_lto_p)
+ output_file_directive (asm_out_file, "<artificial>");
+ else
+ output_file_directive (asm_out_file, main_input_filename);
+ }
}
/* This is a generic routine suitable for use as TARGET_ASM_FILE_END
size_t len;
if (DECL_INITIAL (decl) != error_mark_node
- || !in_lto_p)
+ || !in_lto_p
+ || !lto_file_data)
return DECL_INITIAL (decl);
timevar_push (TV_IPA_LTO_CTORS_IN);
return alias_node;
}
-/* Call calback on varpool symbol and aliases associated to varpool symbol.
- When INCLUDE_OVERWRITABLE is false, overwritable aliases and thunks are
- skipped. */
+/* Worker for call_for_symbol_and_aliases. */
bool
-varpool_node::call_for_node_and_aliases (bool (*callback) (varpool_node *,
- void *),
- void *data,
- bool include_overwritable)
+varpool_node::call_for_symbol_and_aliases_1 (bool (*callback) (varpool_node *,
+ void *),
+ void *data,
+ bool include_overwritable)
{
ipa_ref *ref;
- if (callback (this, data))
- return true;
-
FOR_EACH_ALIAS (this, ref)
{
varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
if (include_overwritable
|| alias->get_availability () > AVAIL_INTERPOSABLE)
- if (alias->call_for_node_and_aliases (callback, data,
- include_overwritable))
+ if (alias->call_for_symbol_and_aliases (callback, data,
+ include_overwritable))
return true;
}
return false;
#include "ansidecl.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
/* A floatformat consists of a sign bit, an exponent and a mantissa. Once the
bytes are concatenated according to the byteorder flag, then each of those
fields is contiguous. We number the bits with 0 being the most significant
extern int
floatformat_is_valid (const struct floatformat *fmt, const void *from);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* defined (FLOATFORMAT_H) */
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
-#include <stdlib.h>
-#include <string.h>
+#include <stddef.h>
#include "nvptx-malloc.h"
void *
oldsz = *sp;
}
if (oldsz != 0)
- memcpy (newptr, ptr, oldsz > newsz ? newsz : oldsz);
+ __builtin_memcpy (newptr, ptr, oldsz > newsz ? newsz : oldsz);
__nvptx_free (ptr);
return newptr;
va_list ap;
va_start (ap, msg);
- gomp_debug (kind, msg, ap);
+ gomp_vdebug (kind, msg, ap);
va_end (ap);
}
".version 3.1\n" \
".target sm_30\n" \
".address_size 64\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1);\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1);\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1);\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1);\n" \
".visible .func (.param .u32 %out_retval) GOACC_get_num_threads;\n" \
".visible .func (.param .u32 %out_retval) GOACC_get_thread_num;\n" \
".extern .func abort;\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_tid (.param .u32 %in_ar1)\n" \
+ "{\n" \
+ ".reg .u32 %ar1;\n" \
+ ".reg .u32 %retval;\n" \
+ ".reg .u64 %hr10;\n" \
+ ".reg .u32 %r22;\n" \
+ ".reg .u32 %r23;\n" \
+ ".reg .u32 %r24;\n" \
+ ".reg .u32 %r25;\n" \
+ ".reg .u32 %r26;\n" \
+ ".reg .u32 %r27;\n" \
+ ".reg .u32 %r28;\n" \
+ ".reg .u32 %r29;\n" \
+ ".reg .pred %r30;\n" \
+ ".reg .u32 %r31;\n" \
+ ".reg .pred %r32;\n" \
+ ".reg .u32 %r33;\n" \
+ ".reg .pred %r34;\n" \
+ ".local .align 8 .b8 %frame[4];\n" \
+ "ld.param.u32 %ar1,[%in_ar1];\n" \
+ "mov.u32 %r27,%ar1;\n" \
+ "st.local.u32 [%frame],%r27;\n" \
+ "ld.local.u32 %r28,[%frame];\n" \
+ "mov.u32 %r29,1;\n" \
+ "setp.eq.u32 %r30,%r28,%r29;\n" \
+ "@%r30 bra $L4;\n" \
+ "mov.u32 %r31,2;\n" \
+ "setp.eq.u32 %r32,%r28,%r31;\n" \
+ "@%r32 bra $L5;\n" \
+ "mov.u32 %r33,0;\n" \
+ "setp.eq.u32 %r34,%r28,%r33;\n" \
+ "@!%r34 bra $L8;\n" \
+ "mov.u32 %r23,%tid.x;\n" \
+ "mov.u32 %r22,%r23;\n" \
+ "bra $L7;\n" \
+ "$L4:\n" \
+ "mov.u32 %r24,%tid.y;\n" \
+ "mov.u32 %r22,%r24;\n" \
+ "bra $L7;\n" \
+ "$L5:\n" \
+ "mov.u32 %r25,%tid.z;\n" \
+ "mov.u32 %r22,%r25;\n" \
+ "bra $L7;\n" \
+ "$L8:\n" \
+ "{\n" \
+ "{\n" \
+ "call abort;\n" \
+ "}\n" \
+ "}\n" \
+ "$L7:\n" \
+ "mov.u32 %r26,%r22;\n" \
+ "mov.u32 %retval,%r26;\n" \
+ "st.param.u32 [%out_retval],%retval;\n" \
+ "ret;\n" \
+ "}\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_ntid (.param .u32 %in_ar1)\n" \
+ "{\n" \
+ ".reg .u32 %ar1;\n" \
+ ".reg .u32 %retval;\n" \
+ ".reg .u64 %hr10;\n" \
+ ".reg .u32 %r22;\n" \
+ ".reg .u32 %r23;\n" \
+ ".reg .u32 %r24;\n" \
+ ".reg .u32 %r25;\n" \
+ ".reg .u32 %r26;\n" \
+ ".reg .u32 %r27;\n" \
+ ".reg .u32 %r28;\n" \
+ ".reg .u32 %r29;\n" \
+ ".reg .pred %r30;\n" \
+ ".reg .u32 %r31;\n" \
+ ".reg .pred %r32;\n" \
+ ".reg .u32 %r33;\n" \
+ ".reg .pred %r34;\n" \
+ ".local .align 8 .b8 %frame[4];\n" \
+ "ld.param.u32 %ar1,[%in_ar1];\n" \
+ "mov.u32 %r27,%ar1;\n" \
+ "st.local.u32 [%frame],%r27;\n" \
+ "ld.local.u32 %r28,[%frame];\n" \
+ "mov.u32 %r29,1;\n" \
+ "setp.eq.u32 %r30,%r28,%r29;\n" \
+ "@%r30 bra $L11;\n" \
+ "mov.u32 %r31,2;\n" \
+ "setp.eq.u32 %r32,%r28,%r31;\n" \
+ "@%r32 bra $L12;\n" \
+ "mov.u32 %r33,0;\n" \
+ "setp.eq.u32 %r34,%r28,%r33;\n" \
+ "@!%r34 bra $L15;\n" \
+ "mov.u32 %r23,%ntid.x;\n" \
+ "mov.u32 %r22,%r23;\n" \
+ "bra $L14;\n" \
+ "$L11:\n" \
+ "mov.u32 %r24,%ntid.y;\n" \
+ "mov.u32 %r22,%r24;\n" \
+ "bra $L14;\n" \
+ "$L12:\n" \
+ "mov.u32 %r25,%ntid.z;\n" \
+ "mov.u32 %r22,%r25;\n" \
+ "bra $L14;\n" \
+ "$L15:\n" \
+ "{\n" \
+ "{\n" \
+ "call abort;\n" \
+ "}\n" \
+ "}\n" \
+ "$L14:\n" \
+ "mov.u32 %r26,%r22;\n" \
+ "mov.u32 %retval,%r26;\n" \
+ "st.param.u32 [%out_retval],%retval;\n" \
+ "ret;\n" \
+ "}\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_ctaid (.param .u32 %in_ar1)\n" \
+ "{\n" \
+ ".reg .u32 %ar1;\n" \
+ ".reg .u32 %retval;\n" \
+ ".reg .u64 %hr10;\n" \
+ ".reg .u32 %r22;\n" \
+ ".reg .u32 %r23;\n" \
+ ".reg .u32 %r24;\n" \
+ ".reg .u32 %r25;\n" \
+ ".reg .u32 %r26;\n" \
+ ".reg .u32 %r27;\n" \
+ ".reg .u32 %r28;\n" \
+ ".reg .u32 %r29;\n" \
+ ".reg .pred %r30;\n" \
+ ".reg .u32 %r31;\n" \
+ ".reg .pred %r32;\n" \
+ ".reg .u32 %r33;\n" \
+ ".reg .pred %r34;\n" \
+ ".local .align 8 .b8 %frame[4];\n" \
+ "ld.param.u32 %ar1,[%in_ar1];\n" \
+ "mov.u32 %r27,%ar1;\n" \
+ "st.local.u32 [%frame],%r27;\n" \
+ "ld.local.u32 %r28,[%frame];\n" \
+ "mov.u32 %r29,1;\n" \
+ "setp.eq.u32 %r30,%r28,%r29;\n" \
+ "@%r30 bra $L18;\n" \
+ "mov.u32 %r31,2;\n" \
+ "setp.eq.u32 %r32,%r28,%r31;\n" \
+ "@%r32 bra $L19;\n" \
+ "mov.u32 %r33,0;\n" \
+ "setp.eq.u32 %r34,%r28,%r33;\n" \
+ "@!%r34 bra $L22;\n" \
+ "mov.u32 %r23,%ctaid.x;\n" \
+ "mov.u32 %r22,%r23;\n" \
+ "bra $L21;\n" \
+ "$L18:\n" \
+ "mov.u32 %r24,%ctaid.y;\n" \
+ "mov.u32 %r22,%r24;\n" \
+ "bra $L21;\n" \
+ "$L19:\n" \
+ "mov.u32 %r25,%ctaid.z;\n" \
+ "mov.u32 %r22,%r25;\n" \
+ "bra $L21;\n" \
+ "$L22:\n" \
+ "{\n" \
+ "{\n" \
+ "call abort;\n" \
+ "}\n" \
+ "}\n" \
+ "$L21:\n" \
+ "mov.u32 %r26,%r22;\n" \
+ "mov.u32 %retval,%r26;\n" \
+ "st.param.u32 [%out_retval],%retval;\n" \
+ "ret;\n" \
+ "}\n" \
+ ".visible .func (.param .u32 %out_retval) GOACC_nctaid (.param .u32 %in_ar1)\n" \
+ "{\n" \
+ ".reg .u32 %ar1;\n" \
+ ".reg .u32 %retval;\n" \
+ ".reg .u64 %hr10;\n" \
+ ".reg .u32 %r22;\n" \
+ ".reg .u32 %r23;\n" \
+ ".reg .u32 %r24;\n" \
+ ".reg .u32 %r25;\n" \
+ ".reg .u32 %r26;\n" \
+ ".reg .u32 %r27;\n" \
+ ".reg .u32 %r28;\n" \
+ ".reg .u32 %r29;\n" \
+ ".reg .pred %r30;\n" \
+ ".reg .u32 %r31;\n" \
+ ".reg .pred %r32;\n" \
+ ".reg .u32 %r33;\n" \
+ ".reg .pred %r34;\n" \
+ ".local .align 8 .b8 %frame[4];\n" \
+ "ld.param.u32 %ar1,[%in_ar1];\n" \
+ "mov.u32 %r27,%ar1;\n" \
+ "st.local.u32 [%frame],%r27;\n" \
+ "ld.local.u32 %r28,[%frame];\n" \
+ "mov.u32 %r29,1;\n" \
+ "setp.eq.u32 %r30,%r28,%r29;\n" \
+ "@%r30 bra $L25;\n" \
+ "mov.u32 %r31,2;\n" \
+ "setp.eq.u32 %r32,%r28,%r31;\n" \
+ "@%r32 bra $L26;\n" \
+ "mov.u32 %r33,0;\n" \
+ "setp.eq.u32 %r34,%r28,%r33;\n" \
+ "@!%r34 bra $L29;\n" \
+ "mov.u32 %r23,%nctaid.x;\n" \
+ "mov.u32 %r22,%r23;\n" \
+ "bra $L28;\n" \
+ "$L25:\n" \
+ "mov.u32 %r24,%nctaid.y;\n" \
+ "mov.u32 %r22,%r24;\n" \
+ "bra $L28;\n" \
+ "$L26:\n" \
+ "mov.u32 %r25,%nctaid.z;\n" \
+ "mov.u32 %r22,%r25;\n" \
+ "bra $L28;\n" \
+ "$L29:\n" \
+ "{\n" \
+ "{\n" \
+ "call abort;\n" \
+ "}\n" \
+ "}\n" \
+ "$L28:\n" \
+ "mov.u32 %r26,%r22;\n" \
+ "mov.u32 %retval,%r26;\n" \
+ "st.param.u32 [%out_retval],%retval;\n" \
+ "ret;\n" \
+ "}\n" \
".visible .func (.param .u32 %out_retval) GOACC_get_num_threads\n" \
"{\n" \
".reg .u32 %retval;\n" \
gomp_load_plugin_for_device (struct gomp_device_descr *device,
const char *plugin_name)
{
- char *err = NULL, *last_missing = NULL;
+ const char *err = NULL, *last_missing = NULL;
int optional_present, optional_total;
/* Clear any existing error. */
#define DLSYM_OPT(f, n) \
do \
{ \
- char *tmp_err; \
+ const char *tmp_err; \
device->f##_func = dlsym (plugin_handle, "GOMP_OFFLOAD_" #n); \
tmp_err = dlerror (); \
if (tmp_err == NULL) \
_OIter
reverse_copy(_BIter, _BIter, _OIter);
- template<typename _FIter>
- _FIter
- rotate(_FIter, _FIter, _FIter);
+ inline namespace _V2
+ {
+ template<typename _FIter>
+ _FIter
+ rotate(_FIter, _FIter, _FIter);
+ }
template<typename _FIter, typename _OIter>
_OIter
{
if (__str._M_is_local())
{
- if (__str.length())
- traits_type::copy(_M_local_buf, __str._M_local_buf,
- _S_local_capacity + 1);
+ traits_type::copy(_M_local_buf, __str._M_local_buf,
+ _S_local_capacity + 1);
}
else
{
return __m;
}
+ inline namespace _V2
+ {
+
/// This is a helper function for the rotate algorithm.
template<typename _ForwardIterator>
_ForwardIterator
std::__iterator_category(__first));
}
+ } // namespace _V2
+
/**
* @brief Copy a sequence, rotating its elements.
* @ingroup mutating_algorithms
{
// Algorithm from http://www.unicode.org/faq/utf_bom.html#utf16-4
const char32_t LEAD_OFFSET = 0xD800 - (0x10000 >> 10);
- const char32_t SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
char16_t lead = LEAD_OFFSET + (codepoint >> 10);
char16_t trail = 0xDC00 + (codepoint & 0x3FF);
- char32_t utf16bytes = (lead << 10) + trail + SURROGATE_OFFSET;
-
- to.next[0] = adjust_byte_order(utf16bytes >> 16, mode);
- to.next[1] = adjust_byte_order(utf16bytes & 0xFFFF, mode);
+ to.next[0] = adjust_byte_order(lead, mode);
+ to.next[1] = adjust_byte_order(trail, mode);
to.next += 2;
return true;
}
return codecvt_base::partial;
if (codepoint > maxcode)
return codecvt_base::error;
- if (!write_utf16_code_point(to, codepoint, {}))
+ if (!write_utf16_code_point(to, codepoint, mode))
{
from.next = first;
return codecvt_base::partial;
{
range<const char> from{ __from, __from_end };
range<char16_t> to{ __to, __to_end };
- auto res = utf16_in(from, to);
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+ codecvt_mode mode = {};
+#else
+ codecvt_mode mode = little_endian;
+#endif
+ auto res = utf16_in(from, to, max_code_point, mode);
__from_next = from.next;
__to_next = to.next;
return res;